1

I've been working with AWS since last night and today so please excuse my ignorance and lack of terminology.

I currently have an EC2 Instance running an Unreal Engine Dedicated Game Server and I'm able to connect to it as a Client.

This tells me I've setup the permissions and routing correctly since I'm able to SSH as well as connect and play the game remotely.

The current task is to create UI that shows a server list and I'm having a hard time understanding how I could troubleshoot why my call to ec2.describeInstances() from my Lambda function isn't working.

This is (one of the many variations) of the code I'm using:

let aws = require('aws-sdk');
let ec2 = new aws.EC2({apiVersion: '2016-11-15'});

aws.config.update({region: 'us-east-2'});

exports.handler = async function (event) {

  console.log("Describe Instance\n");

  await ec2.describeInstances({}, (e, data) => {
    console.log("Callback\n");
    e ? console.log(e) : console.log(data);
  });
};

I've been reading the documentation as well as previous questions and answers but it seems that some folks insist that you need a NAT while others say you only need a NAT if your Lambda function needs access to the internet.

However, your Lambda only needs access to the internet if it's attached to a VPC - but even if it's attached to be a VPC, I'm still able to call it remotely without setting up a NAT so I don't understand how that works.

Either way, my Lambda is not attached to a VPC nor does it need to be (as far as I understand) due to my EC2 being on a public subnet anyway so my Lambda should be able to see it and communicate with it.

Although, I'm assuming ec2.describeInstances will get ALL of my instances (at least that's what I'm hoping for). Does that mean I need to provide the Lambda with some global account access or something?

EDIT: The Lambda has the following Execution role permissions:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "EC2InstanceConnect",
            "Action": [
                "ec2:DescribeInstances",
                "ec2:DescribeVpcs",
                "ec2:DescribeRegions",
                "ec2:DescribeVolumes",
                "ec2:DescribeSubnets",
                "ec2:DescribeSecurityGroups",
                "ec2:CreateNetworkInterface",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DeleteNetworkInterface",
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Effect": "Allow",
            "Resource": [
                "*",
                "arn:aws:logs:*:*:*"
            ]
        }
    ]
}

EDIT 2: I threw up a quick node app and tried this and was able to successfully get the instances. Still working on trying to figure out why this same exact function call isn't working when being called from AWS Lambda.

import aws from "aws-sdk"

aws.config.update({
    credentials: new aws.Credentials("KEY", "SECRET"),
    region: 'us-east-2'
})

let ec2 = new aws.EC2();

ec2.describeInstances((err, data) => {
  err ? console.log(err) : console.log(data);
});

EDIT 3: I've created a test for my Lambda (within Lambda) and when executing it I can see my console log for Describe Instance as such - note that this is before ec2.describeInstances gets called:

enter image description here

This happens sporadically, but when I click Test again, I'm sometimes getting my EC2 instance data. However, it's not always the same output - sometimes the data is truncated in very odd places.

Here's an example of the latest test that successfully brought data back in a somewhat "full" manner. However, notice the console logs don't make any sense. Describe Instances is called BEFORE I call ec2.describeInstances yet the test Starts, prints Callback, prints the data from the callback, and then finally prints Describe Instance and Ends.

enter image description here

It's almost as if I'm getting this data from a previous call? Which doesn't make any sense but due to the weird log output, I'm a bit more confused than I was before! 😅

FINAL UPDATE: Thanks to Felix for the removal of the async tip - see answer below. Once I removed the async/await from my function, the Lambda started getting the EC2 data. However, the response was always null.

Felix provided this link and upon further reading it states that if your handler is NOT async, then you must use the callback to respond.

So here is what my Lambda looks like now and I was able to build a quick little UMG widget within Unreal and pull the data I needed.

Hope this helps someone in the future! 😊

let aws = require('aws-sdk');
let ec2 = new aws.EC2({apiVersion: '2016-11-15'});

// Callback is required for non-async handlers - without it the response is always "null"
exports.handler = function (event, context, callback) {

  aws.config.update({region: event.region});

  ec2.describeInstances((e, data) => {
    
    if (e) callback(e, {}); // return the error and an empty object
    
    else {
      
      // build your response object based on the data you get back
      // in this case, I just want the ip to my single instance but this will be updated to include more info
      let response = {
        ip: data.Reservations[0].Instances[0].PublicIpAddress
      };

      callback(null, response); // return null for "error" and our response object as a response
    }
  });
};
2
  • 1
    First, you are on the right track - so don't worry about being new and all that stuff. Second, the fact that you can SSH to the instance seems irrelevant to your question. describe-instances doesn't connect to the instance - it only shows a list of instances. Finally, what is the error that you are getting? Commented Jul 28, 2022 at 4:47
  • Thanks Felix. I'm not getting an error at all, the ec2.describeInstances method in my Lambda doesn't seem to be running. The console.log("Describe Instance") prints out in the logs but the console.log("Callback") isn't being printed. I'm assuming it's a permissions issue somewhere but I'm not sure yet. I found logs within CloudWatch but there's nothing in regards to Lambda permissions, credentials, etc. or any other helpful info. I just see my one console.log("Describe Instances") and that's it. Commented Jul 28, 2022 at 6:57

1 Answer 1

1

I am looking at my examples - and invocation of ec2.describeInstances() is not asynchronous. In other words, try

exports.handler = async function (event) {

  console.log("Describe Instance\n");

  ec2.describeInstances({}, (e, data) => {
    console.log("Callback\n");
    e ? console.log(e) : console.log(data);
  });
};

before you go any further. In fact I would try non-async handler as described here.

Sign up to request clarification or add additional context in comments.

2 Comments

Oh man... my last edit should have been a major clue.. haha! 😅 I can finally sleep in peace knowing the last 12 hours didn't fully go to waste today. Thank you so much Felix! 😁
yes, it gave me a clue as well! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.