Lambda Function for 2 Different Launch Templates - amazon-web-services

So I have two different launch templates I am spinning up into 2 AZs. The code runs successfully, but only the first launch template "lt" runs successfully. Why is that?
import boto3
# I have called the EC2 resource
ec2 = boto3.resource('ec2')
# I have defined my launch template
lt = {
'LaunchTemplateName': 'My_Launch_Template',
'Version': '1'
}
lt_a = {
'LaunchTemplateName': 'My_Launch_Template_2',
'Version': '1'
}
# I have defined a function to execute
def lambda_handler(event, context):
instances = ec2.create_instances(
LaunchTemplate=lt,
MinCount=1,
MaxCount=1
)
def lambda_handler(event, context):
instances = ec2.create_instances(
LaunchTemplate=lt_a,
MinCount=1,
MaxCount=1
)

Your code isn't valid Python code. I suggest you review the basics of the language before you start implementing the function on AWS lambda. Get all of your code working on your local machine and once you're happy, move it to AWS.
Anyway, I would rewrite your code to have a helper function. This way you maximize code reuse (and you make your life easier):
import boto3
ec2 = boto3.resource('ec2')
def create_instance(launch_template_name, launch_template_id):
lt = {
'LaunchTemplateName': launch_template_name,
'Version': launch_template_id
}
return ec2.create_instanceS(
LaunchTemplate=lt,
MinCount=1,
MaxCount=1
)
def lambda_handler(event, context):
first_instance = create_instance('My_Launch_Template', '1')
second_instance = create_instance('My_Launch_Template_2', '1')
...

Related

How to get the list of Nitro system based EC2 instance type by CLI?

I know this page lists up the instance types which based on Nitro system but I would like to know the list in a dynamic way with CLI. (for example, using aws ec2 describe-instances). Is it possible to get Nitro based instance type other than parsing the static page? If so, could you tell me the how?
You'd have to write a bit of additional code to get that information. aws ec2 describe-instances will give you InstanceType property. You should use a programming language to parse the JSON, extract InstanceType and then call describe-instances like so: https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instance-types.html?highlight=nitro
From the JSON you get back, extract hypervisor. That'll give you Nitro if the instance is Nitro.
Here's a Python code that might work. I have not tested it fully but you can tweak this to get the results you want.
"""List all EC2 instances"""
import boto3
def ec2_connection():
"""Connect to AWS using API"""
region = 'us-east-2'
aws_key = 'xxx'
aws_secret = 'xxx'
session = boto3.Session(
aws_access_key_id = aws_key,
aws_secret_access_key = aws_secret
)
ec2 = session.client('ec2', region_name = region)
return ec2
def get_reservations(ec2):
"""Get a list of instances as a dictionary"""
response = ec2.describe_instances()
return response['Reservations']
def process_instances(reservations, ec2):
"""Print a colorful list of IPs and instances"""
if len(reservations) == 0:
print('No instance found. Quitting')
return
for reservation in reservations:
for instance in reservation['Instances']:
# get friendly name of the server
# only try this for mysql1.local server
friendly_name = get_friendly_name(instance)
if friendly_name.lower() != 'mysql1.local':
continue
# get the hypervisor based on the instance type
instance_type = get_instance_info(instance['InstanceType'], ec2)
# print findings
print(f'{friendly_name} // {instance["InstanceType"]} is {instance_type}')
break
def get_instance_info(instance_type, ec2):
"""Get hypervisor from the instance type"""
response = ec2.describe_instance_types(
InstanceTypes=[instance_type]
)
return response['InstanceTypes'][0]['Hypervisor']
def get_friendly_name(instance):
"""Get friendly name of the instance"""
tags = instance['Tags']
for tag in tags:
if tag['Key'] == 'Name':
return tag['Value']
return 'Unknown'
def run():
"""Main method to call"""
ec2 = ec2_connection()
reservations = get_reservations(ec2)
process_instances(reservations, ec2)
if __name__ == '__main__':
run()
print('Done')
In the above answer , the statement "From the JSON you get back, extract hypervisor. That'll give you Nitro if the instance is Nitro " is not longer accurate.
As per the latest AWS documentation,
hypervisor - The hypervisor type of the instance (ovm | xen ). The value xen is used for both Xen and Nitro hypervisors.
Cleaned up, verified working code below:
# Get all instance types that run on Nitro hypervisor
import boto3
def get_nitro_instance_types():
"""Get all instance types that run on Nitro hypervisor"""
ec2 = boto3.client('ec2', region_name = 'us-east-1')
response = ec2.describe_instance_types(
Filters=[
{
'Name': 'hypervisor',
'Values': [
'nitro',
]
},
],
)
instance_types = []
for instance_type in response['InstanceTypes']:
instance_types.append(instance_type['InstanceType'])
return instance_types
get_nitro_instance_types()
Example output as of 12/06/2022 below:
['r5dn.8xlarge', 'x2iedn.xlarge', 'r6id.2xlarge', 'r6gd.medium',
'm5zn.2xlarge', 'r6idn.16xlarge', 'c6a.48xlarge', 'm5a.16xlarge',
'im4gn.2xlarge', 'c6gn.16xlarge', 'c6in.24xlarge', 'r5ad.24xlarge',
'r6i.xlarge', 'c6i.32xlarge', 'x2iedn.2xlarge', 'r6id.xlarge',
'i3en.24xlarge', 'i3en.12xlarge', 'm5d.8xlarge', 'c6i.8xlarge',
'r6g.large', 'm6gd.4xlarge', 'r6a.2xlarge', 'x2iezn.4xlarge',
'c6i.large', 'r6in.24xlarge', 'm6gd.xlarge', 'm5dn.2xlarge',
'd3en.2xlarge', 'c6id.8xlarge', 'm6a.large', 'is4gen.xlarge',
'r6g.8xlarge', 'm6idn.large', 'm6a.2xlarge', 'c6i.4xlarge',
'i4i.16xlarge', 'm5zn.6xlarge', 'm5.8xlarge', 'm6id.xlarge',
'm5n.16xlarge', 'c6g.16xlarge', 'r5n.12xlarge', 't4g.nano',
'm5ad.12xlarge', 'r6in.12xlarge', 'm6idn.12xlarge', 'g5.2xlarge',
'trn1.32xlarge', 'x2gd.8xlarge', 'is4gen.4xlarge', 'r6gd.xlarge',
'r5a.xlarge', 'r5a.2xlarge', 'c5ad.24xlarge', 'r6a.xlarge',
'r6g.medium', 'm6id.12xlarge', 'r6idn.2xlarge', 'c5n.2xlarge',
'g5.4xlarge', 'm5d.xlarge', 'i3en.3xlarge', 'r5.24xlarge',
'r6gd.2xlarge', 'c5d.large', 'm6gd.12xlarge', 'm6id.2xlarge',
'm6i.large', 'z1d.2xlarge', 'm5a.4xlarge', 'm5a.2xlarge',
'c6in.xlarge', 'r6id.16xlarge', 'c7g.8xlarge', 'm5dn.12xlarge',
'm6gd.medium', 'im4gn.8xlarge', 'm5dn.large', 'c5ad.4xlarge',
'r6g.16xlarge', 'c6a.24xlarge', 'c6a.16xlarge']
"""List all EC2 instances"""
import boto3
def ec2_connection():
"""Connect to AWS using API"""
region = 'us-east-2'
aws_key = 'xxx'
aws_secret = 'xxx'
session = boto3.Session(
aws_access_key_id = aws_key,
aws_secret_access_key = aws_secret
)
ec2 = session.client('ec2', region_name = region)
return ec2
def get_reservations(ec2):
"""Get a list of instances as a dictionary"""
response = ec2.describe_instances()
return response['Reservations']
def process_instances(reservations, ec2):
"""Print a colorful list of IPs and instances"""
if len(reservations) == 0:
print('No instance found. Quitting')
return
for reservation in reservations:
for instance in reservation['Instances']:
# get friendly name of the server
# only try this for mysql1.local server
friendly_name = get_friendly_name(instance)
if friendly_name.lower() != 'mysql1.local':
continue
# get the hypervisor based on the instance type
instance_type = get_instance_info(instance['InstanceType'], ec2)
# print findings
print(f'{friendly_name} // {instance["InstanceType"]} is {instance_type}')
break
def get_instance_info(instance_type, ec2):
"""Get hypervisor from the instance type"""
response = ec2.describe_instance_types(
InstanceTypes=[instance_type]
)
return response['InstanceTypes'][0]['Hypervisor']
def get_friendly_name(instance):
"""Get friendly name of the instance"""
tags = instance['Tags']
for tag in tags:
if tag['Key'] == 'Name':
return tag['Value']
return 'Unknown'
def run():
"""Main method to call"""
ec2 = ec2_connection()
reservations = get_reservations(ec2)
process_instances(reservations, ec2)
if name == 'main':
run()
print('Done')

Return only instance ID, in Lambda using describe instance

I am running following script in lambda function to describe ec2 instance using tags. But in response I want only instance ID, whereas it retuns lot of info. please guide or anyother way to find out ec2 insatnce id using tags. Thanks
code is:
import boto3
import json
from collections import defaultdict
region = 'us-east-1'
def lambda_handler(event, context):
client = boto3.client('ec2')
running_instances = client.describe_instances(
Filters=[
{
'Name': 'tag:orgid',
'Values': [
'demoxx',
]
},
],
)
return json.loads(json.dumps(running_instances, default=str))
To get instance ids from describe_instances you have to iterate over Reservations, and then over Instances.
Thus, you code could be:
import boto3
import json
from collections import defaultdict
region = 'us-east-1'
def lambda_handler(event, context):
client = boto3.client('ec2')
running_instances = client.describe_instances(
Filters=[
{
'Name': 'tag:orgid',
'Values': [
'demoxx',
]
},
],
)
instance_ids = []
for reservation in running_instances['Reservations']:
for instance in reservation['Instances']:
instance_ids.append(instance['InstanceId'])
return instance_ids

AWS Lambda Stop EC2 but exclude two instances

We are looking for AWS Lambda Script to Stop all EC2 instances in a particular region expect two instances
First you need to add tags for the instances that you want to stop, for example, AutoStop tag and assign them with value True, and then run this code:
import boto3
import logging
#setup simple logging for INFO
logger = logging.getLogger()
logger.setLevel(logging.INFO)
#define the connection
ec2 = boto3.resource('ec2')
def lambda_handler(event, context):
# Use the filter() method of the instances collection to retrieve
# all running EC2 instances.
filters = [{
'Name': 'tag:AutoOff',
'Values': ['True']
},
{
'Name': 'instance-state-name',
'Values': ['running']
},
{
'Name': 'region',
'Values': ['us-east-1'] #replace it with your region
}
]
#filter the instances
instances = ec2.instances.filter(Filters=filters)
#locate all running instances
RunningInstances = [instance.id for instance in instances]
#print the instances for logging purposes
#print RunningInstances
#make sure there are actually instances to shut down.
if len(RunningInstances) > 0:
#perform the shutdown
shuttingDown = ec2.instances.filter(InstanceIds=RunningInstances).stop()
print shuttingDown
else:
print "Nothing to see here"

Lambda Script Update to Change Instance Size

I would like to update this script to stop this instance, make a backup, change the size and then restart the instance.
Basically I'm trying to mesh together three scripts. All say they are written in Python 2.7 but the syntax doesn't match up.
See the scripts below. Can I really just mash up these scripts? The first script looks like I would do something like this:
def lambda_handler(event, context):
ec2 = boto3.client('ec2', region_name=region)
ec2.change_instances(InstanceIds=instances)
print 'started your instances: ' + str(instances)
But I'm not even sure if that's the right syntax. Where in the second script says:
client.modify_instance_attribute(InstanceId=my_instance,
Attribute='instanceType', Value='m3.xlarge')
Obviously I would change the variable, but not sure if I need the def lamba_handler syntax.
Can you anyone point me in the right direction?
Script 1
import boto3
region = 'us-east-1'
instances = ['XXXXXXXXXXXXXXXXX']
def lambda_handler(event, context):
ec2 = boto3.client('ec2', region_name=region)
ec2.stop_instances(InstanceIds=instances)
print 'started your instances: ' + str(instances)
def lambda_handler(event, context):
ec2 = boto3.client('ec2', region_name=region)
ec2.start_instances(InstanceIds=instances)
print 'started your instances: ' + str(instances)
Script 2
client = boto3.client('ec2')
# Insert your Instance ID here
region = 'us-east-1'
instances = ['XXXXXXXXXXXXXXXXX']
# Stop the instance
client.stop_instances(InstanceIds=[instances])
waiter=client.get_waiter('instance_stopped')
waiter.wait(InstanceIds=[my_instance])
# Change the instance type
client.modify_instance_attribute(InstanceId=my_instance,
Attribute='instanceType', Value='m3.xlarge')
# Start the instance
client.start_instances(InstanceIds=[my_instance])
import boto3
region = 'us-east-1'
instances = ['XXXXXXXXXXXXXXXXX']
def lambda_handler(event, context):
ec2 = boto3.client('ec2', region_name=region)
ec2.stop_instances(InstanceIds=instances)
print 'started your instances: ' + str(instances)
waiter=ec2.get_waiter('instance_stopped')
waiter.wait(InstanceIds=[my_instance])
# Change the instance type
ec2.modify_instance_attribute(InstanceId=my_instance,
Attribute='instanceType', Value='m3.xlarge')
ec2.start_instances(InstanceIds=instances)
print 'started your instances: ' + str(instances)

Getting NULL output when running python job

I am running a python job in AWS Lambda to stop ec2 instances based on tags.
The script is running properly, but even if the script completes successfully, I am getting output "null" in the result returned by function execution.
Attached herewith is the python script. I am new to Python scripting. I am from ops side.
import boto3
import logging
#setup simple logging for INFO
logger = logging.getLogger()
logger.setLevel(logging.INFO)
#define the connection
ec2 = boto3.resource('ec2')
def lambda_handler(event, context):
# Use the filter() method of the instances collection to retrieve
# all running EC2 instances.
filters = [{
'Name': 'tag:AutoOff',
'Values': ['True']
},
{
'Name': 'instance-state-name',
'Values': ['running']
}
]
#filter the instances
instances = ec2.instances.filter(Filters=filters)
#locate all running instances
RunningInstances = [instance.id for instance in instances]
#print the instances for logging purposes
print RunningInstances
#make sure there are actually instances to shut down.
if len(RunningInstances) > 0:
#perform the shutdown
shuttingDown = ec2.instances.filter(InstanceIds=RunningInstances).stop()
print shuttingDown
else:
print "NOTHING"
In order to get response from the lambda you need to return something (usually a dictionary) from lambda_handler method. By default all Python methods return None type, that is why you do not receive any valuable response.
def lambda_handler(event, context):
... your code here ...
return {"turned_off": RunningInstances}
PS. it is preferred to use logging.debug|info|... method instead of print(). You can find more info in the documentation: https://docs.python.org/2.7/library/logging.html
Anyway all the output is saved to CloudWatch Logs. The Log Stream is created automatically when you create a Lambda function. You can find all your prints there for debugging.