skip to Main Content

Ultimately, I’d like to have an extra feature in my app if the app is running on AWS EC2.

How do I check and set a variable to indicate if it is on AWS or not? I found this thread to do the check, but upon startup how do I set a variable across the app like a boolean? Something like:

let checkAWS;

metadata.isEC2().then(function (onEC2) {
  checkAWS = true;
  console.log("EC2: "  + onEC2);
});

let app = express();
app.locals.isAWS = checkAWS;
console.log(checkAWS);

Every time, I always get the same output:

undefined
EC2: true

I am using the isAWS variable in my .ejs file to decide on that functionality.

2

Answers


  1. Chosen as BEST ANSWER

    For future reference in case anyone else is looking, this is what worked for me in order to be able to tell if you are running on AWS.

    let isAwsSet = false; //has the app checked whether it is running on AWS by setting app.locals.isAWS
    app.locals.isAWS = false;
    
    app.get('/home', function(request, response) {
    
      if (!isAwsSet){
        urlExists().then(function (onAWS){
          app.locals.isAWS = true;
          isAwsSet = true;
          response.render('home');
        }).catch(function(error){
            app.locals.isAWS = false;
            isAwsSet = true;
            response.render('home');
        })
      } else {
        response.render('home');
      }
    });
    
    function urlExists() {
      return new Promise((resolve, reject) => {
        //https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html
        const options = {
          method: 'HEAD',
          host: '169.254.169.254',
          path: '/latest/meta-data/',
          port: 80,
          timeout: 1500
        };
    
        const req = http.request(options, (res) => {
          // reject on bad status
          if (res.statusCode !== 200) {
              return reject(new Error('statusCode=' + res.statusCode));
          }
          resolve(res.statusCode = 200);
        });
    
        req.on('timeout', () => {
            req.destroy();
        });
    
        req.on('error', function(err) {
          reject(err);
        });
    
        req.end();
      });
    }
    

  2. metadata.isEC2() is asynchronous so its value is available some time later when the .then() handler runs. Meanwhile, you’re trying to use the value of checkAWS BEFORE that .then() handler has run.

    Since you want access to that value before you start your Express sever, you could only start it inside the .then() handler like this:

    let isAWS;
    metadata.isEC2().then(function (onEC2) {
      console.log("EC2: "  + onEC2);
      isAWS = true;
    }).catch(err => {
      isAWS = false;
    }).finally(err => {
      const app = express();
      app.locals.isAWS = isAWS;
    
      // do the rest of your app initialization here
    
      app.listen(...);
    
    });
    
    // do not use app here (it won't be defined here)
    

    If you’re trying to export app for other modules to use, you will have to take a slightly different approach. We’d have to see your broader code context to know what to recommend for that. But, basically the idea here is that you shouldn’t start your server until you have the asynchronously retrieved isAWS result.

    Also, you should know that with that metadata.isEC2() call you’re using, that looks for a known endpoint in an EC2 instance to detect EC2. If that endpoint does not exist, then this will take 500ms to timeout and hit the .catch() branch above. If it is an EC2 instance, it will be quick.


    Note, it might be simpler to just check for the presence of some environment variables that are automatically set by the AWS environment such as AWS_REGION or AWS_EXECUTION_ENV. Those can be checked for synchronously.

    let app = express();
    app.locals.isAWS = !!process.env.AWS_REGION;;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search