Initialize DB on Aurora Serverless with Data API enabled using CFN Custom Resource

TOC

Initializing Aurora Serverless DB with Data API enabled with CloudFormation custom resource

The following page shows how to enable the Data API for Aurora Serverless and connect to Aurora Server using the API.

あわせて読みたい
Connect Aurora Serverless from EC2/Lambda using Data API 【Enabling Aurora Serverless Data API and connecting from EC2 (AWS CLI) and Lambda (Boto3)】 The following pages cover the basics of Aurora Serverless. https...

In the above page, we manually performed the DB initialization process (table creation, test record addition) from an EC2 instance using the AWS CLI.
In this article, we will use CloudFormation custom resources to automate the initialization process.

Environment

Diagram of initialize DB on Aurora Serverless with Data API enabled using CloudFormation Custom Resource.

Basically, this is the same as the page introduced at the beginning of this article.

However, the following two points are different.

The first is the CloudFormation custom resource and Lambda function.
A function is associated with a custom resource and set to run when the stack is created.
The function’s function is to initialize the Aurora Serverless DB.
The runtime environment for the function is Python 3.8.

The second point does not deploy an EC2 instance.
As mentioned earlier, the Lambda function initializes the DB, so no instance is needed.
Since the instance is no longer needed, the VPC endpoints (for SSM and RDS Data) used by the instance will also not be created.

CloudFormation template files

The above configuration is built using CloudFormation.
The CloudFormation templates are located at the following URL

https://github.com/awstut-an-r/awstut-fa/tree/main/060

Explanation of key points of the template files

CloudFormation Custom Resource

First, check the Lambda function for custom resource.

Resources:
  Function2:
    Type: AWS::Lambda::Function
    Properties:
      Environment:
        Variables:
          DBCLUSTER_ARN: !Ref DBClusterArn
          DBNAME: !Ref DBName
          DBTABLE: !Ref DBTableName
          REGION: !Ref AWS::Region
          SECRET_ARN: !Ref SecretArn
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          import json
          import os

          dbcluster_arn = os.environ['DBCLUSTER_ARN']
          dbname = os.environ['DBNAME']
          dbtable = os.environ['DBTABLE']
          region = os.environ['REGION']
          secret_arn = os.environ['SECRET_ARN']

          sql1 = 'create table {table}(id varchar(200), type varchar(200), price float)'.format(table=dbtable)
          sql2 = 'insert into {table} values (111, "dog", 123)'.format(table=dbtable)
          client = boto3.client('rds-data', region_name=region)
          schema = 'mysql'

          CREATE = 'Create'
          response_data = {}

          def lambda_handler(event, context):
            try:
              if event['RequestType'] == CREATE:
                response1 = client.execute_statement(
                  database=dbname,
                  resourceArn=dbcluster_arn,
                  schema=schema,
                  secretArn=secret_arn,
                  sql=sql1
                )
                print(response1)

                response2 = client.execute_statement(
                  database=dbname,
                  resourceArn=dbcluster_arn,
                  schema=schema,
                  secretArn=secret_arn,
                  sql=sql2
                )
                print(response2)

              cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data)

            except Exception as e:
              print(e)
              cfnresponse.send(event, context, cfnresponse.FAILED, response_data)
      FunctionName: !Sub "${Prefix}-function2"
      Handler: !Ref Handler
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole.Arn
Code language: YAML (yaml)

Define the code in inline notation.
For more information, see the following page

あわせて読みたい
3 parterns to create Lambda with CloudFormation (S3/Inline/Container) 【Creating Lambda with CloudFormation】 When creating a Lambda with CloudFormation, there are three main patterns as follows. Uploading the code to an S3 buc...

Use the cfnresponse module to implement the function as a Lambda-backed custom resource.
For more information, please see the following page

あわせて読みたい
Introduction to CloudFormation Custom Resources 【Configuration to check behavior of CloudFormation Custom resources】 One of the features of CloudFormation is custom resources. Custom resources enable you...

The code is to create a client object for the Data API using Boto3.
Through the client object, initialize the Aurora Serverless DB by executing the following two SQL statements.
The first is an SQL statement to create a table.
The second is a statement to add test record.

Architecting

Using CloudFormation, we will build this environment and check the actual behavior.

Create CloudFormation stacks and check resources in stacks

Create CloudFormation stacks.
For information on how to create stacks and check each stack, please refer to the following page

あわせて読みたい
CloudFormation’s nested stack 【How to build an environment with a nested CloudFormation stack】 Examine nested stacks in CloudFormation. CloudFormation allows you to nest stacks. Nested ...

After checking the resources in each stack, information on the main resources created this time is as follows

  • Lambda function 1: fa-060-function1
  • Function URL for Lambda function 1: https://xv2pdk3gw3nncmvbb45pvabhji0gzlug.lambda-url.ap-northeast-1.on.aws/
  • Lambda function 2: fa-060-function2

The AWS Management Console also checks the creation status of CloudFormation custom resources.

Detail of CloudFormation Stack 1.
Detail of CloudFormation Stack 2.

You can see that the custom resource and Lambda function have been created successfully.

Checking Action

First, check the operation of the Lambda function for the CloudFormation custom resource.
Specifically, check the CloudWatch Logs log group of the function.

CloudWatch Logs of Lambda Function for CloudFormation Custom Resource.

We can see that two SQL statements were successfully executed.

We also see that the function returns “SUCCESS” as a CloudFormation custom resource.
This means that the function has successfully acted as a custom resource.

Now that we are ready, we can execute another Lambda function.
This function executes an SQL statement to retrieve data from Aurora Serverless.
The invocation of the function takes the form of accessing the Function URL.

Invocation of Lambda Function 1.

Successfully executed.
The records added by the function for the custom resource are displayed.
This shows that the custom resource was successfully created and the function was successfully executed.

Summary

We have seen how to automate the initialization process of Aurora Serverless DB using CloudFormation custom resources.

TOC