Search code examples
pythonaws-lambdaterraform

Get the EC2 Id create by terraform and use it in a python script for the lambda


With terraform I want to create an EC2 and a lambda. The lambda will be use to start and stop this EC2. But to start the EC2 with a lambda I need a script where I specify the id of this instance. How can I extract the id the instance I create and add it to my python script ?

Create the instance:

resource "aws_instance" "app_server" {
  ami           = "ami-0ed752ea0f62749af"
  instance_type = "t2.micro"

  tags = {
    Name = "Instance_test"
  }
}

The lambda:

# GET AND CONVERT PYTON FILE TO ZIP
data "archive_file" "zipit_lambda_start" {
  type        = "zip"
  source_file = "index_lambda_start.py"
  output_path = "lambda_function_start.zip"
}
# GET THE ROLE 
module "role" {
source = "../IAM_POLICY_IAM_ROLE"
}
#CREATE LAMBDA
resource "aws_lambda_function" "lambda_start_ec2" {
  filename                       = "lambda_function_start.zip"
  function_name                  = "StartEC2Instance"
  role                           = module.role.role_lambda_test_arn
  handler                        = "index.lambda_handler"
  source_code_hash = "${data.archive_file.zipit_lambda_start.output_base64sha256}"
  runtime                        = "python3.9"
  timeout                        = 10
}

The python script export to the lambda to start the EC2:

import boto3
region = 'eu-west-1'
instances = ['i-0e6**********c3']
ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
    ec2.start_instances(InstanceIds=instances)
    print('started your instances: ' + str(instances))

enter image description here


Solution

  • To solve my problem by using the resource template file:

    First, export the instance Id as an Output:

    • EC2/main.tf:
    output "instance_id" {
      value = aws_instance.app_server.id
    }
    
    • In Lambda/main.tf, get the instance id with a module then add a resource made to create a python file from another file with variables as inputs. In this case the only input is instance_id.
    #GET THE EC2
    module "ec2" {
    source = "../EC2"
    }
    
    resource "local_file" "lambda_function" {
      content  = templatefile("${path.module}/index_lambda.py.tpl", { 
                                                                    instance_id = module.ec2.instance_id
                                                                    })
      filename = "${path.module}/index.py"
    }
    # GET AND CONVERT PYTON FILE TO ZIP   utiliser template file 
    data "archive_file" "zipit_lambda_start" {
      type        = "zip"
      source_file = local_file.lambda_function.filename
      output_path = "index.zip"
    }
    
    resource "aws_lambda_function" "lambda_start_ec2" {
      filename                       = data.archive_file.zipit_lambda_start.output_path
      function_name                  = "StartEC2Instance"
      role                           = module.role.role_lambda_test_arn
      handler                        = "index.lambda_handler"
      source_code_hash = "${data.archive_file.zipit_lambda_start.output_base64sha256}"
      runtime                        = "python3.9"
    
    
    • Now create the file for the source code, index_lambda.py.tpl, with our variable being instance_id:
    import boto3
    
    region = 'eu-west-1'
    instances = ["${instance_id}"]
    ec2 = boto3.client('ec2', region_name=region)
    
    def lambda_handler(event, context):
        ec2.start_instances(InstanceIds=instances)
        print('started your instances: ' + str(instances))
    
    

    I am able to create lambda index code with id of the EC2 created before.