This is the easy-to-run maintenance free AWS Lambda function package of k0kubun/sqldef for MySQL.
The database schema management tool k0kubun/sqldef is really nice, but it is always problem where we should run it. If our database is in a closed network on a cloud service, we should create and maintain a virtual server to run sqldef for a long time. It's also a problem that we can't run sqldef triggered by CIs in such environment.
This repository is to package the mysqldef binary and a script with some more files of schema and keys into a .zip file, which is available as a Lambda function. Once you place the package onto your AWS environment, you can trigger sqldef schema management with schema files on GitHub repositories.
An example event data to trigger this function:
{
"database_name": "mydata",
"database_host": "mydata.cluster-xxxxxxxx.ap-northeast-1.rds.amazonaws.com",
"database_username": "root",
"database_password": "SECRET_DATABASE_PASSWORD",
"input": {
"type": "github",
"repository": "exampleorg/myproject",
"schema_path": "db/schema.sql",
"key_name": "myproject_deploy_key1"
},
"dry_run": true
}
Put the event above into the "Test" event JSON and execute it, then what you get::
{
"statusCode": 200,
"body": "\"Done\""
}
START RequestId: 9cd66c4e-f5d7-4fdd-ba0d-ba313db134c7 Version: $LATEST
2023-05-02T09:43:05.603Z 9cd66c4e-f5d7-4fdd-ba0d-ba313db134c7 INFO -------------- stdout --------------
-- dry run --
CREATE TABLE `notifications` (
`id` bigint NOT NULL AUTO_INCREMENT,
`uuid` varchar(36) NOT NULL,
`subject` text NOT NULL,
(snip)
You can check the --dry-run
results, then turn "dry_run": true
into false
and apply the changes actually.
Yes. This package can contain SSH keys to be specified in triggering events. So you can create a deploy key of your private repository, then package it into the .zip file. Lambda function will fetch the schema file by the deploy key (if specified so).
Definitely! This project's main purpose is to maintain DB schema of an Aurora database in a private VPC originally.
You don't have to maintain the environment to execute sqldef.
It's easier to setup a Lambda function than any others.
AWS Lambda environment is a modified Linux environment, which prohibits seteuid
required by git+ssh. I couldn't find a good workaround of the problem, but found git-lambda-layer for the classic Lambda package.
Yes. You can easily fork this repository and modify the script for PostgreSQL or MS SQL.
Yes.
- Clone this repository
- Put your schema SQL files into
includes/
if you want to bundle schema file into .zip package - Put your deployment key file into
deploy_keys/
if you want to fetch schema files from your private repository - Build the package by running
./build.sh
, and getpkg/mysqldef_lambda.zip
- Create a Lambda function within your VPC network (if needed), with a layer of git-lambda-layer
This is just an example of Lambda function creation. You can use AWS CLI, AWS Management Console or any other ways to create it.
$ aws lambda create-function \
--function-name myproject-mysqldef \
--runtime nodejs18.x \
--package-type Zip \
--handler index.handler \
--zip-file fileb://$(pwd)/pkg/mysqldef_lambda.zip \
--role arn:aws:iam::MY_ACCOUNT:role/RoleToManageDatabases \
--vpc-config SubnetIds=subnet-xxx,subnet-yyy,SecurityGroupIds=sg-zzzzzz \
--architectures x86_64 \
--layers arn:aws:lambda:YOUR_REGION:553035198032:layer:git-lambda2:8 \
--timeout 60
The requirements of this package are:
option | value | |
---|---|---|
runtime | nodejs18.x | fixed value |
handler | index.handler | fixed value |
role | ARN of your IAM role | the IAM role must be able to access the DB |
vpc-config | SubnetIds=...,SecurityGroupIds=... | subnets and security groups of your VPC if needed |
architecture | x86_64 | fixed value |
layers | ARNs of Lambda layers | See below |
timeout | 60 | the default (3 seconds) is too short to clone a git repository |
The AWS Lambda function prohibits seteuid
call, which is required by usual git+ssh. As the workaround of this problem, this package needs a Lambda layer of a patched git
command, git-lambda-layer.
This Lambda function script uses git
and ssh
commands to clone private repositories. To execute git clone
, the Lambda function of this package needs to be configured with a Lambda layer of git-lambda-layer
to replace git
command by the patched version.
You can choose any of available versions, but newer should be better.
Many things can be configured via both environment variables and events. Values from events are prior to values from environment variables.
But the 2 things below must be specified by events:
- Database schema source (files in the package, or GitHub.com repository)
- Dry-run or not (dry-run in default)
Event JSON should be like:
{
"database_name": "mydata",
"database_host": "mydata.cluster-xxxxxxxx.ap-northeast-1.rds.amazonaws.com",
"database_username": "root",
"database_password": "SECRET_DATABASE_PASSWORD",
"input": {
"type": "github",
"repository": "exampleorg/myproject",
"schema_path": "db/schema.sql",
"key_name": "myproject_deploy_key1"
},
"dry_run": true
}
input
: the database schema input, a string (filename) or an object
If the value of input
is a string, it means a filename, that should be in includes/
directory (without includes/
).
If the value of input
is an object, it should/can have attributes below:
type
: must be"github"
repository
: theaccount/repo
style repository nameschema_path
: the file path of the schema file in the repositorybranch
: the branch name (default:main
)key_name
: the deploy key file name, should be indeploy_keys/
The deploy key name must be specified for private repositories.
database_name
: the name of the databasedatabase_host
: the hostname of MySQL databasedatabase_port
: the port number of MySQL database (default:3306
)database_username
: the username (default:root
)database_password
: the password of the specified userdry_run
: specify--dry-run
option (true
) or not (false
) (default:true
)
DATABASE_NAME
DATABASE_HOST
DATABASE_PORT
DATABASE_USERNAME
DATABASE_PASSWORD
This function can fetch secret values from AWS Secrets Manager for the database name, host, port, username and password.
If those values are configured as secrets_manager:xxxx
, the function will fetch secrets from Secrets Manager and use the fetched values instead of using configured values directly.
Value patterns are:
secrets_manager:xxxx
(with single:
)xxxx
should be a key of secret, and fetched string value will be used as value
secrets_manager:xxxx:yyyy
(with double:
)xxxx
should be a key of secret, and value must be a JSON object stringyyyy
should be an attribute name of the JSON object
Prerequisites:
- Docker
- MySQL on the docker host (or in the local network)
- Create a database
deftest
on the MySQL
Steps:
- Clone this repository
- (Add modifications if needed)
- Execute
./build.sh
to build the container - Run the container:
docker run -e DATABASE_HOST=host.docker.internal -e DATABASE_PORT=3306 -p 9000:8080 mysqldef-lambda
- Trigger the function:
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"database_name":"deftest","input":{"type":"github","repository":"tagomoris/mysqldef_lambda_package","schema_path":"example/schema.sql","branch":"branch-for-schema-file"}}' | jq .