@guardian/cdk 50.0.0-beta.1 → 50.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/bin/commands/new-project/index.js +9 -9
- package/lib/bin/commands/new-project/index.js.map +1 -1
- package/lib/constants/ssm-parameter-paths.d.ts +1 -0
- package/lib/constants/ssm-parameter-paths.d.ts.map +1 -1
- package/lib/constants/ssm-parameter-paths.js +4 -0
- package/lib/constants/ssm-parameter-paths.js.map +1 -1
- package/lib/constructs/autoscaling/asg.d.ts +2 -1
- package/lib/constructs/autoscaling/asg.d.ts.map +1 -1
- package/lib/constructs/autoscaling/asg.js +26 -10
- package/lib/constructs/autoscaling/asg.js.map +1 -1
- package/lib/constructs/cloudwatch/alarm.d.ts +1 -0
- package/lib/constructs/cloudwatch/alarm.d.ts.map +1 -1
- package/lib/constructs/cloudwatch/alarm.js +4 -1
- package/lib/constructs/cloudwatch/alarm.js.map +1 -1
- package/lib/constructs/lambda/lambda.d.ts +1 -10
- package/lib/constructs/lambda/lambda.d.ts.map +1 -1
- package/lib/constructs/lambda/lambda.js +0 -5
- package/lib/constructs/lambda/lambda.js.map +1 -1
- package/lib/constructs/loadbalancing/alb/application-listener.d.ts +1 -1
- package/lib/constructs/loadbalancing/alb/application-listener.d.ts.map +1 -1
- package/lib/constructs/loadbalancing/alb/application-listener.js +9 -7
- package/lib/constructs/loadbalancing/alb/application-listener.js.map +1 -1
- package/lib/experimental/riff-raff-yaml-file/deployments/cloudformation.d.ts.map +1 -1
- package/lib/experimental/riff-raff-yaml-file/deployments/cloudformation.js +3 -0
- package/lib/experimental/riff-raff-yaml-file/deployments/cloudformation.js.map +1 -1
- package/lib/experimental/riff-raff-yaml-file/index.d.ts.map +1 -1
- package/lib/experimental/riff-raff-yaml-file/index.js +1 -4
- package/lib/experimental/riff-raff-yaml-file/index.js.map +1 -1
- package/lib/patterns/ec2-app/base.d.ts +112 -243
- package/lib/patterns/ec2-app/base.d.ts.map +1 -1
- package/lib/patterns/ec2-app/base.js +14 -176
- package/lib/patterns/ec2-app/base.js.map +1 -1
- package/lib/patterns/ec2-app/framework.d.ts +13 -1
- package/lib/patterns/ec2-app/framework.d.ts.map +1 -1
- package/lib/patterns/ec2-app/framework.js +17 -1
- package/lib/patterns/ec2-app/framework.js.map +1 -1
- package/lib/patterns/scheduled-lambda.d.ts.map +1 -1
- package/lib/patterns/scheduled-lambda.js +1 -3
- package/lib/patterns/scheduled-lambda.js.map +1 -1
- package/lib/types/amigo.d.ts +12 -0
- package/lib/types/amigo.d.ts.map +1 -1
- package/lib/types/amigo.js.map +1 -1
- package/package.json +17 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../../constructs/autoscaling\";\nimport { GuStack } from \"../../constructs/core\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport { addAmiParametersToCloudFormationDeployment, cloudFormationDeployment } from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { groupByClassNameStackRegionStage } from \"./group-by\";\nimport type {\n GroupedCdkStacks,\n Region,\n RiffRaffDeployment,\n RiffRaffDeploymentName,\n RiffRaffDeploymentProps,\n RiffRaffYaml,\n StackTag,\n StageTag,\n} from \"./types\";\n\n/**\n * A class that creates a `riff-raff.yaml` file.\n *\n * Rather than using this directly, prefer to use [[`GuRoot`]] instead.\n *\n * Supports:\n * - Multiple CloudFormation stacks\n * - Multiple regions\n * - Lambda applications\n * - EC2 (autoscaling) applications\n *\n * For lambda applications, 3 deployments will be defined:\n * 1. Lambda upload (`aws-lambda`, `action: [uploadLambda]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Lambda update (`aws-lambda`, `action: [updateLambda]`)\n *\n * For EC2 applications, 3 deployments will be defined:\n * 1. Artifact upload (`autoscaling`, `action: [uploadArtifacts]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Autoscaling deploy (`autoscaling`, `action: [deploy]`)\n *\n * It assumes a Riff-Raff bundle structure as follows:\n *\n * ```\n * .\n * ├── cdk.out\n * │ └── MyApplication.template.json\n * ├── my-application\n * │ └── my-application.deb\n * └── my-lambda\n * └── my-lambda.zip\n * ```\n *\n * That is, all CloudFormation templates are in a `cdk.out` directory, and there is a directory per app.\n * Application artifact(s) are in the app directory.\n *\n * NOTE: The file extension is decided by you, the above file tree is used for illustration purposes.\n *\n * NOTE: Resources will be looked up by tags (Stack, Stage, App). Ensure your CFN stack is tagged appropriately!\n *\n * @see https://riffraff.gutools.co.uk/docs/reference/riff-raff.yaml.md\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\nexport class RiffRaffYamlFileExperimental {\n private readonly allCdkStacks: GuStack[];\n private readonly allStackTags: StackTag[];\n private readonly allStageTags: StageTag[];\n private readonly allRegions: Region[];\n\n private readonly riffRaffYaml: RiffRaffYaml;\n private readonly outdir: string;\n\n private isCdkStackPresent(expectedStack: StackTag, expectedStage: StageTag): boolean {\n const matches = this.allCdkStacks.find((cdkStack) => {\n const { stack, stage } = cdkStack;\n return stack === expectedStack && stage === expectedStage;\n });\n\n return !!matches;\n }\n\n /**\n * Check there are the appropriate number of `GuStack`s.\n * Expect to find an instance for each combination of `stack`, and `stage`.\n *\n * If not valid, a message is logged describing what is missing to aid debugging.\n *\n * Given the following:\n *\n * ```ts\n * const app = new App();\n *\n * class MyApplicationStack extends GuStack { }\n *\n * new MyApplicationStack(app, \"App-CODE-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"CODE\"\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-media-service\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"media-service\",\n * stage: \"PROD\",\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"PROD\"\n * });\n * ```\n *\n * This will log a message like this, where ❌ denotes something missing,\n * specifically there is no `CODE` template for `media-service`.\n *\n * ```log\n * Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)\n *\n * ┌───────────────┬──────┬──────┐\n * │ (index) │ CODE │ PROD │\n * ├───────────────┼──────┼──────┤\n * │ deploy │ '✅' │ '✅' │\n * │ media-service │ '❌' │ '✅' │\n * └───────────────┴──────┴──────┘\n * ```\n *\n * @private\n */\n private validateStacksInApp(): void {\n type Found = \"✅\";\n type NotFound = \"❌\";\n type AppValidation = Record<StackTag, Record<StageTag, Found | NotFound>>;\n\n const { allStackTags, allStageTags } = this;\n\n const checks: AppValidation = allStackTags.reduce((accStackTag, stackTag) => {\n return {\n ...accStackTag,\n [stackTag]: allStageTags.reduce((accStageTag, stageTag) => {\n return {\n ...accStageTag,\n [stageTag]: this.isCdkStackPresent(stackTag, stageTag) ? \"✅\" : \"❌\",\n };\n }, {}),\n };\n }, {});\n\n const missingDefinitions: Array<Found | NotFound> = Object.values(checks).flatMap((groupedByStackTag) => {\n return Object.values(groupedByStackTag).filter((_) => _ === \"❌\");\n });\n\n if (missingDefinitions.length > 0) {\n const message = `Unable to produce a working riff-raff.yaml file; missing ${missingDefinitions.length} definitions`;\n\n console.log(`${message} (details below)`);\n console.table(checks);\n\n throw new Error(message);\n }\n }\n\n private validateAllRegionsAreResolved(): void {\n const unresolved = this.allRegions.filter((region) => Token.isUnresolved(region));\n\n if (unresolved.length !== 0) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; all stacks must have an explicit region set`);\n }\n }\n\n private getLambdas(cdkStack: GuStack): GuLambdaFunction[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuLambdaFunction) as GuLambdaFunction[];\n }\n\n private getAutoScalingGroups(cdkStack: GuStack): GuAutoScalingGroup[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuAutoScalingGroup) as GuAutoScalingGroup[];\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree\n constructor(app: App) {\n this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));\n this.allStageTags = Array.from(allowedStages);\n this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));\n this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));\n\n this.validateStacksInApp();\n this.validateAllRegionsAreResolved();\n\n this.outdir = app.outdir;\n\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n const groupedStacks: GroupedCdkStacks = groupByClassNameStackRegionStage(this.allCdkStacks);\n\n Object.values(groupedStacks).forEach((stackTagGroup) => {\n Object.values(stackTagGroup).forEach((regionGroup) => {\n Object.values(regionGroup).forEach((stageGroup) => {\n const stacks: GuStack[] = Object.values(stageGroup).flat();\n\n if (stacks.length === 0) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `stacks` is checked above\n const stack = stacks[0]!;\n\n const lambdas = this.getLambdas(stack);\n const autoscalingGroups = this.getAutoScalingGroups(stack);\n\n const artifactUploads: RiffRaffDeployment[] = [\n lambdas.map(uploadLambdaArtifact),\n autoscalingGroups.map(uploadAutoscalingArtifact),\n ].flat();\n artifactUploads.forEach(({ name, props }) => deployments.set(name, props));\n\n const cfnDeployment = cloudFormationDeployment(stacks, artifactUploads, this.outdir);\n deployments.set(cfnDeployment.name, cfnDeployment.props);\n\n const lambdasWithoutAnAlias = lambdas.filter((lambda) => lambda.alias === undefined)\n // If the Lambda has an alias it is using versioning. When using versioning, there is no need for Riff-Raff\n // to modify the unpublished version of the function\n lambdasWithoutAnAlias.forEach((lambda) => {\n const lambdaDeployment = updateLambdaDeployment(lambda, cfnDeployment);\n deployments.set(lambdaDeployment.name, lambdaDeployment.props);\n });\n\n autoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n });\n\n deployments.set(\n cfnDeployment.name,\n addAmiParametersToCloudFormationDeployment(cfnDeployment, autoscalingGroups)\n );\n });\n });\n });\n\n this.riffRaffYaml = {\n allowedStages,\n deployments,\n };\n }\n\n /**\n * The `riff-raff.yaml` file as a string.\n * Useful for testing.\n */\n toYAML(): string {\n // Add support for ES6 Set and Map. See https://github.com/nodeca/js-yaml/issues/436.\n const replacer = (_key: string, value: unknown) => {\n if (value instanceof Set) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Array.from(value);\n }\n if (value instanceof Map) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Object.fromEntries(value);\n }\n return value;\n };\n\n return dump(this.riffRaffYaml, { replacer });\n }\n\n /**\n * Write the `riff-raff.yaml` file to disk.\n * It'll be located with the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n const outPath = path.join(this.outdir, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML());\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../../constructs/autoscaling\";\nimport { GuStack } from \"../../constructs/core\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport { addAmiParametersToCloudFormationDeployment, cloudFormationDeployment } from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { groupByClassNameStackRegionStage } from \"./group-by\";\nimport type {\n GroupedCdkStacks,\n Region,\n RiffRaffDeployment,\n RiffRaffDeploymentName,\n RiffRaffDeploymentProps,\n RiffRaffYaml,\n StackTag,\n StageTag,\n} from \"./types\";\n\n/**\n * A class that creates a `riff-raff.yaml` file.\n *\n * Rather than using this directly, prefer to use [[`GuRoot`]] instead.\n *\n * Supports:\n * - Multiple CloudFormation stacks\n * - Multiple regions\n * - Lambda applications\n * - EC2 (autoscaling) applications\n *\n * For lambda applications, 3 deployments will be defined:\n * 1. Lambda upload (`aws-lambda`, `action: [uploadLambda]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Lambda update (`aws-lambda`, `action: [updateLambda]`)\n *\n * For EC2 applications, 3 deployments will be defined:\n * 1. Artifact upload (`autoscaling`, `action: [uploadArtifacts]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Autoscaling deploy (`autoscaling`, `action: [deploy]`)\n *\n * It assumes a Riff-Raff bundle structure as follows:\n *\n * ```\n * .\n * ├── cdk.out\n * │ └── MyApplication.template.json\n * ├── my-application\n * │ └── my-application.deb\n * └── my-lambda\n * └── my-lambda.zip\n * ```\n *\n * That is, all CloudFormation templates are in a `cdk.out` directory, and there is a directory per app.\n * Application artifact(s) are in the app directory.\n *\n * NOTE: The file extension is decided by you, the above file tree is used for illustration purposes.\n *\n * NOTE: Resources will be looked up by tags (Stack, Stage, App). Ensure your CFN stack is tagged appropriately!\n *\n * @see https://riffraff.gutools.co.uk/docs/reference/riff-raff.yaml.md\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\nexport class RiffRaffYamlFileExperimental {\n private readonly allCdkStacks: GuStack[];\n private readonly allStackTags: StackTag[];\n private readonly allStageTags: StageTag[];\n private readonly allRegions: Region[];\n\n private readonly riffRaffYaml: RiffRaffYaml;\n private readonly outdir: string;\n\n private isCdkStackPresent(expectedStack: StackTag, expectedStage: StageTag): boolean {\n const matches = this.allCdkStacks.find((cdkStack) => {\n const { stack, stage } = cdkStack;\n return stack === expectedStack && stage === expectedStage;\n });\n\n return !!matches;\n }\n\n /**\n * Check there are the appropriate number of `GuStack`s.\n * Expect to find an instance for each combination of `stack`, and `stage`.\n *\n * If not valid, a message is logged describing what is missing to aid debugging.\n *\n * Given the following:\n *\n * ```ts\n * const app = new App();\n *\n * class MyApplicationStack extends GuStack { }\n *\n * new MyApplicationStack(app, \"App-CODE-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"CODE\"\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-media-service\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"media-service\",\n * stage: \"PROD\",\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"PROD\"\n * });\n * ```\n *\n * This will log a message like this, where ❌ denotes something missing,\n * specifically there is no `CODE` template for `media-service`.\n *\n * ```log\n * Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)\n *\n * ┌───────────────┬──────┬──────┐\n * │ (index) │ CODE │ PROD │\n * ├───────────────┼──────┼──────┤\n * │ deploy │ '✅' │ '✅' │\n * │ media-service │ '❌' │ '✅' │\n * └───────────────┴──────┴──────┘\n * ```\n *\n * @private\n */\n private validateStacksInApp(): void {\n type Found = \"✅\";\n type NotFound = \"❌\";\n type AppValidation = Record<StackTag, Record<StageTag, Found | NotFound>>;\n\n const { allStackTags, allStageTags } = this;\n\n const checks: AppValidation = allStackTags.reduce((accStackTag, stackTag) => {\n return {\n ...accStackTag,\n [stackTag]: allStageTags.reduce((accStageTag, stageTag) => {\n return {\n ...accStageTag,\n [stageTag]: this.isCdkStackPresent(stackTag, stageTag) ? \"✅\" : \"❌\",\n };\n }, {}),\n };\n }, {});\n\n const missingDefinitions: Array<Found | NotFound> = Object.values(checks).flatMap((groupedByStackTag) => {\n return Object.values(groupedByStackTag).filter((_) => _ === \"❌\");\n });\n\n if (missingDefinitions.length > 0) {\n const message = `Unable to produce a working riff-raff.yaml file; missing ${missingDefinitions.length} definitions`;\n\n console.log(`${message} (details below)`);\n console.table(checks);\n\n throw new Error(message);\n }\n }\n\n private validateAllRegionsAreResolved(): void {\n const unresolved = this.allRegions.filter((region) => Token.isUnresolved(region));\n\n if (unresolved.length !== 0) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; all stacks must have an explicit region set`);\n }\n }\n\n private getLambdas(cdkStack: GuStack): GuLambdaFunction[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuLambdaFunction) as GuLambdaFunction[];\n }\n\n private getAutoScalingGroups(cdkStack: GuStack): GuAutoScalingGroup[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuAutoScalingGroup) as GuAutoScalingGroup[];\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree\n constructor(app: App) {\n this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));\n this.allStageTags = Array.from(allowedStages);\n this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));\n this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));\n\n this.validateStacksInApp();\n this.validateAllRegionsAreResolved();\n\n this.outdir = app.outdir;\n\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n const groupedStacks: GroupedCdkStacks = groupByClassNameStackRegionStage(this.allCdkStacks);\n\n Object.values(groupedStacks).forEach((stackTagGroup) => {\n Object.values(stackTagGroup).forEach((regionGroup) => {\n Object.values(regionGroup).forEach((stageGroup) => {\n const stacks: GuStack[] = Object.values(stageGroup).flat();\n\n if (stacks.length === 0) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `stacks` is checked above\n const stack = stacks[0]!;\n\n const lambdas = this.getLambdas(stack);\n const autoscalingGroups = this.getAutoScalingGroups(stack);\n\n const artifactUploads: RiffRaffDeployment[] = [\n lambdas.map(uploadLambdaArtifact),\n autoscalingGroups.map(uploadAutoscalingArtifact),\n ].flat();\n artifactUploads.forEach(({ name, props }) => deployments.set(name, props));\n\n const cfnDeployment = cloudFormationDeployment(stacks, artifactUploads, this.outdir);\n deployments.set(cfnDeployment.name, cfnDeployment.props);\n\n lambdas.forEach((lambda) => {\n const lambdaDeployment = updateLambdaDeployment(lambda, cfnDeployment);\n deployments.set(lambdaDeployment.name, lambdaDeployment.props);\n });\n\n autoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n });\n\n deployments.set(\n cfnDeployment.name,\n addAmiParametersToCloudFormationDeployment(cfnDeployment, autoscalingGroups)\n );\n });\n });\n });\n\n this.riffRaffYaml = {\n allowedStages,\n deployments,\n };\n }\n\n /**\n * The `riff-raff.yaml` file as a string.\n * Useful for testing.\n */\n toYAML(): string {\n // Add support for ES6 Set and Map. See https://github.com/nodeca/js-yaml/issues/436.\n const replacer = (_key: string, value: unknown) => {\n if (value instanceof Set) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Array.from(value);\n }\n if (value instanceof Map) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Object.fromEntries(value);\n }\n return value;\n };\n\n return dump(this.riffRaffYaml, { replacer });\n }\n\n /**\n * Write the `riff-raff.yaml` file to disk.\n * It'll be located with the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n const outPath = path.join(this.outdir, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML());\n }\n}\n"]}
|
|
@@ -13,7 +13,19 @@ import { AppAccess } from "../../types";
|
|
|
13
13
|
import type { GuAsgCapacity, GuDomainName } from "../../types";
|
|
14
14
|
import type { AmigoProps } from "../../types/amigo";
|
|
15
15
|
export interface AccessLoggingProps {
|
|
16
|
+
/**
|
|
17
|
+
* Enable (load balancer) access logs.
|
|
18
|
+
*
|
|
19
|
+
* Note, you will need to specify a region in your stack declaration to use
|
|
20
|
+
* this.
|
|
21
|
+
* See`https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-elasticloadbalancingv2.ApplicationLoadBalancer.html#logwbraccesswbrlogsbucket-prefix`
|
|
22
|
+
*/
|
|
16
23
|
enabled: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* S3 prefix for the logs.
|
|
26
|
+
*
|
|
27
|
+
* @defaultValue no prefix
|
|
28
|
+
*/
|
|
17
29
|
prefix?: string;
|
|
18
30
|
}
|
|
19
31
|
/**
|
|
@@ -29,283 +41,140 @@ export interface AccessLoggingProps {
|
|
|
29
41
|
* to Kinesis will be configured automatically via the [[`GuEc2App`]] pattern.
|
|
30
42
|
*/
|
|
31
43
|
export interface ApplicationLoggingProps {
|
|
44
|
+
/**
|
|
45
|
+
* Enables forwarding of application logs to the Guardian ELK stack.
|
|
46
|
+
*
|
|
47
|
+
* Note, to work, you will need to also do the following non-CDK things:
|
|
48
|
+
*
|
|
49
|
+
* 1. Include the `cdk-base` Amigo role in your AMI.
|
|
50
|
+
* 2. Log to `journald`. We recommend doing this by logging to `stdout` and
|
|
51
|
+
* using `systemd` to start your app
|
|
52
|
+
* 3. Confirm that your [[`systemdUnitName`]] is configured properly.
|
|
53
|
+
*
|
|
54
|
+
* Unless you have explicitly opted-out, appropriate IAM permissions for
|
|
55
|
+
* logging to Kinesis will be configured automatically via the [[`GuEc2App`]]
|
|
56
|
+
* pattern.
|
|
57
|
+
*
|
|
58
|
+
* @see https://github.com/guardian/amigo/tree/main/roles/cdk-base
|
|
59
|
+
*/
|
|
32
60
|
enabled: boolean;
|
|
33
61
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
62
|
+
* This needs to match the name of your SystemD unit.
|
|
63
|
+
*
|
|
64
|
+
* If your systemd unit is not `<app>.service` set this value.
|
|
36
65
|
*
|
|
37
|
-
*
|
|
38
|
-
* behavour. I.e. if your app is running as `some-different-name.service`, then
|
|
39
|
-
* this prop should be set to `some-different-name`.
|
|
66
|
+
* @defaultValue `<app>.service`
|
|
40
67
|
*/
|
|
41
68
|
systemdUnitName?: string;
|
|
42
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* @privateRemarks we should rename this to AlarmsProps.
|
|
72
|
+
*/
|
|
43
73
|
export interface Alarms {
|
|
74
|
+
/**
|
|
75
|
+
* Name of the target (SNS Topic) for alarm notifications.
|
|
76
|
+
*/
|
|
44
77
|
snsTopicName: string;
|
|
78
|
+
/**
|
|
79
|
+
* Enable the 5xx alarm with settings.
|
|
80
|
+
*/
|
|
45
81
|
http5xxAlarm: false | Http5xxAlarmProps;
|
|
82
|
+
/**
|
|
83
|
+
* Enable the unhealthy instances alarm.
|
|
84
|
+
*/
|
|
46
85
|
unhealthyInstancesAlarm: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Internal flag - users of this library should ignore this setting.
|
|
88
|
+
*/
|
|
47
89
|
noMonitoring?: false;
|
|
48
90
|
}
|
|
49
|
-
/**
|
|
50
|
-
* Configuration options for the [[`GuEc2App`]] pattern.
|
|
51
|
-
*
|
|
52
|
-
* To grant EC2 instances additional IAM permissions, use the `roleConfiguration` prop. For example,
|
|
53
|
-
* to allow your app to write to DynamoDB:
|
|
54
|
-
*
|
|
55
|
-
* ```typescript
|
|
56
|
-
* // other props
|
|
57
|
-
* roleConfiguration: {
|
|
58
|
-
* additionalPolicies: [new GuDynamoDBWritePolicy(stack, "DynamoTable", { tableName: "my-dynamo-table" })],
|
|
59
|
-
* }
|
|
60
|
-
* ```
|
|
61
|
-
*
|
|
62
|
-
* To create alarms (recommended), use:
|
|
63
|
-
* ```typescript
|
|
64
|
-
* // other props
|
|
65
|
-
* monitoringConfiguration: {
|
|
66
|
-
* snsTopicName: "alerts-topic-for-my-team",
|
|
67
|
-
* http5xxAlarm: {
|
|
68
|
-
* tolerated5xxPercentage: 1,
|
|
69
|
-
* },
|
|
70
|
-
* unhealthyInstancesAlarm: true,
|
|
71
|
-
* }
|
|
72
|
-
* ```
|
|
73
|
-
*
|
|
74
|
-
* To opt out of creating alarms, use:
|
|
75
|
-
*```typescript
|
|
76
|
-
* // other props
|
|
77
|
-
* monitoringConfiguration: { noMonitoring: true }
|
|
78
|
-
* ```
|
|
79
|
-
*
|
|
80
|
-
* To automatically ship application logs from `stdout` to ELK, use:
|
|
81
|
-
*
|
|
82
|
-
* ```typescript
|
|
83
|
-
* {
|
|
84
|
-
* // other props
|
|
85
|
-
* applicationLogging: { enabled: true }
|
|
86
|
-
* }
|
|
87
|
-
* ```
|
|
88
|
-
*
|
|
89
|
-
* For more details on the requirements for application log shipping, see [[`ApplicationLoggingProps`]].
|
|
90
|
-
*
|
|
91
|
-
* To enable access logging for your load balancer, you can specify the prefix to write the logs to.
|
|
92
|
-
* The S3 bucket used to hold these access logs must be specified in SSM at `/account/services/access-logging/bucket`
|
|
93
|
-
* You must specify a region in your stack declaration if you are to use this prop, as specified here:
|
|
94
|
-
* https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-elasticloadbalancingv2.ApplicationLoadBalancer.html#logwbraccesswbrlogsbucket-prefix
|
|
95
|
-
* For example:
|
|
96
|
-
* ```typescript
|
|
97
|
-
* {
|
|
98
|
-
* // other props
|
|
99
|
-
* accessLogging: {
|
|
100
|
-
* enabled: true,
|
|
101
|
-
* prefix: "my-application-logs"
|
|
102
|
-
* }
|
|
103
|
-
* }
|
|
104
|
-
*
|
|
105
|
-
* If you would like to enable access logging at the root of the S3 bucket (ie without a prefix), you can omit the prefix
|
|
106
|
-
* For example:
|
|
107
|
-
* ```typescript
|
|
108
|
-
* {
|
|
109
|
-
* // other props
|
|
110
|
-
* accessLogging: {
|
|
111
|
-
* enabled: true,
|
|
112
|
-
* }
|
|
113
|
-
* }
|
|
114
|
-
* ```
|
|
115
|
-
*/
|
|
116
91
|
export interface GuEc2AppProps extends AppIdentity {
|
|
92
|
+
/**
|
|
93
|
+
* User data for the autoscaling group.
|
|
94
|
+
*/
|
|
117
95
|
userData: GuUserDataProps | string;
|
|
96
|
+
/**
|
|
97
|
+
* Network access restrictions for your load balancer.
|
|
98
|
+
*
|
|
99
|
+
* Note, this merely provides defence in depth; you should, for example, limit
|
|
100
|
+
* access to the VPN and then treat that as sufficient. Instead, use Google
|
|
101
|
+
* Auth for human access, or a suitable machine auth mechanism.
|
|
102
|
+
*/
|
|
118
103
|
access: AppAccess;
|
|
104
|
+
/**
|
|
105
|
+
* The port your application runs on.
|
|
106
|
+
*/
|
|
119
107
|
applicationPort: number;
|
|
108
|
+
/**
|
|
109
|
+
* Configure IAM roles for autoscaling group EC2 instances.
|
|
110
|
+
*/
|
|
120
111
|
roleConfiguration?: GuInstanceRoleProps;
|
|
112
|
+
/**
|
|
113
|
+
* Enable and configure alarms.
|
|
114
|
+
*/
|
|
121
115
|
monitoringConfiguration: Alarms | NoMonitoring;
|
|
116
|
+
/**
|
|
117
|
+
* EC2 instance type. Note, ensure your code is built for the same
|
|
118
|
+
* architecture family (arm64 - 'Graviton' instances - or x64).
|
|
119
|
+
*/
|
|
122
120
|
instanceType: InstanceType;
|
|
121
|
+
/**
|
|
122
|
+
* Enable and configures application logs.
|
|
123
|
+
*/
|
|
123
124
|
applicationLogging?: ApplicationLoggingProps;
|
|
125
|
+
/**
|
|
126
|
+
* Enable and configures access logs.
|
|
127
|
+
*/
|
|
124
128
|
accessLogging?: AccessLoggingProps;
|
|
129
|
+
/**
|
|
130
|
+
* Add block devices (additional storage).
|
|
131
|
+
*/
|
|
125
132
|
blockDevices?: BlockDevice[];
|
|
133
|
+
/**
|
|
134
|
+
* Autoscaling group min and max sizes.
|
|
135
|
+
*/
|
|
126
136
|
scaling: GuAsgCapacity;
|
|
127
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Specify certificate for the load balancer.
|
|
139
|
+
*/
|
|
140
|
+
certificateProps?: GuDomainName;
|
|
141
|
+
/**
|
|
142
|
+
* Disable imdsv2. Most of the time you should not set this.
|
|
143
|
+
*
|
|
144
|
+
* @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html
|
|
145
|
+
*/
|
|
128
146
|
withoutImdsv2?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Configure Amigo image recipe.
|
|
149
|
+
*/
|
|
129
150
|
imageRecipe?: string | AmigoProps;
|
|
151
|
+
/**
|
|
152
|
+
* Specify the VPC to use.
|
|
153
|
+
*
|
|
154
|
+
* @see https://github.com/guardian/aws-account-setup
|
|
155
|
+
*/
|
|
130
156
|
vpc?: IVpc;
|
|
157
|
+
/**
|
|
158
|
+
* Specify private subnets if using a non-default VPC or (generally
|
|
159
|
+
* discouraged) to limit to a subset of the available subnets.
|
|
160
|
+
*/
|
|
131
161
|
privateSubnets?: ISubnet[];
|
|
162
|
+
/**
|
|
163
|
+
* Specify private subnets if using a non-default VPC or (generally
|
|
164
|
+
* discouraged) to limit to a subset of the available subnets.
|
|
165
|
+
*/
|
|
132
166
|
publicSubnets?: ISubnet[];
|
|
133
167
|
}
|
|
134
168
|
/**
|
|
135
|
-
* Pattern which creates the resources needed to run an application on EC2
|
|
136
|
-
* For convenience, you may wish to use [[`GuPlayApp`]]
|
|
137
|
-
*
|
|
138
|
-
* This pattern will grant your EC2 instances a number of commonly needed IAM permissions. For more information on
|
|
139
|
-
* this, see [[`GuInstanceRole`]]. To add additional permissions to your EC2 instances, see [[`GuEc2AppProps`]].
|
|
140
|
-
*
|
|
141
|
-
* This pattern will automatically create security groups/rules which allow for:
|
|
142
|
-
* 1. Incoming traffic over HTTPS (from the whole internet or from the specified CIDR ranges, depending on the
|
|
143
|
-
* [[`AppAccess`]] specified).
|
|
144
|
-
* 2. Communication between the load balancer and the EC2 instances over HTTP, via the specified application port.
|
|
145
|
-
* 3. Outbound traffic from your EC2 instances over HTTPS (to enable communication with third-party APIs).
|
|
146
|
-
*
|
|
147
|
-
* Example usage for a public facing app (open to the internet):
|
|
148
|
-
* ```typescript
|
|
149
|
-
* new GuEc2App(stack, {
|
|
150
|
-
* applicationPort: 1234,
|
|
151
|
-
* app: "app-name",
|
|
152
|
-
* access: { scope: AccessScope.PUBLIC },
|
|
153
|
-
* instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),
|
|
154
|
-
* certificateProps:{
|
|
155
|
-
* domainName: "prod-guardian.com",
|
|
156
|
-
* },
|
|
157
|
-
* monitoringConfiguration: {
|
|
158
|
-
* snsTopicName: "alerts-topic-for-my-team",
|
|
159
|
-
* http5xxAlarm: {
|
|
160
|
-
* tolerated5xxPercentage: 1,
|
|
161
|
-
* },
|
|
162
|
-
* unhealthyInstancesAlarm: true,
|
|
163
|
-
* },
|
|
164
|
-
* userData: {
|
|
165
|
-
* distributable: {
|
|
166
|
-
* fileName: "app-name.deb",
|
|
167
|
-
* executionStatement: `dpkg -i /app-name/app-name.deb`,
|
|
168
|
-
* }
|
|
169
|
-
* },
|
|
170
|
-
* });
|
|
171
|
-
* ```
|
|
172
|
-
*
|
|
173
|
-
* Example usage for an app which is restricted to specific CIDR ranges:
|
|
174
|
-
* ```typescript
|
|
175
|
-
* new GuEc2App(stack, {
|
|
176
|
-
* applicationPort: 1234,
|
|
177
|
-
* app: "app-name",
|
|
178
|
-
* access: {
|
|
179
|
-
* scope: AccessScope.RESTRICTED,
|
|
180
|
-
* cidrRanges: [Peer.ipv4("192.168.1.1/32"), Peer.ipv4("8.8.8.8/32")],
|
|
181
|
-
* },
|
|
182
|
-
* instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),
|
|
183
|
-
* certificateProps:{
|
|
184
|
-
* domainName: "prod-guardian.com",
|
|
185
|
-
* },
|
|
186
|
-
* monitoringConfiguration: {
|
|
187
|
-
* snsTopicName: "alerts-topic-for-my-team",
|
|
188
|
-
* http5xxAlarm: {
|
|
189
|
-
* tolerated5xxPercentage: 1,
|
|
190
|
-
* },
|
|
191
|
-
* unhealthyInstancesAlarm: true,
|
|
192
|
-
* }
|
|
193
|
-
* userData: {
|
|
194
|
-
* distributable: {
|
|
195
|
-
* fileName: "app-name.deb",
|
|
196
|
-
* executionStatement: `dpkg -i /app-name/app-name.deb`,
|
|
197
|
-
* }
|
|
198
|
-
* },
|
|
199
|
-
* });
|
|
200
|
-
* ```
|
|
201
|
-
*
|
|
202
|
-
* ### Varying values by stage
|
|
203
|
-
*
|
|
204
|
-
* There are times when you want a resource's configuration to be stage aware,
|
|
205
|
-
* for example the number of instances in an ASG.
|
|
206
|
-
*
|
|
207
|
-
* To do this, we can use a simple ternary:
|
|
208
|
-
* ```typescript
|
|
209
|
-
* new GuEc2App(this, {
|
|
210
|
-
* // other required properties
|
|
211
|
-
* scaling: this.stage === "PROD" ? { minimumInstances: 6 } : { minimumInstances: 1 }
|
|
212
|
-
* });
|
|
213
|
-
* ```
|
|
214
|
-
*
|
|
215
|
-
* If multiple properties need to be stage aware, consider encoding this into the `props` of the calling class:
|
|
216
|
-
*
|
|
217
|
-
* ```typescript
|
|
218
|
-
* export interface MyAppProps extends GuStackProps {
|
|
219
|
-
* domainName: string;
|
|
220
|
-
* scaling: GuAsgCapacity;
|
|
221
|
-
* monitoringConfiguration: Alarms | NoMonitoring;
|
|
222
|
-
* }
|
|
223
|
-
*
|
|
224
|
-
* export class MyApp extends GuStack {
|
|
225
|
-
* private static app = "cdk-playground";
|
|
226
|
-
*
|
|
227
|
-
* constructor(scope: App, id: string, props: MyAppProps) {
|
|
228
|
-
* const { stage, domainName, scaling, monitoringConfiguration } = props;
|
|
229
|
-
*
|
|
230
|
-
* super(scope, id, props);
|
|
231
|
-
*
|
|
232
|
-
* new GuPlayApp(this, {
|
|
233
|
-
* app: "my-app",
|
|
234
|
-
* instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MICRO),
|
|
235
|
-
* access: { scope: AccessScope.PUBLIC },
|
|
236
|
-
* userData: {
|
|
237
|
-
* distributable: {
|
|
238
|
-
* fileName: `my-app.deb`,
|
|
239
|
-
* executionStatement: `dpkg -i /my-app/my-app.deb`,
|
|
240
|
-
* },
|
|
241
|
-
* },
|
|
242
|
-
* certificateProps: {
|
|
243
|
-
* domainName,
|
|
244
|
-
* },
|
|
245
|
-
* monitoringConfiguration,
|
|
246
|
-
* scaling,
|
|
247
|
-
* });
|
|
248
|
-
* }
|
|
249
|
-
* }
|
|
250
|
-
*
|
|
251
|
-
* new MyApp(app, "MyApp-CODE", {
|
|
252
|
-
* stage: "CODE",
|
|
253
|
-
* domainName: "my-app.code.dev-gutools.co.uk",
|
|
254
|
-
* scaling: { minimumInstances: 1 },
|
|
255
|
-
* monitoringConfiguration: { noMonitoring: true },
|
|
256
|
-
* });
|
|
257
|
-
*
|
|
258
|
-
* new MyApp(app, "MyApp-PROD", {
|
|
259
|
-
* stage: "PROD",
|
|
260
|
-
* domainName: "my-app.prod.gutools.co.uk",
|
|
261
|
-
* scaling: { minimumInstances: 6 },
|
|
262
|
-
* monitoringConfiguration: {
|
|
263
|
-
* // config to enable alarms in PROD
|
|
264
|
-
* },
|
|
265
|
-
* });
|
|
266
|
-
* ```
|
|
267
|
-
*
|
|
268
|
-
* If you _must_ support a non-standard VPC setup, it's possible to override the VPC and subnet selection into which
|
|
269
|
-
* instances will be started. You need to set the three props below in order for this to work:
|
|
270
|
-
* vpc: this must be an IVpc instance indicating the VPC to deploy into (usually obtained from `Vpc.fromVpcAttributes`)
|
|
271
|
-
* privateSubnets: a list of ISubnet indicating the subnets for the autoscaling group to deploy instances into (usually
|
|
272
|
-
* obtained from `GuVpc.subnets`)
|
|
273
|
-
* publicSubnets: a list of ISubnet indicating the subnets for the loadbalancer to use, if the loadbalancer
|
|
274
|
-
* is intended for public access (usually obtained from `GuVpc.subnets`)
|
|
275
|
-
* On the other hand, if the access is private, then an "internal" loadbalancer is used in the `privateSubnets` list.
|
|
276
|
-
* Please note that no checking is applied to the subnet lists to ensure that they correspond to the vpc given; as
|
|
277
|
-
* an advanced feature it is assumed that the caller ensures this. If the subnets are mismatched then the resulting
|
|
278
|
-
* Cloudformation will fail to deploy.
|
|
279
|
-
*
|
|
280
|
-
* ### Customising the infrastructure generated by this pattern
|
|
281
|
-
*
|
|
282
|
-
* Although we allow users to customise many aspects of their infrastructure via [[`GuEc2AppProps`]], it's possible
|
|
283
|
-
* that there are less common use-cases which are currently unsupported via the API. In these circumstances escape
|
|
284
|
-
* hatches can be used to override specific resources in the stack.
|
|
285
|
-
*
|
|
286
|
-
* In order to do this:
|
|
169
|
+
* Pattern which creates the resources needed to run an application on EC2
|
|
170
|
+
* behind a load balancer. For convenience, you may wish to use [[`GuPlayApp`]]
|
|
171
|
+
* or [[`GuNodeApp`]], which extend this class.
|
|
287
172
|
*
|
|
288
|
-
*
|
|
289
|
-
* ```typescript
|
|
290
|
-
* const sg = new GuSecurityGroup(
|
|
291
|
-
* // custom parameters
|
|
292
|
-
* );
|
|
293
|
-
* ```
|
|
294
|
-
* 2. Access the CloudFormation version of the resource that you wish to customise, for example:
|
|
295
|
-
* ```typescript
|
|
296
|
-
* const pattern = new GuEc2App(
|
|
297
|
-
* // all parameters
|
|
298
|
-
* )
|
|
299
|
-
* const cfnLb = pattern.loadBalancer.node.defaultChild as CfnLoadBalancer;
|
|
300
|
-
* ```
|
|
301
|
-
* 3. Replace the resource generated by the pattern with your bespoke resource, for example:
|
|
302
|
-
* ```typescript
|
|
303
|
-
* cfnLb.securityGroups = [sg.securityGroupId];
|
|
304
|
-
* ```
|
|
173
|
+
* See props for further details.
|
|
305
174
|
*/
|
|
306
175
|
export declare class GuEc2App extends Construct {
|
|
307
176
|
readonly vpc: IVpc;
|
|
308
|
-
readonly certificate
|
|
177
|
+
readonly certificate?: GuCertificate;
|
|
309
178
|
readonly loadBalancer: GuApplicationLoadBalancer;
|
|
310
179
|
readonly autoScalingGroup: GuAutoScalingGroup;
|
|
311
180
|
readonly listener: GuHttpsApplicationListener;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/patterns/ec2-app/base.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/patterns/ec2-app/base.ts"],"names":[],"mappings":"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"}
|