Lauch of EC2 Intance and attach to Target Group using Lambda - amazon-web-services

I am trying to launch EC2 instance and attachig to Target group using following code in lambda function But i am getting following error. But lambda funciton not getting Intsance ID and giving and error, please guide
Error is:
An error occurred (ValidationError) when calling the RegisterTargets operation: Instance ID 'instance_id' is not valid",
"errorType": "ClientError",
Code is :
import boto3
import json
import time
import os
AMI = 'ami-047a51fa27710816e'
INSTANCE_TYPE = os.environ['MyInstanceType']
KEY_NAME = 'miankeyp'
REGION = 'us-east-1'
ec2 = boto3.client('ec2', region_name=REGION)
def lambda_handler(event, context):
instance = ec2.run_instances(
ImageId=AMI,
InstanceType=INSTANCE_TYPE,
KeyName=KEY_NAME,
MaxCount=1,
MinCount=1
)
print ("New instance created:")
instance_id = instance['Instances'][0]['InstanceId']
print (instance_id)
client=boto3.client('elbv2')
time.sleep(5)
response = client.register_targets(
TargetGroupArn='arn:aws:elasticloadbalancing:us-east-1::targetgroup/target-demo/c46e6bfc00b6886f',
Targets=[
{
'Id': 'instance_id'
},
]
)

To wait until an instance is running, you can use an Instance State waiter.
This is a boto3 capability that will check the state of an instance every 15 seconds until it reaches the desired state, up to a limit of 40 checks, which allows 10 minutes.

Related

Return FilesystemID after cloudformation stack deployment complete

i am trying to create efs filesystem using cloudformation template inside lambda using boto3. And interested to return output as Filesystemid from stack using describe_stack. however i am getting null values in return. please suggest where i am making mistake.
error is:
Response
null
Code is:
import boto3
import time
import json
import botocore
datetime = time.strftime("%Y%m%d%H%M%S")
stackname = 'My-EFS'
region = "ap-south-1"
client = boto3.client('cloudformation')
s = boto3.Session(region_name=region)
def lambda_handler(event, context):
response = client.create_stack(
StackName= stackname,
TemplateURL='https://cloudnaeem.s3.amazonaws.com/efs.yaml',
)
waiter = client.get_waiter('stack_create_complete')
res = waiter.wait(
StackName=stackname,
)
stack = client.describe_stacks(StackName=stackname)
FileSystem_id=None
for v in stack["Stacks"][0]["Outputs"]:
if v["OutputKey"] == "FileSystemId":
FileSystem_id = v["OutputValue"]
return FileSystem_id
template output is :
Outputs:
EFS:
Description: The created EFS
Value: !Ref EFSFileSystem
Your output is called EFS but you are looking for FileSystemId. Your code should be thus:
for v in stack["Stacks"][0]["Outputs"]:
if v["OutputKey"] == "EFS":
FileSystem_id = v["OutputValue"]

Trying to run a Lambda function to invoke ssm and define a EC2 tag to push the same on multiple instance

Trying to run a Lambda function to invoke SSM and define an EC2 tag to push the same on multiple instances with the below script. Getting the below error when trying to execute. I am just started learning to write a script and using aws lambda first time. Please help me to fix.
import boto3
ssm = boto3.client('ssm')
ec2 = boto3.resource('ec2')
def lambda_handler(event, context):
filters = (
Name = 'tag:Product',
Values = ['Essay']
)
instances = ('filters')
response = ssm.send_command(
InstanceIds=instances,
DocumentName='xxxxxxxxxxxxx',
DocumentVersion='$DEFAULT',
DocumentHash='916fdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdcdbe7940',
DocumentHashType='Sha256'
)
print(response)
Error :
Response:
{
"errorMessage": "Syntax error in module 'lambda_function': invalid syntax (lambda_function.py, line 7)",
"errorType": "Runtime.UserCodeSyntaxError",
"stackTrace": [
" File \"/var/task/lambda_function.py\" Line 7\n Name = 'tag:Product',\n"
]
}
Request ID:
"8cb4cd39-b744-41da-befb-5f60b6e49fa4"
Function logs:
START RequestId: 8cb4cd39-b744-41da-befb-5f60b6e49fa4 Version: $LATEST
[ERROR] Runtime.UserCodeSyntaxError: Syntax error in module 'lambda_function': invalid syntax (lambda_function.py, line 7)
Traceback (most recent call last):
  File "/var/task/lambda_function.py" Line 7
            Name = 'tag:Product',END RequestId: 8cb4cd39-b744-41da-befb-5f60b6e49fa4
REPORT RequestId: 8cb4cd39-b744-41da-befb-5f60b6e49fa4
There are several issues:
Wrong indentation.
There is no such thing in python as
filters = (
Name = 'tag:Product',
Values = ['Essay']
)
maybe you meant dictionary?:
filters = {
'Name':'tag:Product',
'Values': ['Essay']
}
InstanceIds=instances should be a list of strings, not a literal string of 'filters'.
The closes to fixing the code is the following:
import boto3
ssm = boto3.client('ssm')
ec2 = boto3.resource('ec2')
def lambda_handler(event, context):
filters = [{
'Name':'tag:Product',
'Values': ['Essay']
}]
instances = [instance.id for instance in ec2.instances.filter(Filters = filters)]
response = ssm.send_command(
InstanceIds=instances,
DocumentName='xxxxxxxxxxxxx',
DocumentVersion='$DEFAULT',
DocumentHash='916fdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdcdbe7940',
DocumentHashType='Sha256'
)
print(response)

How to change termination protection by boto3

I want to teminate many AWS ec2 instance,then i use boto3 like this:
#!/usr/bin/env python
#coding=utf8
import boto3
ec2 = boto3.resource(
'ec2',
aws_access_key_id="<AK>",
aws_secret_access_key="<SK>",
region_name='eu-central-1'
)
instances = ec2.instances.filter(
Filters=[{'Name': 'instance-state-name', 'Values': ['stopped']}])
ids = ['id1','id2'.....'idn']
status = ec2.instances.filter(InstanceIds=ids).terminate()
print(status)
But I got a ERROR:
botocore.exceptions.ClientError: An error occurred (OperationNotPermitted) when calling the TerminateInstances operation: The instance 'i-0f06b49c1f16dcfde' may not be terminated. Modify its 'disableApiTermination' instance attribute and try again.
please tell me how to modify the disableApiTermination.
Use modify_attribute. See the documentation.
import boto3
ec2 = boto3.resource('ec2')
instances = ec2.instances.filter(
Filters=[{'Name': 'instance-state-name', 'Values': ['stopped']}])
for instance in instances:
print(instance.id)
# after choosing the instances to terminate:
ids = ['id1', 'id2']
for id in ids:
ec2.Instance(id).modify_attribute(
DisableApiTermination={
'Value': False
})
ec2.Instance(id).terminate()
Adding to previous answer, you can also use the following method from client module
client.modify_instance_attribute(InstanceId='string',Attribute="disableApiTermination",Value='True|False'

Iteration not working in Lambda as I want to run lambda in two regions listed in code

Hi I have this simple lambda function which stops all EC-2 instances tagged with Auto_off. I have set a for loop so that it works for two regions us-east-1 and us-east-2. I am running the function in us-east-2 region.
the problem is that only the instance located in us-east2 is stopping and the other instance is not(located in us-east-1). what modifications can i make.
please suggest as i am new to python and boto library
import boto3
import logging
#setup simple logging for INFO
logger = logging.getLogger()
logger.setLevel(logging.INFO)
#define the connection
ec2 = boto3.resource('ec2')
client = boto3.client('ec2', region_name='us-east-1')
ec2_regions = ['us-east-1','us-east-2']
for region in ec2_regions:
conn = boto3.resource('ec2',region_name=region)
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 to see here"
You are creating 2 instances of ec2 resource, and 1 instance of ec2 client. You are only using one instance of ec2 resource, and not using the client at all. You are also setting the region in your loop on a different resource object from the one you are actually using.
Change all of this:
ec2 = boto3.resource('ec2')
client = boto3.client('ec2', region_name='us-east-1')
ec2_regions = ['us-east-1','us-east-2']
for region in ec2_regions:
conn = boto3.resource('ec2',region_name=region)
To this:
ec2_regions = ['us-east-1','us-east-2']
for region in ec2_regions:
ec2 = boto3.resource('ec2',region_name=region)
Also your indentation is all wrong in the code in your question. I hope that's just a copy/paste issue and not how your code is really indented, because indentation is syntax in Python.
The loop you do here
ec2_regions = ['us-east-1','us-east-2']
for region in ec2_regions:
conn = boto3.resource('ec2',region_name=region)
Firstly assigns us-east-1 to the conn variable and on the second step, it overwrites it with us-east-2 and then it enters your function.
So what you can do is put that loop inside your function and do the current definition of the function inside that loop.

boto3 can't delete AWS tags

boto3 mentioned on Github that they added support for deleting tags. However, when I execute the code below, it throws an exception:
ec2 = boto3.resource('ec2', region_name=aws_region)
ec2.delete_tags(Resources=[instance.id],Tags=[{"Key": non_compliant_tag_name}])
'ec2.ServiceResource' object has no attribute 'delete_tags'
$ pip show boto3
Name: boto3
Version: 1.4.4
What am I doing wrong?
The delete_tags() method should be called on a client object rather than a resource object:
import boto3
client = boto3.client('ec2', region_name='ap-southeast-2')
...
client.delete_tags(Resources=[instance.id],Tags=[{"Key": non_compliant_tag_name}])
You can use it as follows in Python
import boto3
reservations = ec2.describe_instances(
Filters=[
#{'Name': 'tag:Type', 'Values': ['management']},
]
).get(
'Reservations', []
)
instances = sum(
[
[i for i in r['Instances']]
for r in reservations
], [])
for instance in instances:
# Delete the tag 'baz' if it exists
ec2.delete_tags(Resources=[instance['InstanceId']], Tags=[{"Key": "TAGNAME"}])