Home > Back-end >  How can I determine if my node js app is running on AWS at startup?
How can I determine if my node js app is running on AWS at startup?

Time:10-22

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

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.

CodePudding user response:

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;;

CodePudding user response:

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) {
  let status = healthStatus();

  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();
  });
}
  • Related