How to pass userdata script on lambda python while launching ec2 instance? - python

I am trying to launch instance using aws lambda using python, but I cannot pass my base64 encoded userdata script.
The script looks like this:
import os
import boto3
AMI = "ami-052efd3df9dad4825"
INSTANCE_TYPE = "c6a.32xlarge"
ec2 = boto3.resource('ec2')
def lambda_handler(event, context):
instance = ec2.create_instances(
ImageId=AMI,
InstanceType=INSTANCE_TYPE,
MaxCount=1,
MinCount=1,
UserData=*my script here*,
)
print("New instance created:", instance[0].id)

You should be able to specify it without needing to base64 encode it, such as:
user_data = '''
#!/bin/bash
echo 'test' > /home/ec2/test.txt
'''
Make sure the first line starts with a #!.
See also: EC2 User Data not working via python boto command (It's old, but shows examples.)

Related

boto3 lambda script to shutdown RDS not working

I'm just starting out with boto3 and lambda and was trying to run the below function via Pycharm.
import boto3
client = boto3.client('rds')
response = client.stop_db_instance(
DBInstanceIdentifier='dummy-mysql-rds'
)
But i receive the below error:
botocore.errorfactory.DBInstanceNotFoundFault: An error occurred (DBInstanceNotFound) when calling the StopDBInstance operation: DBInstance dummy-mysql-rds not found.
Do you know what may be causing this?
For the record, I have the AWS toolkit installed for Pycharm and can run simple functions to list and describe ec2 instances and my AWS profile has admin access.
By explicitly defining the profile name the below function now works via Pycharm. Thank you #OleksiiDonoha for your help in getting this resolved.
import boto3
rds = boto3.setup_default_session(profile_name='dev')
client = boto3.client('rds')
response = client.stop_db_instance(
DBInstanceIdentifier='dev-mysql-rds'
)

Send command to Amazon EC2 instance using Boto3 in Python

I am able to create an instance from an image on Amazon EC2 using boto3 using the following code:
ec2 = boto3.client('ec2',region_name = 'eu-west-2')
instance = ec2.run_instances(
ImageId='ami-011c936382e4e2g9c',
MinCount=1,
MaxCount=1,
InstanceType = 't2.micro',
SecurityGroupIds= ['sg-0c08ad7b130e3hf3',],)
id = str(instance['Instances'][0]['InstanceId'])
This works fine, but I then wish to send a simple command to the instance which will execute a python script stored on the instance. From what I can gather, boto3 has the AWS command line functionality built in and so I shouldn't have to SSH to the instance; I should be able to send a command through boto3. However I'm strugging to do this, after trying different variations of the below code:
client = boto3.client('ssm',region_name='eu-west-2')
commands = ['echo "hello world" > hello.txt'] #this would be replaced by the command to execute the python script
instance_id = [id] #id being the instance id established from above
response = client.send_command(DocumentName='AWS-RunShellScript',
Parameters= 'commands':commands},
InstanceIds=instance_id,)
I'm aware that it takes time for the server to fire up etc but this isn't the problem. I have executed this second chunk of code after a large delay when I know the server is indeed ready to go.
As mentioned, I think this might be to do with the pem file that I normally need to use in order to putty/ssh into an instance as this isn't configured anywhere into my code. Any clues would be greatly appreciated!

Is there a way for a Python script to "recognize" which EC2 instance it is running on?

Let's say that my script is running on an EC2 instance named ec2-test1 and it communicates with an S3 bucket named: s3-bucket-test1, but when the script is ran on ec2-test2 it's able to identify the EC2 instance it is currently running on and change the directory to reference s3-bucket-test2. Is there a way to do that? I know that for internal paths you can use os.path.dirname(os.path.realpath(__file__)) but was wondering if there is a way to do something like that for EC2 instance name in Python?
Use the following Boto3 to get the current instance name. Warning: No exception handling is included.
import boto3
import os
def get_inst_name():
# Get Instance ID from EC2 Instance Metadata
inst_id = os.popen("curl -s http://169.254.169.254/latest/meta-data/instance-id").read()
# Get EC2 instance object
ec2 = boto3.resource('ec2')
inst = ec2.Instance(inst_id)
# Obtain tags associated with the EC2 instance object
for tags in inst.tags:
if tags["Key"] == 'Name':
#print tags["Value"]
return tags["Value"]
Get the instance id from metadata server
Use the instance id to query Boto3 resource

How to create an ec2 instance using boto3

Is it possible to create an ec2 instance using boto3 in python?
Boto3 document is not helping here, and I couldn't find any helping documents online. please provide some sample codes/links.
The API has changed but it's right there in the documentation
# Boto 3
ec2.create_instances(ImageId='<ami-image-id>', MinCount=1, MaxCount=5)
Link to the documentation:
http://boto3.readthedocs.org/en/latest/guide/migrationec2.html#launching-new-instances
You can run the code I used from the boto3 docs. You can add or remove parameters as per your requirements, but this is what you would normally require:
import boto3
client = boto3.client('ec2', region_name='us-west-2')
response = client.run_instances(
BlockDeviceMappings=[
{
'DeviceName': '/dev/xvda',
'Ebs': {
'DeleteOnTermination': True,
'VolumeSize': 8,
'VolumeType': 'gp2'
},
},
],
ImageId='ami-6cd6f714',
InstanceType='t3.micro',
MaxCount=1,
MinCount=1,
Monitoring={
'Enabled': False
},
SecurityGroupIds=[
'sg-1f39854x',
],
)
The link you're really looking for in the documentation is the create_instances() method of the ServiceResource object. This is the type of object you are calling if you create an EC2 resource like this:
s = boto3.Session(region_name="us-west-1")
ec2 = s.resource('ec2')
...
instance = ec2.create_instances(**y_kwargs)
This contains a more detailed example and a longer list of available parameters.
You can also get parameter values for AWS instances that are already running using the AWS command line interface:
$ aws ec2 describe-instances
This prints out a JSON file from which relevant parameters can be extracted and passed to the create_instances() method. (Or, you can use a boto client and call the describe_instances() method.)
(Note: If you're wondering what the difference is between the Client and the Resource, they serve different purposes for the same end - the client is a lower-level interface while the Resource is a higher-level interface.)
Refer to API docs has all available options to create instance
http://boto3.readthedocs.org/en/latest/reference/services/ec2.html#EC2.Subnet.create_instances
If your running from your windows computer you need configure AWS Cli with proper EC2 permisssion to launch instance.
#
import boto3
ec2 = boto3.resource('ec2')
instance = ec2.create_instances(
ImageId='ami-5eb63a32',
MinCount=1,
MaxCount=1,
InstanceType='t2.micro',
)
print(instance[0].id)

Python Boto3: set session, create an EC2 instance and run command using csdshell

I need to write a python script using boto3 which does the following,
set aws access & secret key for my session
then create an ec2 instance (using ami image)
execute a command in newly created ec2 instance
Its not really difficult, what you are asking is mostly covered on boto3 docs.
For creating a new t2.micro on us-east-1a running ubuntu 14.04. You should be able to do it like this :
# latest ubuntu ami
ami_id = 'ami-5189a661'
# define userdata to be run at instance launch
userdata = """#cloud-config
runcmd:
- touch /home/ubuntu/heythere.txt
"""
conn_args = {
'aws_access_key_id': 'YOURKEY',
'aws_secret_access_key': 'YOUSECACCESSKEY',
'region_name': 'us-east-1'
}
ec2_res = boto3.resource('ec2', **conn_args)
new_instance = ec2_res.create_instances(
ImageId=ami_id,
MinCount=1,
MaxCount=1,
UserData=userdata,
InstanceType='t2.micro'
)
print new_instance.id

Categories

Resources