I want to deploy AWS CDK stacks from with a Lambda function. The use case is to support similar functionality to that described in Trek10's Serverless CI/CD pipeline, where the relevant code is here.
In a nutshell, AWS CodePipelines only support listening to changes within a single Git branch. I want to listen to GitHub events relating to the creation of repos and branches and create CodePipeline instances in response to these events so that there is a Pipeline for each branch of each Git repository. I want a Lambda to listen to the GitHub events and create CDK stacks. The Trek10 example uses Python and calls CloudFormation directly. I'd like the Lambdas to be much simpler and use the CDK instead.
Here is a simple Lambda using Typescript that is derived from this AWS CDK issue:
// index.ts
import {ScheduledEvent} from 'aws-lambda';
import {CloudFormationDeploymentTarget, DEFAULT_TOOLKIT_STACK_NAME} from 'aws-cdk/lib/api/deployment-target';
import {CdkToolkit} from 'aws-cdk/lib/cdk-toolkit';
import {AppStacks} from 'aws-cdk/lib/api/cxapp/stacks';
import {Configuration} from 'aws-cdk/lib/settings';
import {execProgram} from "aws-cdk/lib/api/cxapp/exec";
import * as yargs from 'yargs';
import {SDK} from 'aws-cdk/lib/api/util/sdk';
export const handleCloudWatchEvent = async (event: ScheduledEvent): Promise<void> => {
try {
const aws = new SDK();
const argv = await yargs.parse(['deploy', '--app', 'bin/pipeline.js', '--staging', '/tmp', '--verbose', '--require-approval', 'never']);
const configuration = new Configuration(argv);
await configuration.load();
const appStacks = new AppStacks({
configuration,
aws,
synthesizer: execProgram,
});
const provisioner = new CloudFormationDeploymentTarget({ aws });
const cli = new CdkToolkit({ appStacks, provisioner });
const toolkitStackName = configuration.settings.get(['toolkitStackName']) || DEFAULT_TOOLKIT_STACK_NAME;
await cli.deploy({
stackNames: [],
exclusively: argv.exclusively as boolean,
toolkitStackName,
roleArn: argv.roleArn as string,
requireApproval: configuration.settings.get(['requireApproval']),
ci: true,
reuseAssets: argv['build-exclude'] as string[],
sdk: aws
});
return;
} catch (e) {
console.error(e);
return;
}
};
However, I get an error as described in the issue mentioned above:
ERROR { Error: Cannot find module '../package.json'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
at Function.Module._load (internal/modules/cjs/loader.js:562:25)
at Module.require (internal/modules/cjs/loader.js:692:17)
at new SDK (/var/task/node_modules/aws-cdk/lib/api/util/sdk.ts:92:39)
at Runtime.exports.handleCloudWatchEvent [as handler] (/resources/index.ts:204:21)
at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)
at process._tickCallback (internal/process/next_tick.js:68:7) code: 'MODULE_NOT_FOUND' }
I don't want to patch sdk.ts
: https://github.com/aws/aws-cdk/blob/master/packages/aws-cdk/lib/api/util/sdk.ts#L92 as that seems to be a very dirty solution so I'm looking for another solution.
What is the simplest working example of calling the CDK from within a Lambda function?
Steps to create a Lambda Function in AWS CDKStep 1: Instantiate Function Class. Step 2: Add the code for the Lambda Function. Step 3: Adding IAM Permissions for Lambda Function. Step 4: Deploy the Function.
All in all, CloudFormation makes deploying AWS Lambda functions incredibly simple. Start by creating the template file that will define your resources. This will be your working folder for your code. Next, create your function in the appropriate file for your desired Lambda runtime.
How did you end up packaging cdk to run inside lambda? was that done via layers or is there a easier way?
Recently I had an ideal use case for a CDK deployer in Lambda but couldn't find any good and full examples of how to do this. Using kadishmal example from CDK Github I managed to put CDK into Lambda layer, delete AWS SDK module from there (Lambda already has it), include it into a Lambda, and run CDK deploy/destroy from there. There is a size restriction for a Lambda and all its layers of 250mb so I also had to use Webpack to optimize the build size.
Here a Github repository with a basic example - a stack template that deploys S3 bucket and destroys it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With