As far as I’m aware, there isn’t a built-in solution for statically typing a configuration for the AWS Cloud Development Kit (CDK). So after a bit of research, I created a way of doing it!
CDK Context
Context is a way to pass in runtime values to our CDK application. You can do this several ways. In this example, we’ll use a combination of the cdk.json
file and the —context
or -c
cli flag to pass in our runtime configuration.
Configuration File
The first step is to add your configuration values to the context
key in the cdk.json
file for each environment.
{
...
"context": {
...
"dev": {
"region": "us-east-1",
"appPrefix": "cc"
},
"prod": {
"region": "us-east-1",
"appPrefix": "cc"
},
"sandbox": {
"region": "us-west-2",
"appPrefix": "cc",
}
...
}
}
This example is using dev
, sandbox
, and prod
as environment names, but you can call them any name you want.
Specify an Environment
The next step is to come up with a way to specify which environment to deploy to when your CDK app is deployed. You do this with the cli flag mentioned above: --context
or -c
. This flag allows you to pass in a value to CDK from the command line. In this example, we are going to pass in a config
value that will specify which environment we want to use:
cdk deploy -c config=dev|sandbox|prod
Build the Configuration
After you’ve specified your configuration and specified an environment to run, the next step is to ingest the configuration and type it. Paste the following contents into a file named build-config.ts
in your CDK project:
import * as cdk from "aws-cdk-lib";
// These values map to the keys in our cdk.json and make sure
// no values that aren't supported are passed in with the
// -c config=env flag
const supportedEnvironments = ["prod", "dev", "sandbox"] as const;
type SupportedEnvironments = typeof supportedEnvironments[number];
// This maps to the values you specified in your cdk.json file
// if you add any values to your cdk.json file, also add them here!
export type BuildConfig = {
environment: SupportedEnvironments;
appPrefix: string;
region: string;
};
// This function is used by your CDK app and pulls your config values
// from the context
export const getConfig = (app: cdk.App): BuildConfig => {
const env = app.node.tryGetContext("config");
if (!env) {
throw new Error(
"Environment variable must be passed to cdk: `yarn cdk -c config=XXX`"
);
}
if (!supportedEnvironments.includes(env)) {
throw new Error(
`${env} is not in supported environments: ${supportedEnvironments.join(
", "
)}`
);
}
// this contains the values in the context without being
// validated
const unparsedEnv = app.node.tryGetContext(env);
return {
environment: env,
appPrefix: ensureString(unparsedEnv, "appPrefix"),
region: ensureString(unparsedEnv, "region"),
};
};
// this function ensures that the value from the config is
// the correct type. If you have any types other than
// strings be sure to create a new validation function
function ensureString(
object: { [name: string]: any },
key: keyof BuildConfig
): string {
if (
!object[key] ||
typeof object[key] !== "string" ||
object[key].trim().length === 0
) {
throw new Error(key + " does not exist in cdk config");
}
return object[key];
}
Wrap Up: Statically Typed CDK Configurations
And that’s it! You now have a statically typed config you can use in your CDK scripts. I hope this example is useful in your CDK project.
some day the internet will have cdk examples for python