Search code examples
amazon-web-servicesvariableslambdauser-data

How can I pass AWS lambda environement variable into userdata script (script will fire during ec2 spinup)


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

Solution

  • 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'