AWSTemplateFormatVersion: '2010-09-09' Resources: MySQLDatabase: Type: AWS::RDS::DBCluster Properties: DatabaseName: lookupnodejs EngineMode: serverless Engine: aurora-mysql EnableHttpEndpoint: TRUE MasterUserPassword: mysqlpassword MasterUsername: mysqluser ScalingConfiguration: MaxCapacity : 1 MinCapacity : 1 MySQLSecret: Type: AWS::SecretsManager::Secret Properties: Name: lookupnodejs Description: f-mysql-lookup-nodejs mysql secret SecretString: !Sub - '{ "username": "mysqluser", "password": "mysqlpassword", "host": "${Host}" }' - { Host: !GetAtt [ MySQLDatabase, Endpoint.Address ] } InitRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: / Policies: - PolicyName: CloudwatchLogs PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: logs:CreateLogGroup Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*" - Effect: Allow Action: - logs:CreateLogStream - logs:PutLogEvents Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*" - Effect: Allow Action: rds-data:ExecuteStatement Resource: !Sub "arn:aws:rds:${AWS::Region}:${AWS::AccountId}:cluster:*" - Effect: Allow Action: secretsmanager:GetSecretValue Resource: !Sub "arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:*" InitFunction: Type: AWS::Lambda::Function Properties: Role: !GetAtt 'InitRole.Arn' Handler: index.handler Runtime: python3.9 Timeout: 30 Code: ZipFile: | import boto3, json, urllib3 http = urllib3.PoolManager() rdsdata = boto3.client('rds-data') def send(event, context, responseStatus, responseData): responseUrl = event['ResponseURL'] responseBody = { 'Status' : responseStatus, 'Reason' : "See the details in CloudWatch Log Stream: {}".format(context.log_stream_name), 'PhysicalResourceId' : context.log_stream_name, 'StackId' : event['StackId'], 'RequestId' : event['RequestId'], 'LogicalResourceId' : event['LogicalResourceId'], 'NoEcho' : False, 'Data' : responseData } json_responseBody = json.dumps(responseBody) headers = { 'content-type' : '', 'content-length' : str(len(json_responseBody)) } try: response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody) except Exception as e: print("send(..) failed executing http.request(..):", e) def handler(event, context): print("Received event: " + json.dumps(event, indent=2)) if event['RequestType'] == 'Delete': send(event, context, 'SUCCESS', {'Data': 'Delete complete'}) else: try: secretArn = event['ResourceProperties']['SecretArn'] resourceArn = event['ResourceProperties']['ResourceArn'] sql="drop table if exists customers;" rdsdata.execute_statement(database='lookupnodejs', sql=sql, resourceArn=resourceArn, secretArn=secretArn); sql="create table customers(id varchar(10), fname varchar(100), lname varchar(100));" rdsdata.execute_statement(database='lookupnodejs', sql=sql, resourceArn=resourceArn, secretArn=secretArn); sql="insert into customers values ('1','John','Doe'),('2','Jane','Doe'),('3','Carlos','Salazar'),('4','Diego','Ramirez'),('5','Mary','Major'),('6','Richard','Roe');" rdsdata.execute_statement(database='lookupnodejs', sql=sql, resourceArn=resourceArn, secretArn=secretArn); send(event, context, 'SUCCESS', {'Data': 'Insert complete'}) except Exception as e: print(e) send(event, context, 'FAILED', {'Data': 'Insert failed'}) InitializeMySQLDB: Type: Custom::InitFunction DeletionPolicy: Retain DependsOn: MySQLDatabase Properties: ServiceToken: Fn::GetAtt: [ InitFunction , "Arn" ] SecretArn: !Ref MySQLSecret ResourceArn: !Sub - 'arn:aws:rds:${AWS::Region}:${AWS::AccountId}:cluster:${db}' - { db: !Ref MySQLDatabase}