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-...
2
Answers
@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:
Your code was able to run properly after adding a function handler and granting the Lambda access to EC2:
Your Lambda function’s request to the EC2 service to retrieve the list of EC2 instances is timing out.
The typical reasons are either:
The typical cause of issue #1 is that you connected the Lambda function to your VPC unnecessarily and your network configuration is incorrect, either:
you selected a public subnet but you have no VPC Endpoint to the EC2 service, or
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.