skip to Main Content

This code does not throw any errors, just shows me an empty answer:

import os
import boto3

ec2 = boto3.resource('ec2',region)

for ins in ec2.instances.all():
        ip = ins.private_ip_address
        state_name = ins.state['Name']
        print("ip:{}, state:{}".format(ip, state_name))

Cloudwatch says nothing too. I tried to add try/catch, but no luck…nothing.

VPC is common for EC2 instances and lambda, lambda is binded to private subnets and has the same security group as EC2 instance.

https://policysim.aws.amazon.com/ says me that the assigned role is working with EC2 well. Probably i missed smth in configuration but how to find out whats wrong?

Update:

to avoid confusion, I’m providing here the full code:

import os
import boto3

def get_ec2_instances(region, project, state):
    ec2_instances = []
    ec2 = boto3.resource('ec2', region_name=region)
    
    filters = [
        {
            'Name': 'tag:project',
            'Values': [project]
        },
        {
            'Name': 'instance-state-name',
            'Values': [state]
        }
    ]
    
    for ins in ec2.instances.all():
        ip = ins.private_ip_address
        state_name = ins.state['Name']
        print("ip:{}, state:{}".format(ip, state_name)) // is not printing already
        
    for instance in ec2.instances.filter(Filters=filters):
        ip = instance.private_ip_address
        state_name = instance.state['Name']
        print("ip:{}, state:{}".format(ip, state_name))
        ec2_instances.append(instance)
    
    return ec2_instances
    
def start_ec2_instance(region, project):
    instances_to_start = get_ec2_instances(region, project, 'stopped')
    instance_state_changed = 0
    for instance in instances_to_start:
        instance.start()
        instance_state_changed += 1
    return instance_state_changed
    
def stop_ec2_instance(region, project):
    instances_to_stop = get_ec2_instances(region, project, "running")
    instance_state_changed = 0
    for instance in instances_to_stop:
        instance.stop()
        instance_state_changed += 1
    return instance_state_changed

def describe_ec2_instances(region, project):
    instances = get_ec2_instances(region, project, "running")
    for instance in instances:
        print("Instance ID: {}, IP: {}, State: {}".format(instance.id, instance.private_ip_address, instance.state['Name']))
        
def lambda_handler(event, context):
    region = os.getenv('REGION', 'eu-central-1')
    project = os.getenv('PROJECT', 'ec2-instance')
    instance_state_changed = 0

    if event.get('action') == 'start':
        instance_state_changed = start_ec2_instance(region, project)
    elif event.get('action') == 'stop':
        instance_state_changed = stop_ec2_instance(region, project)
    elif event.get('action') == 'describe':
        describe_ec2_instances(region, project)
        
    return instance_state_changed

And this is the output that i have on the function running:

Test Event Name
Start

Response
{
  "errorMessage": "2023-06-16T16:17:37.510Z 75118795-2ffd-46ab-84e6-.... Task timed out after 3.02 seconds"
}

Function Logs
START RequestId: 75118795-2ffd-46ab-84e6-... Version: $LATEST
2023-06-16T16:17:37.510Z 75118795-2ffd-46ab-84e6-... Task timed out after 3.02 seconds

END RequestId: 75118795-2ffd-46ab-84e6-...
REPORT RequestId: 75118795-2ffd-46ab-84e6-...   Duration: 3018.80 ms    Billed Duration: 3000 ms    Memory Size: 128 MB Max Memory Used: 83 MB  Init Duration: 293.49 ms

Request ID
75118795-2ffd-46ab-84e6-...

update 2 (for the @jarmods comment: )
enter image description here

2

Answers


  1. @jarmod is correct. A function handler is required is required for Lambda which makes sense because Lambdas are event-driven. You should be seeing an error that looks similar to this:

    {
      "errorMessage": "Handler 'lambda_handler' missing on module 'lambda_function'",
      "errorType": "Runtime.HandlerNotFound",
      "requestId": "14d7be4f-b8fd-4a42-b370-e0fe99309a94",
      "stackTrace": []
    }
    

    Your code was able to run properly after adding a function handler and granting the Lambda access to EC2:

    import os
    import boto3
    
    ec2 = boto3.resource('ec2')
    
    def lambda_handler(event, context):
            for ins in ec2.instances.all():
                    ip = ins.private_ip_address
                    state_name = ins.state['Name']
                    print("ip:{}, state:{}".format(ip, state_name))
    
    Login or Signup to reply.
  2. Your Lambda function’s request to the EC2 service to retrieve the list of EC2 instances is timing out.

    The typical reasons are either:

    1. your network connectivity is incorrect and your Lambda function has no network route to the EC2 service, or
    2. you have a lot of EC2 instances and the API request genuinely took longer to complete than your Lambda function timeout

    The typical cause of issue #1 is that you connected the Lambda function to your VPC unnecessarily and your network configuration is incorrect, either:

    1. you selected a public subnet but you have no VPC Endpoint to the EC2 service, or

    2. you selected a private subnet but your VPC has no internet connectivity (it has no IGW/NAT) and it has no VPC Endpoint to the EC2 service

    In your case, I believe the fix is to disconnect the Lambda function from your VPC (it’s not required) and increase your Lambda function timeout.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search