Having built a few production stacks we are seeing patterns in the component parts we use, and want to enforce internal best practices: timeouts / env values / roles etc as well as keep actual stack logic as small/focused as possible. I was discussing this with @eladb on gitter...
I've been playing with something like: lib/our-company/lambda.ts (with a lib/our-company/index.ts so we can import all constructs with a simple single import):
interface OurCompanyILamdaProps {
assetPath: string, // what are we deploying
environment?: any,
handler?: string,
description?: string,
timeout?: number
}
export class Lambda extends cdk.Construct {
public readonly function: lambda.Function;
constructor(scope: cdk.Construct, id: string, props: OurCompanyILamdaProps) {
super(scope, id);
let env: any = props.environment ? props.environment : {};
// make sure we always have the ENV available to the lambda function.
env.DEPLOY_ENV = process.env.DEPLOY_ENV;
// construct ID needs to be unique
let constructId = id + env.DEPLOY_ENV;
let lam = new lambda.Function(scope, constructId, {
code: lambda.Code.asset(props.assetPath),
handler: props.handler ? props.handler : "index.handler",
runtime: lambda.Runtime.NODEJS_10_X,
environment: props.environment,
description: props.description,
timeout: cdk.Duration.seconds(props.timeout ? props.timeout : 60)
})
// Do stuff..
// if prop.allowAccessSecrets ... create role and assign to lambda
// if prop.addMonitoring ...
// if prop.someThingElse ...
this.function = lam;
}
}
Then assuming stacks/NAME/index.ts:
import * as OurCompany from '../constructs/';
let lambFunction = new OurCompany.Lambda(this, 'aThing', {
assetPath: __dirname + '/lambda/function_a/',
environment: environment
}).function; // note .function here to get the underlying construct if needed
aDynamoDBTable.grantReadWriteData(lambFunction);
Other sorts of defaults we are thinking of:
- All queues get a DLQ
- Monitoring / alerts
- Permissions to secrets (by creating specific role), but just pass in the secret string
- Backup settings on DynamoDB table
- possibly tagging - though I know you should be able to do that at stack level, last time I tried it hasn't worked.
Additionally we could build feature factory constructs... 'swagger file + lambda functions' = apigateway (I've basically used https://gist.github.com/abbottdev/17379763ebc14a5ecbf2a111ffbcdd86 - from #1461 - and mundged it to hide the implementation of parsing the swagger file).
Some of this will include differences we want between production and development environments - but the goal being standards and best practices (for our company) over all.
Feedback / thoughts would be most appreciated.
Having built a few production stacks we are seeing patterns in the component parts we use, and want to enforce internal best practices: timeouts / env values / roles etc as well as keep actual stack logic as small/focused as possible. I was discussing this with @eladb on gitter...
I've been playing with something like:
lib/our-company/lambda.ts(with alib/our-company/index.tsso we can import all constructs with a simple single import):Then assuming
stacks/NAME/index.ts:Other sorts of defaults we are thinking of:
Additionally we could build feature factory constructs... 'swagger file + lambda functions' = apigateway (I've basically used https://gist.github.com/abbottdev/17379763ebc14a5ecbf2a111ffbcdd86 - from #1461 - and mundged it to hide the implementation of parsing the swagger file).
Some of this will include differences we want between production and development environments - but the goal being standards and best practices (for our company) over all.
Feedback / thoughts would be most appreciated.