skip to Main Content

I want to bootstrap a new RDS cluster with a user and password while it’s being instantiated by Terraform.

I’ve created a Lambda and successfully configured a cluster with hardcoded variables. Here’s the Python:

import boto3
import psycopg2

user = ""
password = ""
host = ""
database = ""
role_user = ""
role_passwd = ""

def lambda_handler(event, context):
  connection = psycopg2.connect(f"user={user} password={password} host={host} dbname={database} port=5432")
  cursor = connection.cursor()
  cursor.execute(f"CREATE ROLE {role_user} WITH PASSWORD {role_passwd} CREATEDB CREATEROLE LOGIN ;")
  cursor.execute(f"GRANT rds_superuser TO {role_user} ;")
  print('Password applied')

I want to use Terraform’s ‘aws_lambda_invocation’ resource to inject the variables and I thought the code below would do the trick, but I am wrong.

resource "aws_lambda_invocation" "this" {
  function_name = aws_lambda_function.this.function_name
  input         = jsonencode({
    user        = jsondecode(data.aws_secretsmanager_secret_version.rds.secret_string)["username"]
    password    = jsondecode(data.aws_secretsmanager_secret_version.rds.secret_string)["password"]
    host        = data.aws_rds_cluster.this.endpoint
    database    = "postgres"
    role_user   = jsondecode(data.aws_secretsmanager_secret_version.role.secret_string)["username"]
    role_passwd = jsondecode(data.aws_secretsmanager_secret_version.role.secret_string)["password"]   
  })
}

I’m getting this error:

Error: invoking Lambda Function (bootstrap-modeler-hbmy-mct-joc-eu-west-1-dev): {"errorMessage": "name 'user' is not defined", "errorType": "NameError",

I’m new to Lambda and hoping there’s something dumb I’m missing that you can help me with.

2

Answers


  1. Chosen as BEST ANSWER

    Many thanks to Mark for pointing the way.

    import boto3
    import psycopg2
    
    def lambda_handler(event, context):
      connection = psycopg2.connect(user = event['user'],
                                    password = event['password'],
                                    host = event['host'])
      cursor = connection.cursor()
      cursor.execute(f"CREATE ROLE {event['role_user']} WITH PASSWORD '{event['role_passwd']}' CREATEDB CREATEROLE LOGIN;")
      cursor.execute(f"GRANT rds_superuser TO {event['role_user']};")
      cursor.close()
      connection.commit()
      print('Password applied')
    

  2. That’s not how AWS Lambda functions work. The input to an AWS Lambda function doesn’t directly update variables inside the Lambda function’s source code. Any input like that will be made available to the Lambda function invocation as attributes on the event object that is passed into the Lambda hander.

    I suggest printing the event object in your Lambda function, and then examining that in CloudWatch Logs to see exactly how you will need to access those values in your code.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search