In my aws lambda/python script, I am intending to call a environment variable into my userdata script which will run during instance spinup, but I am facing issue passing environment variable into my user data script.
This code is bigger as I am running codepipeline, cloudformation, lambda , etc. What exactly you need to look is aws sns publish --topic-arn {} --message "echo $message" --region us-east-1 2>&1| tee sns.log
. I am trying to pass snstopic arn crated part of the cloudformation, I am able to pass that in the lambda env variable but that is not working in user data. Hence after my instance creation its uable to sned sns as "TopicArn" not able to passing actual arn for the sns topic in the above mentioned .
How can we pass variable from lambda to userdata if possible at all?
LambdaFunction:
DependsOn:
- "LambdaFunctionLogGroup"
Type: AWS::Lambda::Function
# Type: AWS::Serverless::Function
Properties:
Runtime: python3.9
FunctionName: VPC_Custom_Resource
Timeout: 60
# Handler: index.handler
Role: !GetAtt LambdaFunctionRole.Arn
Environment:
Variables:
SUBNET_ID: !Ref PublicSubnet1
Name: !Ref NameTagValue
INSTANCE_TYPE: t3.small
AMI: ami-0c4e4b4eb2e11d1d4
KEY_NAME: sudsark-dev
TopicArn: !Ref SNSTopic
InstanceProfile: !GetAtt Ec2InstanceProfile.Arn
InstanceProfileName: !Ref Ec2InstanceProfile
Handler: index.lambda_handler
Code:
ZipFile: |
#/usr/bin/env python3
import cfnresponse
import logging
import traceback
#lambda to luanch EC2
import boto3
import os
ec2 = boto3.resource('ec2')
import logging
#Start Logging
#lOGGER = logging.getLogger()
logger = logging.getLogger(__name__)
#LOGGER.setLevel(logging.INFO)
logging.getLogger().setLevel(logging.INFO)
#code block for Environment variable declaration which would be
INSTANCE_TYPE = os.environ['INSTANCE_TYPE'] #These will be environment variables that we must specify in lambda
KEY_NAME = os.environ['KEY_NAME']
AMI=os.environ['AMI']
SUBNET_ID=os.environ['SUBNET_ID']
TopicArn=os.environ['TopicArn']
Name=os.environ['Name']
InstanceProfile=os.environ['InstanceProfile']
InstanceProfileName= os.environ['InstanceProfileName']
topicarn=TopicArn
#code block for variable of user data
userData= ''' #!/bin/bash
cat << 'EOF' >> /tmp/connectiontest.sh
#!/bin/bash
echo "PINGTEST Result:"
echo "================================"
v=$(ping google.com -c 3)
w=$(ping google.com -c 3 | wc -l)
x=$(ping google.com -c 3 | sed -n 7p)
printf '%s\n' "TrafficStatus :" "$x"
echo "--------------------------------"
y=$(ping google.com -c 3 | awk '{if(NR==7) print $0}')
printf '%s\n' "TrafficStatus :" "$y"
if ping google.com -c 3 | grep -w "time=\|ms" 2>&1 ; then
echo " Ec2 is reachable to internet as ping to google.com is working fine"
else
echo "Ec2 is not rechable over icmp as ping to google.com is failing"
fi
echo "==========================================="
echo "Curl test result:"
echo "================="
if curl -I "https://google.com" 2>&1 | grep -w "200\|301" ; then
echo "Ec2 is reachable to Internet (https://google.com)"
else
echo "Ec2 is not reachable to Internet (https://google.com)"
fi
echo "========================================================"
EOF
sleep 1m
chmod x /tmp/connectiontest.sh
./tmp/connectiontest.sh >> /tmp/connectiontest.log
sleep 15
cd /tmp
message=$(<connectiontest.log)
sudo -i
aws sns publish --topic-arn {} --message "echo $message" --region us-east-1 2>&1| tee sns.log
'''
# Function to create Ec2 instance :
def lambda_handler(event, context): #Start of our function
subnet_id=SUBNET_ID
instance = ec2.create_instances(
InstanceType=INSTANCE_TYPE,
KeyName=KEY_NAME,
ImageId=AMI,
MaxCount=1,
MinCount=1,
NetworkInterfaces=[{
'DeviceIndex': 0,
'SubnetId': subnet_id,
'AssociatePublicIpAddress': True,
}],
IamInstanceProfile={
'Name': InstanceProfileName
},
UserData=userData,
TagSpecifications=[{ #This creates a tag for our resource
'ResourceType': 'instance',
'Tags': [{'Key': 'Name','Value': 'Dry-run'}]
}]
)
print("New instance created:", instance[0].id)
codepipeline = boto3.client('codepipeline')
job_id = event['CodePipeline.job']['id']
response = codepipeline.put_job_success_result(jobId=job_id)
return response
CodePudding user response:
I have update only userdata section
you just need to use python string formatting https://realpython.com/python-string-formatting/
userData= ''' #!/bin/bash
cat << 'EOF' >> /tmp/connectiontest.sh
#!/bin/bash
echo "PINGTEST Result:"
echo "================================"
v=$(ping google.com -c 3)
w=$(ping google.com -c 3 | wc -l)
x=$(ping google.com -c 3 | sed -n 7p)
printf '%s\n' "TrafficStatus :" "$x"
echo "--------------------------------"
y=$(ping google.com -c 3 | awk '{if(NR==7) print $0}')
printf '%s\n' "TrafficStatus :" "$y"
if ping google.com -c 3 | grep -w "time=\|ms" 2>&1 ; then
echo " Ec2 is reachable to internet as ping to google.com is working fine"
else
echo "Ec2 is not rechable over icmp as ping to google.com is failing"
fi
echo "==========================================="
echo "Curl test result:"
echo "================="
if curl -I "https://google.com" 2>&1 | grep -w "200\|301" ; then
echo "Ec2 is reachable to Internet (https://google.com)"
else
echo "Ec2 is not reachable to Internet (https://google.com)"
fi
echo "========================================================"
EOF
sleep 1m
chmod x /tmp/connectiontest.sh
./tmp/connectiontest.sh >> /tmp/connectiontest.log
sleep 15
cd /tmp
message=$(<connectiontest.log)
sudo -i
'''
userData = f'aws sns publish --topic-arn ${topicarn} --message "echo $message" --region us-east-1 2>&1| tee sns.log'