@guardian/cdk 64.1.0 → 64.3.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.
Files changed (35) hide show
  1. package/lib/bin/commands/new-project/index.d.ts.map +1 -1
  2. package/lib/bin/commands/new-project/index.js +4 -2
  3. package/lib/bin/commands/new-project/index.js.map +1 -1
  4. package/lib/bin/commands/new-project/utils/imports.d.ts.map +1 -1
  5. package/lib/bin/commands/new-project/utils/imports.js +8 -0
  6. package/lib/bin/commands/new-project/utils/imports.js.map +1 -1
  7. package/lib/constructs/acm/certificate.js +1 -1
  8. package/lib/constructs/acm/certificate.js.map +1 -1
  9. package/lib/constructs/cloudwatch/api-gateway-alarms.js +1 -1
  10. package/lib/constructs/cloudwatch/api-gateway-alarms.js.map +1 -1
  11. package/lib/constructs/cloudwatch/ec2-alarms.js +3 -3
  12. package/lib/constructs/cloudwatch/ec2-alarms.js.map +1 -1
  13. package/lib/constructs/core/identity.d.ts +3 -1
  14. package/lib/constructs/core/identity.d.ts.map +1 -1
  15. package/lib/constructs/core/identity.js +8 -3
  16. package/lib/constructs/core/identity.js.map +1 -1
  17. package/lib/constructs/core/parameters/acm.js +1 -1
  18. package/lib/constructs/core/parameters/acm.js.map +1 -1
  19. package/lib/constructs/core/parameters/ec2.js +1 -1
  20. package/lib/constructs/core/parameters/ec2.js.map +1 -1
  21. package/lib/constructs/ecs/ecs-task.js +1 -1
  22. package/lib/constructs/ecs/ecs-task.js.map +1 -1
  23. package/lib/constructs/loadbalancing/alb/application-load-balancer.js +1 -1
  24. package/lib/constructs/loadbalancing/alb/application-load-balancer.js.map +1 -1
  25. package/lib/experimental/patterns/gu-load-balanced-app.d.ts.map +1 -1
  26. package/lib/experimental/patterns/gu-load-balanced-app.js +20 -13
  27. package/lib/experimental/patterns/gu-load-balanced-app.js.map +1 -1
  28. package/lib/patterns/ec2-app/base.js +1 -1
  29. package/lib/patterns/ec2-app/base.js.map +1 -1
  30. package/lib/utils/mixin/app-aware-construct.js +1 -1
  31. package/lib/utils/mixin/app-aware-construct.js.map +1 -1
  32. package/lib/utils/test/assertions.d.ts.map +1 -1
  33. package/lib/utils/test/assertions.js +5 -1
  34. package/lib/utils/test/assertions.js.map +1 -1
  35. package/package.json +17 -17
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/bin/commands/new-project/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAY7D,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,CAAC;AAE5C,UAAU,eAAe;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,cAAc,CAAC;CAChC;AAuED,eAAO,MAAM,aAAa,GAAU,OAAO,eAAe,KAAG,kBA4E5D,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/bin/commands/new-project/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAY7D,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,CAAC;AAE5C,UAAU,eAAe;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,cAAc,CAAC;CAChC;AAuED,eAAO,MAAM,aAAa,GAAU,OAAO,eAAe,KAAG,kBA8E5D,CAAC"}
@@ -106,8 +106,10 @@ const newCdkProject = async (props) => {
106
106
  await commands.installDependencies();
107
107
  console.log(chalk_1.default.green(" ✅ Successfully installed dependencies"));
108
108
  }
109
- // Run `eslint --fix` on the generated files instead of trying to generate code that completely satisfies the linter
110
- await (0, exec_1.execute)("./node_modules/.bin/eslint", ["lib/** bin/**", "--no-error-on-unmatched-pattern", "--fix"], {
109
+ // Run `eslint --fix` on the generated files instead of trying to generate code that completely satisfies the linter.
110
+ // Each glob must be a separate argument: `execute` uses `spawn` with `shell: false`, so a single
111
+ // "lib/** bin/**" string would be treated as one (non-matching) pattern and silently fixed nothing.
112
+ await (0, exec_1.execute)("./node_modules/.bin/eslint", ["lib/**", "bin/**", "--no-error-on-unmatched-pattern", "--fix"], {
111
113
  cwd: config.cdkDir,
112
114
  });
113
115
  console.log(chalk_1.default.yellow("Running lint check..."));
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/bin/commands/new-project/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"fs\";\nimport { basename, dirname, join } from \"path\";\nimport chalk from \"chalk\";\nimport type { CliCommandResponse } from \"../../../types/cli\";\nimport { execute } from \"../../../utils/exec\";\nimport { gitRootOrCwd } from \"../../../utils/git\";\nimport { toKebabCase, toPascalCase } from \"../../../utils/string\";\nimport { constructApp } from \"./utils/app\";\nimport { Imports } from \"./utils/imports\";\nimport { buildDirectory } from \"./utils/init\";\nimport { constructTest } from \"./utils/snapshot\";\nimport { constructStack } from \"./utils/stack\";\nimport type { Name } from \"./utils/utils\";\nimport { getCommands } from \"./utils/utils\";\n\nexport type PackageManager = \"npm\" | \"yarn\";\n\ninterface NewProjectProps {\n init: boolean;\n app: string;\n stack: string;\n stages: string[];\n regions: string[];\n yamlTemplateLocation?: string;\n packageManager: PackageManager;\n}\n\ninterface NewProjectConfig extends Omit<NewProjectProps, \"stack\" | \"app\"> {\n cdkDir: string;\n appPath: string;\n appName: Name;\n stackPath: string;\n stackName: Name;\n testPath: string;\n}\n\nconst checkPathExists = (path: string): void => {\n if (!existsSync(path)) {\n throw new Error(`File not found - ${path}`);\n }\n};\n\nconst checkPathDoesNotExist = (path: string): void => {\n if (existsSync(path)) {\n throw new Error(`There is already a file at - ${path}`);\n }\n};\n\nfunction validateConfig(config: NewProjectConfig): void {\n if (!config.init) {\n checkPathExists(config.cdkDir);\n }\n checkPathDoesNotExist(config.appPath); // TODO: Update the app file if it already exists\n checkPathDoesNotExist(config.stackPath);\n\n if (config.yamlTemplateLocation) {\n checkPathExists(config.yamlTemplateLocation);\n }\n}\n\nfunction getConfig(props: NewProjectProps): NewProjectConfig {\n const { init, app, stack, stages, regions, yamlTemplateLocation, packageManager } = props;\n\n const rootDir = gitRootOrCwd();\n const cdkDir = join(rootDir, \"/cdk\");\n\n const appName = toPascalCase(app);\n const kebabAppName = toKebabCase(appName);\n const stackName = toPascalCase(stack);\n const kebabStackName = toKebabCase(stackName);\n\n const config: NewProjectConfig = {\n init,\n yamlTemplateLocation,\n stages,\n regions,\n cdkDir,\n appName: {\n kebab: kebabAppName,\n pascal: appName,\n },\n appPath: `${cdkDir}/bin/${kebabAppName}.ts`,\n stackName: {\n kebab: kebabStackName,\n pascal: stackName,\n },\n stackPath: `${cdkDir}/lib/${kebabAppName}.ts`,\n testPath: `${cdkDir}/lib/${kebabAppName}.test.ts`,\n packageManager,\n };\n\n validateConfig(config);\n\n return config;\n}\n\nexport const newCdkProject = async (props: NewProjectProps): CliCommandResponse => {\n console.log(\"Starting CDK generator\");\n\n const config = getConfig(props);\n\n if (config.init) {\n buildDirectory({ outputDir: config.cdkDir });\n }\n\n console.log(`New app ${config.appName.pascal} will be written to ${config.appPath}`);\n console.log(`New stack ${config.stackName.pascal} will be written to ${config.stackPath}`);\n\n // bin directory\n await constructApp({\n appName: config.appName,\n outputFile: \"cdk.ts\",\n outputDir: dirname(config.appPath),\n stack: config.stackName,\n imports: Imports.newAppImports(config.appName),\n stages: config.stages,\n regions: config.regions,\n });\n\n // lib directory\n await constructStack({\n imports: Imports.newStackImports(!!config.yamlTemplateLocation),\n appName: config.appName,\n outputFile: basename(config.stackPath),\n outputDir: dirname(config.stackPath),\n yamlTemplateLocation: config.yamlTemplateLocation,\n });\n\n // lib directory\n await constructTest({\n imports: Imports.newTestImports(config.appName),\n stackName: config.stackName,\n appName: config.appName,\n outputFile: basename(config.testPath),\n outputDir: dirname(config.stackPath),\n });\n\n const commands = getCommands(config.packageManager, config.cdkDir);\n\n if (config.init) {\n console.log(chalk.yellow(\"Installing dependencies. This may take a while...\"));\n await commands.installDependencies();\n console.log(chalk.green(\" ✅ Successfully installed dependencies\"));\n }\n\n // Run `eslint --fix` on the generated files instead of trying to generate code that completely satisfies the linter\n await execute(\"./node_modules/.bin/eslint\", [\"lib/** bin/**\", \"--no-error-on-unmatched-pattern\", \"--fix\"], {\n cwd: config.cdkDir,\n });\n\n console.log(chalk.yellow(\"Running lint check...\"));\n await commands.lint();\n console.log(chalk.green(\" ✅ Successfully passed lint check\"));\n\n console.log(chalk.yellow(\"Running tests...\"));\n await commands.test();\n console.log(chalk.green(\" ✅ Successfully passed tests\"));\n\n console.log(chalk.yellow(\"Running initial synthesis...\"));\n await commands.synth();\n console.log(chalk.green(\" ✅ Successfully synthesized CDK app\"));\n\n console.log(chalk.green(\"Success! Here's a summary of the created files:\"));\n const tree = await execute(\"tree\", [\"-I\", \"node_modules|cdk.out\"], {\n cwd: config.cdkDir,\n });\n console.log(tree);\n\n const docsUrl = \"https://github.com/guardian/cdk/tree/main/docs\";\n console.log(chalk.green(`Please see the docs (${docsUrl}) for next steps.`));\n\n return Promise.resolve(0);\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/bin/commands/new-project/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"fs\";\nimport { basename, dirname, join } from \"path\";\nimport chalk from \"chalk\";\nimport type { CliCommandResponse } from \"../../../types/cli\";\nimport { execute } from \"../../../utils/exec\";\nimport { gitRootOrCwd } from \"../../../utils/git\";\nimport { toKebabCase, toPascalCase } from \"../../../utils/string\";\nimport { constructApp } from \"./utils/app\";\nimport { Imports } from \"./utils/imports\";\nimport { buildDirectory } from \"./utils/init\";\nimport { constructTest } from \"./utils/snapshot\";\nimport { constructStack } from \"./utils/stack\";\nimport type { Name } from \"./utils/utils\";\nimport { getCommands } from \"./utils/utils\";\n\nexport type PackageManager = \"npm\" | \"yarn\";\n\ninterface NewProjectProps {\n init: boolean;\n app: string;\n stack: string;\n stages: string[];\n regions: string[];\n yamlTemplateLocation?: string;\n packageManager: PackageManager;\n}\n\ninterface NewProjectConfig extends Omit<NewProjectProps, \"stack\" | \"app\"> {\n cdkDir: string;\n appPath: string;\n appName: Name;\n stackPath: string;\n stackName: Name;\n testPath: string;\n}\n\nconst checkPathExists = (path: string): void => {\n if (!existsSync(path)) {\n throw new Error(`File not found - ${path}`);\n }\n};\n\nconst checkPathDoesNotExist = (path: string): void => {\n if (existsSync(path)) {\n throw new Error(`There is already a file at - ${path}`);\n }\n};\n\nfunction validateConfig(config: NewProjectConfig): void {\n if (!config.init) {\n checkPathExists(config.cdkDir);\n }\n checkPathDoesNotExist(config.appPath); // TODO: Update the app file if it already exists\n checkPathDoesNotExist(config.stackPath);\n\n if (config.yamlTemplateLocation) {\n checkPathExists(config.yamlTemplateLocation);\n }\n}\n\nfunction getConfig(props: NewProjectProps): NewProjectConfig {\n const { init, app, stack, stages, regions, yamlTemplateLocation, packageManager } = props;\n\n const rootDir = gitRootOrCwd();\n const cdkDir = join(rootDir, \"/cdk\");\n\n const appName = toPascalCase(app);\n const kebabAppName = toKebabCase(appName);\n const stackName = toPascalCase(stack);\n const kebabStackName = toKebabCase(stackName);\n\n const config: NewProjectConfig = {\n init,\n yamlTemplateLocation,\n stages,\n regions,\n cdkDir,\n appName: {\n kebab: kebabAppName,\n pascal: appName,\n },\n appPath: `${cdkDir}/bin/${kebabAppName}.ts`,\n stackName: {\n kebab: kebabStackName,\n pascal: stackName,\n },\n stackPath: `${cdkDir}/lib/${kebabAppName}.ts`,\n testPath: `${cdkDir}/lib/${kebabAppName}.test.ts`,\n packageManager,\n };\n\n validateConfig(config);\n\n return config;\n}\n\nexport const newCdkProject = async (props: NewProjectProps): CliCommandResponse => {\n console.log(\"Starting CDK generator\");\n\n const config = getConfig(props);\n\n if (config.init) {\n buildDirectory({ outputDir: config.cdkDir });\n }\n\n console.log(`New app ${config.appName.pascal} will be written to ${config.appPath}`);\n console.log(`New stack ${config.stackName.pascal} will be written to ${config.stackPath}`);\n\n // bin directory\n await constructApp({\n appName: config.appName,\n outputFile: \"cdk.ts\",\n outputDir: dirname(config.appPath),\n stack: config.stackName,\n imports: Imports.newAppImports(config.appName),\n stages: config.stages,\n regions: config.regions,\n });\n\n // lib directory\n await constructStack({\n imports: Imports.newStackImports(!!config.yamlTemplateLocation),\n appName: config.appName,\n outputFile: basename(config.stackPath),\n outputDir: dirname(config.stackPath),\n yamlTemplateLocation: config.yamlTemplateLocation,\n });\n\n // lib directory\n await constructTest({\n imports: Imports.newTestImports(config.appName),\n stackName: config.stackName,\n appName: config.appName,\n outputFile: basename(config.testPath),\n outputDir: dirname(config.stackPath),\n });\n\n const commands = getCommands(config.packageManager, config.cdkDir);\n\n if (config.init) {\n console.log(chalk.yellow(\"Installing dependencies. This may take a while...\"));\n await commands.installDependencies();\n console.log(chalk.green(\" ✅ Successfully installed dependencies\"));\n }\n\n // Run `eslint --fix` on the generated files instead of trying to generate code that completely satisfies the linter.\n // Each glob must be a separate argument: `execute` uses `spawn` with `shell: false`, so a single\n // \"lib/** bin/**\" string would be treated as one (non-matching) pattern and silently fixed nothing.\n await execute(\"./node_modules/.bin/eslint\", [\"lib/**\", \"bin/**\", \"--no-error-on-unmatched-pattern\", \"--fix\"], {\n cwd: config.cdkDir,\n });\n\n console.log(chalk.yellow(\"Running lint check...\"));\n await commands.lint();\n console.log(chalk.green(\" ✅ Successfully passed lint check\"));\n\n console.log(chalk.yellow(\"Running tests...\"));\n await commands.test();\n console.log(chalk.green(\" ✅ Successfully passed tests\"));\n\n console.log(chalk.yellow(\"Running initial synthesis...\"));\n await commands.synth();\n console.log(chalk.green(\" ✅ Successfully synthesized CDK app\"));\n\n console.log(chalk.green(\"Success! Here's a summary of the created files:\"));\n const tree = await execute(\"tree\", [\"-I\", \"node_modules|cdk.out\"], {\n cwd: config.cdkDir,\n });\n console.log(tree);\n\n const docsUrl = \"https://github.com/guardian/cdk/tree/main/docs\";\n console.log(chalk.green(`Please see the docs (${docsUrl}) for next steps.`));\n\n return Promise.resolve(0);\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../../../../src/bin/commands/new-project/utils/imports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAQpC,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IAEjD,OAAO;WAIO,eAAe,CAAC,oBAAoB,EAAE,OAAO,GAAG,OAAO;WAuBvD,aAAa,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,GAAG,OAAO;WAkB/C,cAAc,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,GAAG,OAAO;IAiB9D,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;CAgC9B"}
1
+ {"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../../../../src/bin/commands/new-project/utils/imports.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAQpC,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IAEjD,OAAO;WAIO,eAAe,CAAC,oBAAoB,EAAE,OAAO,GAAG,OAAO;WAuBvD,aAAa,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,GAAG,OAAO;WAkB/C,cAAc,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,GAAG,OAAO;IAiB9D,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;CAqC9B"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Imports = void 0;
4
+ const node_module_1 = require("node:module");
4
5
  class Imports {
5
6
  constructor(imports) {
6
7
  this.imports = imports;
@@ -63,6 +64,7 @@ class Imports {
63
64
  render(code) {
64
65
  Object.entries(this.imports)
65
66
  // Render "basic" imports before any others, still in alphabetical order
67
+ // Render Node built-in imports before third-party imports (to satisfy `import/order`)
66
68
  // Render relative imports after absolute imports
67
69
  .sort(([aKey, aImports], [bKey, bImports]) => {
68
70
  if (aImports.basic && !bImports.basic) {
@@ -71,6 +73,12 @@ class Imports {
71
73
  else if (bImports.basic && !aImports.basic) {
72
74
  return 1;
73
75
  }
76
+ else if ((0, node_module_1.isBuiltin)(aKey) && !(0, node_module_1.isBuiltin)(bKey)) {
77
+ return -1;
78
+ }
79
+ else if ((0, node_module_1.isBuiltin)(bKey) && !(0, node_module_1.isBuiltin)(aKey)) {
80
+ return 1;
81
+ }
74
82
  else if (aKey.startsWith(".") && !bKey.startsWith(".")) {
75
83
  return 1;
76
84
  }
@@ -1 +1 @@
1
- {"version":3,"file":"imports.js","sourceRoot":"","sources":["../../../../../src/bin/commands/new-project/utils/imports.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CodeMaker } from \"codemaker\";\nimport type { Name } from \"./utils\";\n\ninterface Import {\n types: string[];\n components: string[];\n basic?: boolean;\n}\n\nexport class Imports {\n private readonly imports: Record<string, Import>;\n\n private constructor(imports: Record<string, Import>) {\n this.imports = imports;\n }\n\n public static newStackImports(addCfnIncludeImports: boolean): Imports {\n return new Imports({\n ...(addCfnIncludeImports && {\n path: {\n types: [],\n components: [\"join\"],\n },\n \"aws-cdk-lib/cloudformation-include\": {\n types: [],\n components: [\"CfnInclude\"],\n },\n }),\n \"aws-cdk-lib\": {\n types: [\"App\"],\n components: [],\n },\n \"@guardian/cdk/lib/constructs/core\": {\n types: [\"GuStackProps\"],\n components: [\"GuStack\"],\n },\n });\n }\n\n public static newAppImports({ kebab, pascal }: Name): Imports {\n return new Imports({\n \"source-map-support/register\": {\n basic: true,\n types: [],\n components: [],\n },\n \"@guardian/cdk/lib/constructs/root\": {\n types: [],\n components: [\"GuRoot\"],\n },\n [`../lib/${kebab}`]: {\n types: [],\n components: [pascal],\n },\n });\n }\n\n public static newTestImports({ kebab, pascal }: Name): Imports {\n return new Imports({\n \"aws-cdk-lib\": {\n types: [],\n components: [\"App\"],\n },\n \"aws-cdk-lib/assertions\": {\n types: [],\n components: [\"Template\"],\n },\n [`./${kebab}`]: {\n types: [],\n components: [pascal],\n },\n });\n }\n\n render(code: CodeMaker): void {\n Object.entries(this.imports)\n // Render \"basic\" imports before any others, still in alphabetical order\n // Render relative imports after absolute imports\n .sort(([aKey, aImports], [bKey, bImports]) => {\n if (aImports.basic && !bImports.basic) {\n return -1;\n } else if (bImports.basic && !aImports.basic) {\n return 1;\n } else if (aKey.startsWith(\".\") && !bKey.startsWith(\".\")) {\n return 1;\n } else if (bKey.startsWith(\".\") && !aKey.startsWith(\".\")) {\n return -1;\n } else {\n return aKey.localeCompare(bKey);\n }\n })\n .forEach(([lib, imports]) => {\n if (imports.basic) {\n code.line(`import \"${lib}\";`);\n }\n\n if (imports.types.length) {\n code.line(`import type { ${imports.types.sort().join(\", \")} } from \"${lib}\";`);\n }\n\n if (imports.components.length) {\n code.line(`import { ${imports.components.sort().join(\", \")} } from \"${lib}\";`);\n }\n });\n code.line();\n }\n}\n"]}
1
+ {"version":3,"file":"imports.js","sourceRoot":"","sources":["../../../../../src/bin/commands/new-project/utils/imports.ts"],"names":[],"mappings":"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","sourcesContent":["import { isBuiltin } from \"node:module\";\nimport type { CodeMaker } from \"codemaker\";\nimport type { Name } from \"./utils\";\n\ninterface Import {\n types: string[];\n components: string[];\n basic?: boolean;\n}\n\nexport class Imports {\n private readonly imports: Record<string, Import>;\n\n private constructor(imports: Record<string, Import>) {\n this.imports = imports;\n }\n\n public static newStackImports(addCfnIncludeImports: boolean): Imports {\n return new Imports({\n ...(addCfnIncludeImports && {\n path: {\n types: [],\n components: [\"join\"],\n },\n \"aws-cdk-lib/cloudformation-include\": {\n types: [],\n components: [\"CfnInclude\"],\n },\n }),\n \"aws-cdk-lib\": {\n types: [\"App\"],\n components: [],\n },\n \"@guardian/cdk/lib/constructs/core\": {\n types: [\"GuStackProps\"],\n components: [\"GuStack\"],\n },\n });\n }\n\n public static newAppImports({ kebab, pascal }: Name): Imports {\n return new Imports({\n \"source-map-support/register\": {\n basic: true,\n types: [],\n components: [],\n },\n \"@guardian/cdk/lib/constructs/root\": {\n types: [],\n components: [\"GuRoot\"],\n },\n [`../lib/${kebab}`]: {\n types: [],\n components: [pascal],\n },\n });\n }\n\n public static newTestImports({ kebab, pascal }: Name): Imports {\n return new Imports({\n \"aws-cdk-lib\": {\n types: [],\n components: [\"App\"],\n },\n \"aws-cdk-lib/assertions\": {\n types: [],\n components: [\"Template\"],\n },\n [`./${kebab}`]: {\n types: [],\n components: [pascal],\n },\n });\n }\n\n render(code: CodeMaker): void {\n Object.entries(this.imports)\n // Render \"basic\" imports before any others, still in alphabetical order\n // Render Node built-in imports before third-party imports (to satisfy `import/order`)\n // Render relative imports after absolute imports\n .sort(([aKey, aImports], [bKey, bImports]) => {\n if (aImports.basic && !bImports.basic) {\n return -1;\n } else if (bImports.basic && !aImports.basic) {\n return 1;\n } else if (isBuiltin(aKey) && !isBuiltin(bKey)) {\n return -1;\n } else if (isBuiltin(bKey) && !isBuiltin(aKey)) {\n return 1;\n } else if (aKey.startsWith(\".\") && !bKey.startsWith(\".\")) {\n return 1;\n } else if (bKey.startsWith(\".\") && !aKey.startsWith(\".\")) {\n return -1;\n } else {\n return aKey.localeCompare(bKey);\n }\n })\n .forEach(([lib, imports]) => {\n if (imports.basic) {\n code.line(`import \"${lib}\";`);\n }\n\n if (imports.types.length) {\n code.line(`import type { ${imports.types.sort().join(\", \")} } from \"${lib}\";`);\n }\n\n if (imports.components.length) {\n code.line(`import { ${imports.components.sort().join(\", \")} } from \"${lib}\";`);\n }\n });\n code.line();\n }\n}\n"]}
@@ -19,7 +19,7 @@ class GuCertificate extends (0, app_aware_construct_1.GuAppAwareConstruct)(aws_c
19
19
  constructor(scope, props) {
20
20
  const { app, domainName, hostedZoneId } = props;
21
21
  const maybeHostedZone = hostedZoneId
22
- ? aws_route53_1.HostedZone.fromHostedZoneId(scope, core_1.AppIdentity.suffixText({ app }, "HostedZone"), hostedZoneId)
22
+ ? aws_route53_1.HostedZone.fromHostedZoneId(scope, core_1.AppIdentity.addAppToStringEnd({ app }, "HostedZone"), hostedZoneId)
23
23
  : undefined;
24
24
  const awsCertificateProps = {
25
25
  domainName,
@@ -1 +1 @@
1
- {"version":3,"file":"certificate.js","sourceRoot":"","sources":["../../../src/constructs/acm/certificate.ts"],"names":[],"mappings":";;;AAAA,6CAA4C;AAC5C,+EAAwF;AAExF,yDAAqD;AAErD,+EAA4E;AAC5E,kCAAsC;AAKtC;;;;;;;;GAQG;AACH,MAAa,aAAc,SAAQ,IAAA,yCAAmB,EAAC,oCAAW,CAAC;IACjE,YAAY,KAAc,EAAE,KAAgC;QAC1D,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;QAEhD,MAAM,eAAe,GAAG,YAAY;YAClC,CAAC,CAAC,wBAAU,CAAC,gBAAgB,CAAC,KAAK,EAAE,kBAAW,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,EAAE,YAAY,CAAC,EAAE,YAAY,CAAC;YACjG,CAAC,CAAC,SAAS,CAAC;QAEd,MAAM,mBAAmB,GAAmC;YAC1D,UAAU;YACV,UAAU,EAAE,8CAAqB,CAAC,OAAO,CAAC,eAAe,CAAC;YAC1D,GAAG;SACJ,CAAC;QACF,KAAK,CAAC,KAAK,EAAE,aAAa,EAAE,mBAAmB,CAAC,CAAC;QACjD,IAAI,CAAC,kBAAkB,CAAC,2BAAa,CAAC,MAAM,CAAC,CAAC;IAChD,CAAC;CACF;AAhBD,sCAgBC","sourcesContent":["import { RemovalPolicy } from \"aws-cdk-lib\";\nimport { Certificate, CertificateValidation } from \"aws-cdk-lib/aws-certificatemanager\";\nimport type { CertificateProps } from \"aws-cdk-lib/aws-certificatemanager/lib/certificate\";\nimport { HostedZone } from \"aws-cdk-lib/aws-route53\";\nimport type { GuDomainName } from \"../../types\";\nimport { GuAppAwareConstruct } from \"../../utils/mixin/app-aware-construct\";\nimport { AppIdentity } from \"../core\";\nimport type { GuStack } from \"../core\";\n\nexport type GuCertificatePropsWithApp = GuDomainName & AppIdentity;\n\n/**\n * Construct which creates a DNS-validated ACM Certificate.\n *\n * If your DNS is managed via Route 53, then supplying `hostedZoneId` props will allow AWS to automatically\n * validate your certificate.\n *\n * If your DNS is not managed via Route 53, or you omit the `hostedZoneId` props, then the CloudFormation\n * operation which adds this construct will pause until the relevant DNS record has been added manually.\n */\nexport class GuCertificate extends GuAppAwareConstruct(Certificate) {\n constructor(scope: GuStack, props: GuCertificatePropsWithApp) {\n const { app, domainName, hostedZoneId } = props;\n\n const maybeHostedZone = hostedZoneId\n ? HostedZone.fromHostedZoneId(scope, AppIdentity.suffixText({ app }, \"HostedZone\"), hostedZoneId)\n : undefined;\n\n const awsCertificateProps: CertificateProps & AppIdentity = {\n domainName,\n validation: CertificateValidation.fromDns(maybeHostedZone),\n app,\n };\n super(scope, \"Certificate\", awsCertificateProps);\n this.applyRemovalPolicy(RemovalPolicy.RETAIN);\n }\n}\n"]}
1
+ {"version":3,"file":"certificate.js","sourceRoot":"","sources":["../../../src/constructs/acm/certificate.ts"],"names":[],"mappings":";;;AAAA,6CAA4C;AAC5C,+EAAwF;AAExF,yDAAqD;AAErD,+EAA4E;AAC5E,kCAAsC;AAKtC;;;;;;;;GAQG;AACH,MAAa,aAAc,SAAQ,IAAA,yCAAmB,EAAC,oCAAW,CAAC;IACjE,YAAY,KAAc,EAAE,KAAgC;QAC1D,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;QAEhD,MAAM,eAAe,GAAG,YAAY;YAClC,CAAC,CAAC,wBAAU,CAAC,gBAAgB,CAAC,KAAK,EAAE,kBAAW,CAAC,iBAAiB,CAAC,EAAE,GAAG,EAAE,EAAE,YAAY,CAAC,EAAE,YAAY,CAAC;YACxG,CAAC,CAAC,SAAS,CAAC;QAEd,MAAM,mBAAmB,GAAmC;YAC1D,UAAU;YACV,UAAU,EAAE,8CAAqB,CAAC,OAAO,CAAC,eAAe,CAAC;YAC1D,GAAG;SACJ,CAAC;QACF,KAAK,CAAC,KAAK,EAAE,aAAa,EAAE,mBAAmB,CAAC,CAAC;QACjD,IAAI,CAAC,kBAAkB,CAAC,2BAAa,CAAC,MAAM,CAAC,CAAC;IAChD,CAAC;CACF;AAhBD,sCAgBC","sourcesContent":["import { RemovalPolicy } from \"aws-cdk-lib\";\nimport { Certificate, CertificateValidation } from \"aws-cdk-lib/aws-certificatemanager\";\nimport type { CertificateProps } from \"aws-cdk-lib/aws-certificatemanager/lib/certificate\";\nimport { HostedZone } from \"aws-cdk-lib/aws-route53\";\nimport type { GuDomainName } from \"../../types\";\nimport { GuAppAwareConstruct } from \"../../utils/mixin/app-aware-construct\";\nimport { AppIdentity } from \"../core\";\nimport type { GuStack } from \"../core\";\n\nexport type GuCertificatePropsWithApp = GuDomainName & AppIdentity;\n\n/**\n * Construct which creates a DNS-validated ACM Certificate.\n *\n * If your DNS is managed via Route 53, then supplying `hostedZoneId` props will allow AWS to automatically\n * validate your certificate.\n *\n * If your DNS is not managed via Route 53, or you omit the `hostedZoneId` props, then the CloudFormation\n * operation which adds this construct will pause until the relevant DNS record has been added manually.\n */\nexport class GuCertificate extends GuAppAwareConstruct(Certificate) {\n constructor(scope: GuStack, props: GuCertificatePropsWithApp) {\n const { app, domainName, hostedZoneId } = props;\n\n const maybeHostedZone = hostedZoneId\n ? HostedZone.fromHostedZoneId(scope, AppIdentity.addAppToStringEnd({ app }, \"HostedZone\"), hostedZoneId)\n : undefined;\n\n const awsCertificateProps: CertificateProps & AppIdentity = {\n domainName,\n validation: CertificateValidation.fromDns(maybeHostedZone),\n app,\n };\n super(scope, \"Certificate\", awsCertificateProps);\n this.applyRemovalPolicy(RemovalPolicy.RETAIN);\n }\n}\n"]}
@@ -32,7 +32,7 @@ class GuApiGateway5xxPercentageAlarm extends alarm_1.GuAlarm {
32
32
  alarmDescription: props.alarmDescription ?? defaultDescription,
33
33
  evaluationPeriods: props.numberOfMinutesAboveThresholdBeforeAlarm ?? 1,
34
34
  };
35
- super(scope, core_1.AppIdentity.suffixText(props, "ApiGatewayHigh5xxPercentageAlarm"), alarmProps);
35
+ super(scope, core_1.AppIdentity.addAppToStringEnd(props, "ApiGatewayHigh5xxPercentageAlarm"), alarmProps);
36
36
  }
37
37
  }
38
38
  exports.GuApiGateway5xxPercentageAlarm = GuApiGateway5xxPercentageAlarm;
@@ -1 +1 @@
1
- {"version":3,"file":"api-gateway-alarms.js","sourceRoot":"","sources":["../../../src/constructs/cloudwatch/api-gateway-alarms.ts"],"names":[],"mappings":";;;AAAA,6CAAuC;AAEvC,+DAAkG;AAElG,kCAAsC;AAEtC,mCAAkC;AAOlC;;;GAGG;AACH,MAAa,8BAA+B,SAAQ,eAAO;IACzD,YAAY,KAAc,EAAE,KAA0C;QACpE,MAAM,cAAc,GAAG,IAAI,+BAAc,CAAC;YACxC,UAAU,EAAE,WAAW;YACvB,YAAY,EAAE;gBACZ,EAAE,EAAE,KAAK,CAAC,kBAAkB,CAAC,iBAAiB,EAAE;gBAChD,EAAE,EAAE,KAAK,CAAC,kBAAkB,CAAC,WAAW,EAAE;aAC3C;YACD,KAAK,EAAE,iCAAiC,KAAK,CAAC,GAAG,EAAE;YACnD,MAAM,EAAE,sBAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;SAC5B,CAAC,CAAC;QACH,MAAM,gBAAgB,GAAG,kCAAkC,KAAK,CAAC,GAAG,oBAAoB,KAAK,CAAC,KAAK,EAAE,CAAC;QACtG,MAAM,kBAAkB,GAAG,GAAG,KAAK,CAAC,GAAG,aAAa,KAAK,CAAC,sBAAsB,cAAc,CAAC;QAC/F,MAAM,UAAU,GAAG;YACjB,GAAG,KAAK;YACR,MAAM,EAAE,cAAc;YACtB,gBAAgB,EAAE,iCAAgB,CAAC,aAAa;YAChD,SAAS,EAAE,KAAK,CAAC,sBAAsB;YACvC,kBAAkB,EAAE,mCAAkB,CAAC,sBAAsB;YAC7D,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,gBAAgB;YAC9C,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,IAAI,kBAAkB;YAC9D,iBAAiB,EAAE,KAAK,CAAC,wCAAwC,IAAI,CAAC;SACvE,CAAC;QACF,KAAK,CAAC,KAAK,EAAE,kBAAW,CAAC,UAAU,CAAC,KAAK,EAAE,kCAAkC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC9F,CAAC;CACF;AAzBD,wEAyBC","sourcesContent":["import { Duration } from \"aws-cdk-lib\";\nimport type { RestApi } from \"aws-cdk-lib/aws-apigateway\";\nimport { ComparisonOperator, MathExpression, TreatMissingData } from \"aws-cdk-lib/aws-cloudwatch\";\nimport type { GuStack } from \"../core\";\nimport { AppIdentity } from \"../core\";\nimport type { GuAlarmProps, Http5xxAlarmProps } from \"./alarm\";\nimport { GuAlarm } from \"./alarm\";\n\ninterface GuApiGateway5xxPercentageAlarmProps\n extends Pick<GuAlarmProps, \"snsTopicName\">, Http5xxAlarmProps, AppIdentity {\n apiGatewayInstance: RestApi;\n}\n\n/**\n * Creates an alarm which is triggered whenever the percentage of requests with a 5xx response code exceeds\n * the specified threshold.\n */\nexport class GuApiGateway5xxPercentageAlarm extends GuAlarm {\n constructor(scope: GuStack, props: GuApiGateway5xxPercentageAlarmProps) {\n const mathExpression = new MathExpression({\n expression: \"100*m1/m2\",\n usingMetrics: {\n m1: props.apiGatewayInstance.metricServerError(),\n m2: props.apiGatewayInstance.metricCount(),\n },\n label: `% of 5XX responses served for ${props.app}`,\n period: Duration.minutes(1),\n });\n const defaultAlarmName = `High 5XX error percentage from ${props.app} (ApiGateway) in ${scope.stage}`;\n const defaultDescription = `${props.app} exceeded ${props.tolerated5xxPercentage}% error rate`;\n const alarmProps = {\n ...props,\n metric: mathExpression,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n threshold: props.tolerated5xxPercentage,\n comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,\n alarmName: props.alarmName ?? defaultAlarmName,\n alarmDescription: props.alarmDescription ?? defaultDescription,\n evaluationPeriods: props.numberOfMinutesAboveThresholdBeforeAlarm ?? 1,\n };\n super(scope, AppIdentity.suffixText(props, \"ApiGatewayHigh5xxPercentageAlarm\"), alarmProps);\n }\n}\n"]}
1
+ {"version":3,"file":"api-gateway-alarms.js","sourceRoot":"","sources":["../../../src/constructs/cloudwatch/api-gateway-alarms.ts"],"names":[],"mappings":";;;AAAA,6CAAuC;AAEvC,+DAAkG;AAElG,kCAAsC;AAEtC,mCAAkC;AAOlC;;;GAGG;AACH,MAAa,8BAA+B,SAAQ,eAAO;IACzD,YAAY,KAAc,EAAE,KAA0C;QACpE,MAAM,cAAc,GAAG,IAAI,+BAAc,CAAC;YACxC,UAAU,EAAE,WAAW;YACvB,YAAY,EAAE;gBACZ,EAAE,EAAE,KAAK,CAAC,kBAAkB,CAAC,iBAAiB,EAAE;gBAChD,EAAE,EAAE,KAAK,CAAC,kBAAkB,CAAC,WAAW,EAAE;aAC3C;YACD,KAAK,EAAE,iCAAiC,KAAK,CAAC,GAAG,EAAE;YACnD,MAAM,EAAE,sBAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;SAC5B,CAAC,CAAC;QACH,MAAM,gBAAgB,GAAG,kCAAkC,KAAK,CAAC,GAAG,oBAAoB,KAAK,CAAC,KAAK,EAAE,CAAC;QACtG,MAAM,kBAAkB,GAAG,GAAG,KAAK,CAAC,GAAG,aAAa,KAAK,CAAC,sBAAsB,cAAc,CAAC;QAC/F,MAAM,UAAU,GAAG;YACjB,GAAG,KAAK;YACR,MAAM,EAAE,cAAc;YACtB,gBAAgB,EAAE,iCAAgB,CAAC,aAAa;YAChD,SAAS,EAAE,KAAK,CAAC,sBAAsB;YACvC,kBAAkB,EAAE,mCAAkB,CAAC,sBAAsB;YAC7D,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,gBAAgB;YAC9C,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,IAAI,kBAAkB;YAC9D,iBAAiB,EAAE,KAAK,CAAC,wCAAwC,IAAI,CAAC;SACvE,CAAC;QACF,KAAK,CAAC,KAAK,EAAE,kBAAW,CAAC,iBAAiB,CAAC,KAAK,EAAE,kCAAkC,CAAC,EAAE,UAAU,CAAC,CAAC;IACrG,CAAC;CACF;AAzBD,wEAyBC","sourcesContent":["import { Duration } from \"aws-cdk-lib\";\nimport type { RestApi } from \"aws-cdk-lib/aws-apigateway\";\nimport { ComparisonOperator, MathExpression, TreatMissingData } from \"aws-cdk-lib/aws-cloudwatch\";\nimport type { GuStack } from \"../core\";\nimport { AppIdentity } from \"../core\";\nimport type { GuAlarmProps, Http5xxAlarmProps } from \"./alarm\";\nimport { GuAlarm } from \"./alarm\";\n\ninterface GuApiGateway5xxPercentageAlarmProps\n extends Pick<GuAlarmProps, \"snsTopicName\">, Http5xxAlarmProps, AppIdentity {\n apiGatewayInstance: RestApi;\n}\n\n/**\n * Creates an alarm which is triggered whenever the percentage of requests with a 5xx response code exceeds\n * the specified threshold.\n */\nexport class GuApiGateway5xxPercentageAlarm extends GuAlarm {\n constructor(scope: GuStack, props: GuApiGateway5xxPercentageAlarmProps) {\n const mathExpression = new MathExpression({\n expression: \"100*m1/m2\",\n usingMetrics: {\n m1: props.apiGatewayInstance.metricServerError(),\n m2: props.apiGatewayInstance.metricCount(),\n },\n label: `% of 5XX responses served for ${props.app}`,\n period: Duration.minutes(1),\n });\n const defaultAlarmName = `High 5XX error percentage from ${props.app} (ApiGateway) in ${scope.stage}`;\n const defaultDescription = `${props.app} exceeded ${props.tolerated5xxPercentage}% error rate`;\n const alarmProps = {\n ...props,\n metric: mathExpression,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n threshold: props.tolerated5xxPercentage,\n comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,\n alarmName: props.alarmName ?? defaultAlarmName,\n alarmDescription: props.alarmDescription ?? defaultDescription,\n evaluationPeriods: props.numberOfMinutesAboveThresholdBeforeAlarm ?? 1,\n };\n super(scope, AppIdentity.addAppToStringEnd(props, \"ApiGatewayHigh5xxPercentageAlarm\"), alarmProps);\n }\n}\n"]}
@@ -34,7 +34,7 @@ class GuAlb5xxPercentageAlarm extends alarm_1.GuAlarm {
34
34
  alarmDescription: props.alarmDescription ?? defaultDescription,
35
35
  evaluationPeriods: props.numberOfMinutesAboveThresholdBeforeAlarm ?? 1,
36
36
  };
37
- super(scope, core_1.AppIdentity.suffixText(props, "High5xxPercentageAlarm"), alarmProps);
37
+ super(scope, core_1.AppIdentity.addAppToStringEnd(props, "High5xxPercentageAlarm"), alarmProps);
38
38
  }
39
39
  }
40
40
  exports.GuAlb5xxPercentageAlarm = GuAlb5xxPercentageAlarm;
@@ -66,7 +66,7 @@ class GuAlb4xxPercentageAlarm extends alarm_1.GuAlarm {
66
66
  alarmDescription: props.alarmDescription ?? defaultDescription,
67
67
  evaluationPeriods: props.numberOfMinutesAboveThresholdBeforeAlarm ?? 1,
68
68
  };
69
- super(scope, core_1.AppIdentity.suffixText(props, "High4xxPercentageAlarm"), alarmProps);
69
+ super(scope, core_1.AppIdentity.addAppToStringEnd(props, "High4xxPercentageAlarm"), alarmProps);
70
70
  }
71
71
  }
72
72
  exports.GuAlb4xxPercentageAlarm = GuAlb4xxPercentageAlarm;
@@ -95,7 +95,7 @@ class GuUnhealthyInstancesAlarm extends alarm_1.GuAlarm {
95
95
  datapointsToAlarm: 30,
96
96
  evaluationPeriods,
97
97
  };
98
- super(scope, core_1.AppIdentity.suffixText(props, "UnhealthyInstancesAlarm"), alarmProps);
98
+ super(scope, core_1.AppIdentity.addAppToStringEnd(props, "UnhealthyInstancesAlarm"), alarmProps);
99
99
  }
100
100
  }
101
101
  exports.GuUnhealthyInstancesAlarm = GuUnhealthyInstancesAlarm;
@@ -1 +1 @@
1
- {"version":3,"file":"ec2-alarms.js","sourceRoot":"","sources":["../../../src/constructs/cloudwatch/ec2-alarms.ts"],"names":[],"mappings":"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","sourcesContent":["import { Duration } from \"aws-cdk-lib\";\nimport { ComparisonOperator, MathExpression, Statistic, TreatMissingData } from \"aws-cdk-lib/aws-cloudwatch\";\nimport { HttpCodeElb, HttpCodeTarget } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport type { GuStack } from \"../core\";\nimport { AppIdentity } from \"../core\";\nimport type { GuApplicationLoadBalancer, GuApplicationTargetGroup } from \"../loadbalancing\";\nimport { GuAlarm } from \"./alarm\";\nimport type { GuAlarmProps, Http4xxAlarmProps, Http5xxAlarmProps } from \"./alarm\";\n\ninterface GuAlb4xxPercentageAlarmProps extends Pick<GuAlarmProps, \"snsTopicName\">, Http4xxAlarmProps, AppIdentity {\n loadBalancer: GuApplicationLoadBalancer;\n}\ninterface GuAlb5xxPercentageAlarmProps extends Pick<GuAlarmProps, \"snsTopicName\">, Http5xxAlarmProps, AppIdentity {\n loadBalancer: GuApplicationLoadBalancer;\n}\n\ninterface GuUnhealthyInstancesAlarmProps extends Pick<GuAlarmProps, \"snsTopicName\" | \"actionsEnabled\">, AppIdentity {\n targetGroup: GuApplicationTargetGroup;\n}\n\n/**\n * Creates an alarm which is triggered whenever the percentage of requests with a 5xx response code exceeds\n * the specified threshold.\n */\nexport class GuAlb5xxPercentageAlarm extends GuAlarm {\n constructor(scope: GuStack, props: GuAlb5xxPercentageAlarmProps) {\n const mathExpression = new MathExpression({\n expression: \"100*(m1+m2)/m3\",\n usingMetrics: {\n m1: props.loadBalancer.metrics.httpCodeElb(HttpCodeElb.ELB_5XX_COUNT),\n m2: props.loadBalancer.metrics.httpCodeTarget(HttpCodeTarget.TARGET_5XX_COUNT),\n m3: props.loadBalancer.metrics.requestCount(),\n },\n label: `% of 5XX responses served for ${props.app} (load balancer and instances combined)`,\n period: Duration.minutes(1),\n });\n const defaultAlarmName = `High 5XX error percentage from ${props.app} in ${scope.stage}`;\n const defaultDescription = `${props.app} exceeded ${props.tolerated5xxPercentage}% error rate`;\n const alarmProps = {\n ...props,\n metric: mathExpression,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n threshold: props.tolerated5xxPercentage,\n comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,\n alarmName: props.alarmName ?? defaultAlarmName,\n alarmDescription: props.alarmDescription ?? defaultDescription,\n evaluationPeriods: props.numberOfMinutesAboveThresholdBeforeAlarm ?? 1,\n };\n super(scope, AppIdentity.suffixText(props, \"High5xxPercentageAlarm\"), alarmProps);\n }\n}\n\n/**\n * Creates an alarm which is triggered whenever the percentage of requests with a 4xx response code exceeds\n * the specified threshold.\n */\nexport class GuAlb4xxPercentageAlarm extends GuAlarm {\n constructor(scope: GuStack, props: GuAlb4xxPercentageAlarmProps) {\n const mathExpression = new MathExpression({\n expression: \"100*(m1+m2)/m3\",\n usingMetrics: {\n m1: props.loadBalancer.metrics.httpCodeElb(HttpCodeElb.ELB_4XX_COUNT),\n m2: props.loadBalancer.metrics.httpCodeTarget(HttpCodeTarget.TARGET_4XX_COUNT),\n m3: props.loadBalancer.metrics.requestCount(),\n },\n label: `% of 4XX responses served for ${props.app} (load balancer and instances combined)`,\n period: Duration.minutes(1),\n });\n const defaultAlarmName = `High 4XX error percentage from ${props.app} in ${scope.stage}`;\n const defaultDescription = `${props.app} exceeded ${props.tolerated4xxPercentage}% error rate`;\n const alarmProps = {\n ...props,\n metric: mathExpression,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n threshold: props.tolerated4xxPercentage,\n comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,\n alarmName: props.alarmName ?? defaultAlarmName,\n alarmDescription: props.alarmDescription ?? defaultDescription,\n evaluationPeriods: props.numberOfMinutesAboveThresholdBeforeAlarm ?? 1,\n };\n super(scope, AppIdentity.suffixText(props, \"High4xxPercentageAlarm\"), alarmProps);\n }\n}\n\n/**\n * Creates an alarm which is triggered whenever there have been several healthcheck failures within a single hour.\n */\nexport class GuUnhealthyInstancesAlarm extends GuAlarm {\n constructor(scope: GuStack, props: GuUnhealthyInstancesAlarmProps) {\n const alarmName = `Unhealthy instances for ${props.app} in ${scope.stage}`;\n\n const period = Duration.minutes(1);\n const evaluationPeriods = 60;\n const evaluationInterval = Duration.minutes(period.toMinutes() * evaluationPeriods).toHumanString();\n\n const alarmDescription = `${props.app}'s instances have failed healthchecks several times over the last ${evaluationInterval}.\n This typically results in the AutoScaling Group cycling instances and can lead to problems with deployment,\n scaling or handling traffic spikes.\n\n Check ${props.app}'s application logs or ssh onto an unhealthy instance in order to debug these problems.`;\n const alarmProps: GuAlarmProps = {\n ...props,\n alarmName: alarmName,\n alarmDescription: alarmDescription,\n metric: props.targetGroup.metrics.unhealthyHostCount().with({ period, statistic: Statistic.MAXIMUM }),\n treatMissingData: TreatMissingData.NOT_BREACHING,\n threshold: 1,\n comparisonOperator: ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,\n datapointsToAlarm: 30,\n evaluationPeriods,\n };\n super(scope, AppIdentity.suffixText(props, \"UnhealthyInstancesAlarm\"), alarmProps);\n }\n}\n"]}
1
+ {"version":3,"file":"ec2-alarms.js","sourceRoot":"","sources":["../../../src/constructs/cloudwatch/ec2-alarms.ts"],"names":[],"mappings":"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","sourcesContent":["import { Duration } from \"aws-cdk-lib\";\nimport { ComparisonOperator, MathExpression, Statistic, TreatMissingData } from \"aws-cdk-lib/aws-cloudwatch\";\nimport { HttpCodeElb, HttpCodeTarget } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport type { GuStack } from \"../core\";\nimport { AppIdentity } from \"../core\";\nimport type { GuApplicationLoadBalancer, GuApplicationTargetGroup } from \"../loadbalancing\";\nimport { GuAlarm } from \"./alarm\";\nimport type { GuAlarmProps, Http4xxAlarmProps, Http5xxAlarmProps } from \"./alarm\";\n\ninterface GuAlb4xxPercentageAlarmProps extends Pick<GuAlarmProps, \"snsTopicName\">, Http4xxAlarmProps, AppIdentity {\n loadBalancer: GuApplicationLoadBalancer;\n}\ninterface GuAlb5xxPercentageAlarmProps extends Pick<GuAlarmProps, \"snsTopicName\">, Http5xxAlarmProps, AppIdentity {\n loadBalancer: GuApplicationLoadBalancer;\n}\n\ninterface GuUnhealthyInstancesAlarmProps extends Pick<GuAlarmProps, \"snsTopicName\" | \"actionsEnabled\">, AppIdentity {\n targetGroup: GuApplicationTargetGroup;\n}\n\n/**\n * Creates an alarm which is triggered whenever the percentage of requests with a 5xx response code exceeds\n * the specified threshold.\n */\nexport class GuAlb5xxPercentageAlarm extends GuAlarm {\n constructor(scope: GuStack, props: GuAlb5xxPercentageAlarmProps) {\n const mathExpression = new MathExpression({\n expression: \"100*(m1+m2)/m3\",\n usingMetrics: {\n m1: props.loadBalancer.metrics.httpCodeElb(HttpCodeElb.ELB_5XX_COUNT),\n m2: props.loadBalancer.metrics.httpCodeTarget(HttpCodeTarget.TARGET_5XX_COUNT),\n m3: props.loadBalancer.metrics.requestCount(),\n },\n label: `% of 5XX responses served for ${props.app} (load balancer and instances combined)`,\n period: Duration.minutes(1),\n });\n const defaultAlarmName = `High 5XX error percentage from ${props.app} in ${scope.stage}`;\n const defaultDescription = `${props.app} exceeded ${props.tolerated5xxPercentage}% error rate`;\n const alarmProps = {\n ...props,\n metric: mathExpression,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n threshold: props.tolerated5xxPercentage,\n comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,\n alarmName: props.alarmName ?? defaultAlarmName,\n alarmDescription: props.alarmDescription ?? defaultDescription,\n evaluationPeriods: props.numberOfMinutesAboveThresholdBeforeAlarm ?? 1,\n };\n super(scope, AppIdentity.addAppToStringEnd(props, \"High5xxPercentageAlarm\"), alarmProps);\n }\n}\n\n/**\n * Creates an alarm which is triggered whenever the percentage of requests with a 4xx response code exceeds\n * the specified threshold.\n */\nexport class GuAlb4xxPercentageAlarm extends GuAlarm {\n constructor(scope: GuStack, props: GuAlb4xxPercentageAlarmProps) {\n const mathExpression = new MathExpression({\n expression: \"100*(m1+m2)/m3\",\n usingMetrics: {\n m1: props.loadBalancer.metrics.httpCodeElb(HttpCodeElb.ELB_4XX_COUNT),\n m2: props.loadBalancer.metrics.httpCodeTarget(HttpCodeTarget.TARGET_4XX_COUNT),\n m3: props.loadBalancer.metrics.requestCount(),\n },\n label: `% of 4XX responses served for ${props.app} (load balancer and instances combined)`,\n period: Duration.minutes(1),\n });\n const defaultAlarmName = `High 4XX error percentage from ${props.app} in ${scope.stage}`;\n const defaultDescription = `${props.app} exceeded ${props.tolerated4xxPercentage}% error rate`;\n const alarmProps = {\n ...props,\n metric: mathExpression,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n threshold: props.tolerated4xxPercentage,\n comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,\n alarmName: props.alarmName ?? defaultAlarmName,\n alarmDescription: props.alarmDescription ?? defaultDescription,\n evaluationPeriods: props.numberOfMinutesAboveThresholdBeforeAlarm ?? 1,\n };\n super(scope, AppIdentity.addAppToStringEnd(props, \"High4xxPercentageAlarm\"), alarmProps);\n }\n}\n\n/**\n * Creates an alarm which is triggered whenever there have been several healthcheck failures within a single hour.\n */\nexport class GuUnhealthyInstancesAlarm extends GuAlarm {\n constructor(scope: GuStack, props: GuUnhealthyInstancesAlarmProps) {\n const alarmName = `Unhealthy instances for ${props.app} in ${scope.stage}`;\n\n const period = Duration.minutes(1);\n const evaluationPeriods = 60;\n const evaluationInterval = Duration.minutes(period.toMinutes() * evaluationPeriods).toHumanString();\n\n const alarmDescription = `${props.app}'s instances have failed healthchecks several times over the last ${evaluationInterval}.\n This typically results in the AutoScaling Group cycling instances and can lead to problems with deployment,\n scaling or handling traffic spikes.\n\n Check ${props.app}'s application logs or ssh onto an unhealthy instance in order to debug these problems.`;\n const alarmProps: GuAlarmProps = {\n ...props,\n alarmName: alarmName,\n alarmDescription: alarmDescription,\n metric: props.targetGroup.metrics.unhealthyHostCount().with({ period, statistic: Statistic.MAXIMUM }),\n treatMissingData: TreatMissingData.NOT_BREACHING,\n threshold: 1,\n comparisonOperator: ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,\n datapointsToAlarm: 30,\n evaluationPeriods,\n };\n super(scope, AppIdentity.addAppToStringEnd(props, \"UnhealthyInstancesAlarm\"), alarmProps);\n }\n}\n"]}
@@ -10,7 +10,9 @@ export interface Identity extends StackStageIdentity, AppIdentity {
10
10
  }
11
11
  export declare const AppIdentity: {
12
12
  isAppIdentity(props: any): props is AppIdentity;
13
- suffixText(appIdentity: AppIdentity, text: string): string;
13
+ toAlphanumericTitleCase(appIdentity: AppIdentity): string;
14
+ addAppToStringEnd(appIdentity: AppIdentity, text: string): string;
15
+ addAppToStringStart(appIdentity: AppIdentity, text: string): string;
14
16
  taggedConstruct<T extends IConstruct>(appIdentity: AppIdentity, construct: T): T;
15
17
  };
16
18
  //# sourceMappingURL=identity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../../src/constructs/core/identity.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,QAAS,SAAQ,kBAAkB,EAAE,WAAW;CAAG;AAEpE,eAAO,MAAM,WAAW;yBAED,GAAG,GAAG,KAAK,IAAI,WAAW;4BAIvB,WAAW,QAAQ,MAAM,GAAG,MAAM;oBAM1C,CAAC,SAAS,UAAU,eAAe,WAAW,aAAa,CAAC,GAAG,CAAC;CAIjF,CAAC"}
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../../src/constructs/core/identity.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,QAAS,SAAQ,kBAAkB,EAAE,WAAW;CAAG;AAEpE,eAAO,MAAM,WAAW;yBAED,GAAG,GAAG,KAAK,IAAI,WAAW;yCAIV,WAAW;mCAMjB,WAAW,QAAQ,MAAM,GAAG,MAAM;qCAIhC,WAAW,QAAQ,MAAM,GAAG,MAAM;oBAInD,CAAC,SAAS,UAAU,eAAe,WAAW,aAAa,CAAC,GAAG,CAAC;CAIjF,CAAC"}
@@ -7,11 +7,16 @@ exports.AppIdentity = {
7
7
  isAppIdentity(props) {
8
8
  return props ? "app" in props : false;
9
9
  },
10
- suffixText(appIdentity, text) {
10
+ toAlphanumericTitleCase(appIdentity) {
11
11
  const titleCaseApp = appIdentity.app.charAt(0).toUpperCase() + appIdentity.app.slice(1);
12
12
  // CloudFormation Logical Ids must be alphanumeric, so remove any non-alphanumeric characters: https://stackoverflow.com/a/20864946
13
- const alphanumericTitleCaseApp = titleCaseApp.replace(/[\W_]+/g, "");
14
- return `${text}${alphanumericTitleCaseApp}`;
13
+ return titleCaseApp.replace(/[\W_]+/g, "");
14
+ },
15
+ addAppToStringEnd(appIdentity, text) {
16
+ return [text, exports.AppIdentity.toAlphanumericTitleCase(appIdentity)].join("");
17
+ },
18
+ addAppToStringStart(appIdentity, text) {
19
+ return [exports.AppIdentity.toAlphanumericTitleCase(appIdentity), text].join("");
15
20
  },
16
21
  taggedConstruct(appIdentity, construct) {
17
22
  aws_cdk_lib_1.Tags.of(construct).add("App", appIdentity.app);
@@ -1 +1 @@
1
- {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../src/constructs/core/identity.ts"],"names":[],"mappings":";;;AAAA,6CAAmC;AActB,QAAA,WAAW,GAAG;IACzB,yFAAyF;IACzF,aAAa,CAAC,KAAU;QACtB,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACxC,CAAC;IAED,UAAU,CAAC,WAAwB,EAAE,IAAY;QAC/C,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACxF,mIAAmI;QACnI,MAAM,wBAAwB,GAAG,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACrE,OAAO,GAAG,IAAI,GAAG,wBAAwB,EAAE,CAAC;IAC9C,CAAC;IACD,eAAe,CAAuB,WAAwB,EAAE,SAAY;QAC1E,kBAAI,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,SAAS,CAAC;IACnB,CAAC;CACF,CAAC","sourcesContent":["import { Tags } from \"aws-cdk-lib\";\nimport type { IConstruct } from \"constructs\";\n\nexport interface StackStageIdentity {\n stack: string;\n stage: string;\n}\n\nexport interface AppIdentity {\n app: string;\n}\n\nexport interface Identity extends StackStageIdentity, AppIdentity {}\n\nexport const AppIdentity = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- user defined type guard\n isAppIdentity(props: any): props is AppIdentity {\n return props ? \"app\" in props : false;\n },\n\n suffixText(appIdentity: AppIdentity, text: string): string {\n const titleCaseApp = appIdentity.app.charAt(0).toUpperCase() + appIdentity.app.slice(1);\n // CloudFormation Logical Ids must be alphanumeric, so remove any non-alphanumeric characters: https://stackoverflow.com/a/20864946\n const alphanumericTitleCaseApp = titleCaseApp.replace(/[\\W_]+/g, \"\");\n return `${text}${alphanumericTitleCaseApp}`;\n },\n taggedConstruct<T extends IConstruct>(appIdentity: AppIdentity, construct: T): T {\n Tags.of(construct).add(\"App\", appIdentity.app);\n return construct;\n },\n};\n"]}
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../src/constructs/core/identity.ts"],"names":[],"mappings":";;;AAAA,6CAAmC;AActB,QAAA,WAAW,GAAG;IACzB,yFAAyF;IACzF,aAAa,CAAC,KAAU;QACtB,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACxC,CAAC;IAED,uBAAuB,CAAC,WAAwB;QAC9C,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACxF,mIAAmI;QACnI,OAAO,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,iBAAiB,CAAC,WAAwB,EAAE,IAAY;QACtD,OAAO,CAAC,IAAI,EAAE,mBAAW,CAAC,uBAAuB,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,mBAAmB,CAAC,WAAwB,EAAE,IAAY;QACxD,OAAO,CAAC,mBAAW,CAAC,uBAAuB,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,eAAe,CAAuB,WAAwB,EAAE,SAAY;QAC1E,kBAAI,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,SAAS,CAAC;IACnB,CAAC;CACF,CAAC","sourcesContent":["import { Tags } from \"aws-cdk-lib\";\nimport type { IConstruct } from \"constructs\";\n\nexport interface StackStageIdentity {\n stack: string;\n stage: string;\n}\n\nexport interface AppIdentity {\n app: string;\n}\n\nexport interface Identity extends StackStageIdentity, AppIdentity {}\n\nexport const AppIdentity = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- user defined type guard\n isAppIdentity(props: any): props is AppIdentity {\n return props ? \"app\" in props : false;\n },\n\n toAlphanumericTitleCase(appIdentity: AppIdentity) {\n const titleCaseApp = appIdentity.app.charAt(0).toUpperCase() + appIdentity.app.slice(1);\n // CloudFormation Logical Ids must be alphanumeric, so remove any non-alphanumeric characters: https://stackoverflow.com/a/20864946\n return titleCaseApp.replace(/[\\W_]+/g, \"\");\n },\n\n addAppToStringEnd(appIdentity: AppIdentity, text: string): string {\n return [text, AppIdentity.toAlphanumericTitleCase(appIdentity)].join(\"\");\n },\n\n addAppToStringStart(appIdentity: AppIdentity, text: string): string {\n return [AppIdentity.toAlphanumericTitleCase(appIdentity), text].join(\"\");\n },\n\n taggedConstruct<T extends IConstruct>(appIdentity: AppIdentity, construct: T): T {\n Tags.of(construct).add(\"App\", appIdentity.app);\n return construct;\n },\n};\n"]}
@@ -6,7 +6,7 @@ const identity_1 = require("../identity");
6
6
  const base_1 = require("./base");
7
7
  class GuCertificateArnParameter extends base_1.GuStringParameter {
8
8
  constructor(scope, props) {
9
- super(scope, identity_1.AppIdentity.suffixText(props, "TLSCertificate"), {
9
+ super(scope, identity_1.AppIdentity.addAppToStringEnd(props, "TLSCertificate"), {
10
10
  allowedPattern: constants_1.RegexPattern.ACM_ARN,
11
11
  constraintDescription: "Must be an ACM ARN resource",
12
12
  description: "The ARN of an ACM certificate for use on a load balancer",
@@ -1 +1 @@
1
- {"version":3,"file":"acm.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/acm.ts"],"names":[],"mappings":";;;AAAA,kDAAkD;AAClD,0CAA0C;AAE1C,iCAA2C;AAE3C,MAAa,yBAA0B,SAAQ,wBAAiB;IAC9D,YAAY,KAAc,EAAE,KAAkB;QAC5C,KAAK,CAAC,KAAK,EAAE,sBAAW,CAAC,UAAU,CAAC,KAAK,EAAE,gBAAgB,CAAC,EAAE;YAC5D,cAAc,EAAE,wBAAY,CAAC,OAAO;YACpC,qBAAqB,EAAE,6BAA6B;YACpD,WAAW,EAAE,0DAA0D;SACxE,CAAC,CAAC;IACL,CAAC;CACF;AARD,8DAQC","sourcesContent":["import { RegexPattern } from \"../../../constants\";\nimport { AppIdentity } from \"../identity\";\nimport type { GuStack } from \"../stack\";\nimport { GuStringParameter } from \"./base\";\n\nexport class GuCertificateArnParameter extends GuStringParameter {\n constructor(scope: GuStack, props: AppIdentity) {\n super(scope, AppIdentity.suffixText(props, \"TLSCertificate\"), {\n allowedPattern: RegexPattern.ACM_ARN,\n constraintDescription: \"Must be an ACM ARN resource\",\n description: \"The ARN of an ACM certificate for use on a load balancer\",\n });\n }\n}\n"]}
1
+ {"version":3,"file":"acm.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/acm.ts"],"names":[],"mappings":";;;AAAA,kDAAkD;AAClD,0CAA0C;AAE1C,iCAA2C;AAE3C,MAAa,yBAA0B,SAAQ,wBAAiB;IAC9D,YAAY,KAAc,EAAE,KAAkB;QAC5C,KAAK,CAAC,KAAK,EAAE,sBAAW,CAAC,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,CAAC,EAAE;YACnE,cAAc,EAAE,wBAAY,CAAC,OAAO;YACpC,qBAAqB,EAAE,6BAA6B;YACpD,WAAW,EAAE,0DAA0D;SACxE,CAAC,CAAC;IACL,CAAC;CACF;AARD,8DAQC","sourcesContent":["import { RegexPattern } from \"../../../constants\";\nimport { AppIdentity } from \"../identity\";\nimport type { GuStack } from \"../stack\";\nimport { GuStringParameter } from \"./base\";\n\nexport class GuCertificateArnParameter extends GuStringParameter {\n constructor(scope: GuStack, props: AppIdentity) {\n super(scope, AppIdentity.addAppToStringEnd(props, \"TLSCertificate\"), {\n allowedPattern: RegexPattern.ACM_ARN,\n constraintDescription: \"Must be an ACM ARN resource\",\n description: \"The ARN of an ACM certificate for use on a load balancer\",\n });\n }\n}\n"]}
@@ -5,7 +5,7 @@ const identity_1 = require("../identity");
5
5
  const base_1 = require("./base");
6
6
  class GuAmiParameter extends base_1.GuParameter {
7
7
  constructor(scope, props) {
8
- super(scope, identity_1.AppIdentity.suffixText(props, "AMI"), {
8
+ super(scope, identity_1.AppIdentity.addAppToStringEnd(props, "AMI"), {
9
9
  type: "AWS::EC2::Image::Id",
10
10
  description: `Amazon Machine Image ID for the app ${props.app}. Use this in conjunction with AMIgo to keep AMIs up to date.`,
11
11
  ...props,
@@ -1 +1 @@
1
- {"version":3,"file":"ec2.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/ec2.ts"],"names":[],"mappings":";;;AAAA,0CAA0C;AAE1C,iCAAqC;AAGrC,MAAa,cAAe,SAAQ,kBAAW;IAC7C,YAAY,KAAc,EAAE,KAA4C;QACtE,KAAK,CAAC,KAAK,EAAE,sBAAW,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE;YACjD,IAAI,EAAE,qBAAqB;YAC3B,WAAW,EAAE,uCAAuC,KAAK,CAAC,GAAG,+DAA+D;YAC5H,GAAG,KAAK;SACT,CAAC,CAAC;IACL,CAAC;CACF;AARD,wCAQC","sourcesContent":["import { AppIdentity } from \"../identity\";\nimport type { GuStack } from \"../stack\";\nimport { GuParameter } from \"./base\";\nimport type { GuNoTypeParameterPropsWithAppIdentity } from \"./base\";\n\nexport class GuAmiParameter extends GuParameter {\n constructor(scope: GuStack, props: GuNoTypeParameterPropsWithAppIdentity) {\n super(scope, AppIdentity.suffixText(props, \"AMI\"), {\n type: \"AWS::EC2::Image::Id\",\n description: `Amazon Machine Image ID for the app ${props.app}. Use this in conjunction with AMIgo to keep AMIs up to date.`,\n ...props,\n });\n }\n}\n"]}
1
+ {"version":3,"file":"ec2.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/ec2.ts"],"names":[],"mappings":";;;AAAA,0CAA0C;AAE1C,iCAAqC;AAGrC,MAAa,cAAe,SAAQ,kBAAW;IAC7C,YAAY,KAAc,EAAE,KAA4C;QACtE,KAAK,CAAC,KAAK,EAAE,sBAAW,CAAC,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE;YACxD,IAAI,EAAE,qBAAqB;YAC3B,WAAW,EAAE,uCAAuC,KAAK,CAAC,GAAG,+DAA+D;YAC5H,GAAG,KAAK;SACT,CAAC,CAAC;IACL,CAAC;CACF;AARD,wCAQC","sourcesContent":["import { AppIdentity } from \"../identity\";\nimport type { GuStack } from \"../stack\";\nimport { GuParameter } from \"./base\";\nimport type { GuNoTypeParameterPropsWithAppIdentity } from \"./base\";\n\nexport class GuAmiParameter extends GuParameter {\n constructor(scope: GuStack, props: GuNoTypeParameterPropsWithAppIdentity) {\n super(scope, AppIdentity.addAppToStringEnd(props, \"AMI\"), {\n type: \"AWS::EC2::Image::Id\",\n description: `Amazon Machine Image ID for the app ${props.app}. Use this in conjunction with AMIgo to keep AMIs up to date.`,\n ...props,\n });\n }\n}\n"]}
@@ -125,7 +125,7 @@ class GuEcsTask extends constructs_1.Construct {
125
125
  stateMachineName: `${app}-${stage}`,
126
126
  });
127
127
  if (!monitoringConfiguration.noMonitoring) {
128
- const alarmTopic = aws_sns_1.Topic.fromTopicArn(scope, core_1.AppIdentity.suffixText(props, "AlarmTopic"), monitoringConfiguration.snsTopicArn);
128
+ const alarmTopic = aws_sns_1.Topic.fromTopicArn(scope, core_1.AppIdentity.addAppToStringEnd(props, "AlarmTopic"), monitoringConfiguration.snsTopicArn);
129
129
  const alarms = [
130
130
  {
131
131
  name: `${app}-execution-failed`,
@@ -1 +1 @@
1
- {"version":3,"file":"ecs-task.js","sourceRoot":"","sources":["../../../src/constructs/ecs/ecs-task.ts"],"names":[],"mappings":"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","sourcesContent":["import { CfnOutput, Duration } from \"aws-cdk-lib\";\nimport { Alarm, TreatMissingData } from \"aws-cdk-lib/aws-cloudwatch\";\nimport { SnsAction } from \"aws-cdk-lib/aws-cloudwatch-actions\";\nimport type { ISecurityGroup, ISubnet, IVpc } from \"aws-cdk-lib/aws-ec2\";\nimport type { IRepository } from \"aws-cdk-lib/aws-ecr\";\nimport {\n Cluster,\n Compatibility,\n ContainerImage,\n CpuArchitecture,\n FargatePlatformVersion,\n LogDrivers,\n OperatingSystemFamily,\n TaskDefinition,\n} from \"aws-cdk-lib/aws-ecs\";\nimport type { ContainerDefinition, ContainerInsights, RepositoryImageProps } from \"aws-cdk-lib/aws-ecs\";\nimport { Effect, PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport { DefinitionBody, IntegrationPattern, JsonPath, StateMachine, Timeout } from \"aws-cdk-lib/aws-stepfunctions\";\nimport type { TaskEnvironmentVariable } from \"aws-cdk-lib/aws-stepfunctions-tasks\";\nimport { EcsFargateLaunchTarget, EcsRunTask } from \"aws-cdk-lib/aws-stepfunctions-tasks\";\nimport { Construct } from \"constructs\";\nimport type { NoMonitoring } from \"../cloudwatch\";\nimport type { GuStack } from \"../core\";\nimport { AppIdentity } from \"../core\";\nimport { GuGetDistributablePolicyStatement } from \"../iam\";\n\n/**\n * Configuration to determine what container to use for the task\n * For example, to run the task in the latest node container:\n *\n * ```typescript\n * const containerConfiguration = {\n * id: 'node:latest'\n * }\n * ```\n *\n * Alternatively you can specify a repository and version, for example for an ECR repository:\n * ```typescript\n * import { Repository } from \"aws-cdk-lib/aws-ecr\";\n * const repository = new Repository(scope, `${app}-repository`, {\n repositoryName: app,\n });\n * const containerConfiguration = {\n * repository: Repository.fromRepositoryArn(\"<repository arn>\"),\n * version: '1'\n * }\n * ```\n */\n\nexport type RepositoryContainer = {\n repository: IRepository;\n version: string;\n type: \"repository\";\n};\n\nexport type RegistryContainer = {\n id?: string;\n imageProps?: RepositoryImageProps;\n type: \"registry\";\n};\n\nexport type ContainerConfiguration = RepositoryContainer | RegistryContainer;\n\nexport type GuEcsTaskMonitoringProps = { snsTopicArn: string; noMonitoring: false };\n\n/**\n * Configuration options for the [[`GuEcsTask`]] pattern.\n *\n * Note it is recommended to use GuVpc.subnetsFromParameterFixedNumber for the subnets prop rather than\n * GuVpc.subnetsFromParameter, as using the latter can result a custom resource being required\n *\n * See [[`ContainerConfiguration`]] for details of how to configure the container used to run the task.\n *\n * `taskTimeoutInMinutes` does what is says on the tin. The default timeout is 15 minutes.\n *\n * The `taskCommand` prop allows you to specify a command to run when the task starts (this can also be done via a CMD statement in\n * your Dockerfile). For example:\n *\n * const props = {\n * //other props\n * taskCommand: `aws s3 cp s3://${distbucket}/${stack}/${stage}/${app}/task.sh . && ./task.sh\n }\n *\n * It is advisable to configure alarms for when the job fails/times out. To do this specify the alarmSnsTopicArn prop.\n *\n * `customTaskPolicies` allows your task to interact with other AWS services. By default a task\n * will have read access to the distribution bucket for your account.\n *\n * You can specify security groups to apply to task using the `securityGroups` prop.\n *\n * You can also set the memory and cpu units for your task. See https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_size\n * for further details.\n *\n * If you want to pass input from the step function into your EcsTask you can do so via the `environmentOverrides` prop, which allows you to wire up\n * step function input JSON to environment variables set on the container. For example,\n * const props = {\n * ...otherProps\n * environmentOverrides: [\n {\n name: \"VERSION\",\n value: JsonPath.stringAt(\"$.version\"),\n },\n }\n * With the above override, your task will attempt to find a `version` property in the JSON input passed to the step function, and apply it to the\n * VERSION environment variable. Alternatively, you could hard code a value for the variable in CDK.\n * See https://docs.aws.amazon.com/step-functions/latest/dg/connect-ecs.html for further detail and other override options - this construct currently\n * only supports environment variables.\n */\nexport interface GuEcsTaskProps extends AppIdentity {\n vpc: IVpc;\n subnets: ISubnet[];\n assignPublicIp?: boolean;\n containerConfiguration: ContainerConfiguration;\n taskTimeoutInMinutes?: number;\n cpu?: number;\n memory?: number;\n taskCommand?: string;\n monitoringConfiguration: NoMonitoring | GuEcsTaskMonitoringProps;\n securityGroups?: ISecurityGroup[];\n customTaskPolicies?: PolicyStatement[];\n environmentOverrides?: TaskEnvironmentVariable[];\n storage?: number;\n /**\n * Whether to give the task IAM role access to the account's dist bucket.\n * This is enabled by default to avoid breaking changes, but consumers of this pattern\n * that pull a container image that doesn't need extra dependencies from S3\n * shoud set this value to `false`.\n */\n enableDistributablePolicy?: boolean;\n\n /**\n * The CloudWatch Container Insights setting\n *\n * @see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cloudwatch-container-insights.html\n */\n containerInsights: ContainerInsights;\n}\n\n/**\n * Containers can be specified either via a repository and version or by container id (in which case it will\n * be fetched from docker hub).\n */\nconst getContainer = (config: ContainerConfiguration) => {\n if (config.type == \"repository\") {\n return ContainerImage.fromEcrRepository(config.repository, config.version);\n } else {\n return ContainerImage.fromRegistry(config.id ?? \"ubuntu:jammy\", config.imageProps);\n }\n};\n\n/**\n * Pattern which creates all of the resources needed for a fargate task\n *\n * The task will be wrapped in a step function to allow for easier triggering and alarming on failure.\n *\n * For all configuration options, see [[`GuEcsTaskProps`]].\n *\n * Note that if your task reliably completes in less than 15 minutes then you should probably use a [[`GuLambda`]] instead. This\n * pattern was mainly created to work around the 15 minute lambda timeout.\n *\n */\nexport class GuEcsTask extends Construct {\n public readonly stateMachine: StateMachine;\n public readonly taskDefinition: TaskDefinition;\n public readonly containerDefinition: ContainerDefinition;\n public readonly task: EcsRunTask;\n\n constructor(scope: GuStack, id: string, props: GuEcsTaskProps) {\n super(scope, id);\n\n const {\n app,\n\n // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html#cfn-ecs-taskdefinition-cpu for details\n cpu = 2048, // 2 cores and from 4-16GB memory\n memory = 4096, // 4GB\n storage, // default is 20 GB when not provided in props\n containerConfiguration,\n taskCommand,\n taskTimeoutInMinutes = 15,\n customTaskPolicies,\n vpc,\n subnets,\n monitoringConfiguration,\n securityGroups = [],\n environmentOverrides,\n enableDistributablePolicy = true,\n containerInsights,\n } = props;\n\n if (storage && storage < 21) {\n throw new Error(\n \"Storage must be at least 21. See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-ephemeralstorage.html\",\n );\n }\n\n const { stack, stage } = scope;\n\n const cluster = new Cluster(scope, `${id}-Cluster`, {\n clusterName: `${app}-cluster-${stage}`,\n enableFargateCapacityProviders: true,\n vpc,\n containerInsightsV2: containerInsights,\n });\n\n const taskDefinition = new TaskDefinition(scope, `${id}-TaskDefinition`, {\n compatibility: Compatibility.FARGATE,\n cpu: cpu.toString(),\n memoryMiB: memory.toString(),\n family: `${stack}-${stage}-${app}`,\n ephemeralStorageGiB: storage,\n runtimePlatform: {\n cpuArchitecture: CpuArchitecture.ARM64,\n operatingSystemFamily: OperatingSystemFamily.of(\"LINUX\"),\n },\n });\n this.taskDefinition = taskDefinition;\n\n const containerDefinition = taskDefinition.addContainer(`${id}-TaskContainer`, {\n image: getContainer(containerConfiguration),\n entryPoint: taskCommand ? [\"/bin/sh\"] : undefined,\n command: taskCommand ? [\"-c\", taskCommand] : undefined, // if unset, falls back to CMD in docker file, or no command will be run\n cpu,\n memoryLimitMiB: memory,\n logging: LogDrivers.awsLogs({\n streamPrefix: app,\n logRetention: 14,\n }),\n readonlyRootFilesystem: true,\n });\n this.containerDefinition = containerDefinition;\n\n if (enableDistributablePolicy) {\n const distPolicy = new GuGetDistributablePolicyStatement(scope, { app });\n taskDefinition.addToTaskRolePolicy(distPolicy);\n }\n\n // these policies are needed for guard duty runtime monitoring\n // See https://docs.aws.amazon.com/guardduty/latest/ug/prereq-runtime-monitoring-ecs-support.html#before-enable-runtime-monitoring-ecs\n const getAuthTokenPolicy = new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"ecr:GetAuthorizationToken\"],\n resources: [\"*\"],\n });\n const guardDutyContainerPolicy = new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"ecr:BatchCheckLayerAvailability\", \"ecr:GetDownloadUrlForLayer\", \"ecr:BatchGetImage\"],\n // See https://docs.aws.amazon.com/guardduty/latest/ug/runtime-monitoring-ecr-repository-gdu-agent.html\n // note that if you are using a region other than eu-west-1 you'll need to add extra repositories here\n resources: [\"arn:aws:ecr:eu-west-1:694911143906:repository/aws-guardduty-agent-fargate\"],\n });\n\n taskDefinition.addToExecutionRolePolicy(getAuthTokenPolicy);\n taskDefinition.addToExecutionRolePolicy(guardDutyContainerPolicy);\n\n (customTaskPolicies ?? []).forEach((p) => taskDefinition.addToTaskRolePolicy(p));\n\n const task = new EcsRunTask(scope, `${id}-task`, {\n cluster,\n launchTarget: new EcsFargateLaunchTarget({\n platformVersion: FargatePlatformVersion.LATEST,\n }),\n taskDefinition,\n subnets: { subnets },\n assignPublicIp: false,\n integrationPattern: IntegrationPattern.RUN_JOB,\n resultPath: JsonPath.DISCARD,\n taskTimeout: Timeout.duration(Duration.minutes(taskTimeoutInMinutes)),\n securityGroups,\n containerOverrides: [\n {\n containerDefinition: containerDefinition,\n environment: environmentOverrides,\n },\n ],\n });\n this.task = task;\n\n this.stateMachine = new StateMachine(scope, `${id}-StateMachine`, {\n definitionBody: DefinitionBody.fromChainable(task),\n stateMachineName: `${app}-${stage}`,\n });\n\n if (!monitoringConfiguration.noMonitoring) {\n const alarmTopic = Topic.fromTopicArn(\n scope,\n AppIdentity.suffixText(props, \"AlarmTopic\"),\n monitoringConfiguration.snsTopicArn,\n );\n const alarms = [\n {\n name: `${app}-execution-failed`,\n description: `${app}-${stage} job failed `,\n metric: this.stateMachine.metricFailed({\n period: Duration.hours(1),\n statistic: \"sum\",\n }),\n },\n {\n name: `${app}-timeout`,\n description: `${app}-${stage} job timed out `,\n metric: this.stateMachine.metricTimedOut({\n period: Duration.hours(1),\n statistic: \"sum\",\n }),\n },\n ];\n\n alarms.forEach(({ name, description, metric }) => {\n const alarm = new Alarm(scope, name, {\n alarmDescription: description,\n actionsEnabled: true,\n metric: metric,\n // default for comparisonOperator is GreaterThanOrEqualToThreshold\n threshold: 1,\n evaluationPeriods: 1,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n });\n alarm.addAlarmAction(new SnsAction(alarmTopic));\n AppIdentity.taggedConstruct({ app }, alarm);\n });\n }\n\n // Tag all constructs with correct app tag\n [cluster, task, taskDefinition, this.stateMachine].forEach((c) => AppIdentity.taggedConstruct({ app }, c));\n\n new CfnOutput(scope, `${id}-StateMachineArnOutput`, {\n value: this.stateMachine.stateMachineArn,\n });\n }\n}\n"]}
1
+ {"version":3,"file":"ecs-task.js","sourceRoot":"","sources":["../../../src/constructs/ecs/ecs-task.ts"],"names":[],"mappings":"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","sourcesContent":["import { CfnOutput, Duration } from \"aws-cdk-lib\";\nimport { Alarm, TreatMissingData } from \"aws-cdk-lib/aws-cloudwatch\";\nimport { SnsAction } from \"aws-cdk-lib/aws-cloudwatch-actions\";\nimport type { ISecurityGroup, ISubnet, IVpc } from \"aws-cdk-lib/aws-ec2\";\nimport type { IRepository } from \"aws-cdk-lib/aws-ecr\";\nimport {\n Cluster,\n Compatibility,\n ContainerImage,\n CpuArchitecture,\n FargatePlatformVersion,\n LogDrivers,\n OperatingSystemFamily,\n TaskDefinition,\n} from \"aws-cdk-lib/aws-ecs\";\nimport type { ContainerDefinition, ContainerInsights, RepositoryImageProps } from \"aws-cdk-lib/aws-ecs\";\nimport { Effect, PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport { DefinitionBody, IntegrationPattern, JsonPath, StateMachine, Timeout } from \"aws-cdk-lib/aws-stepfunctions\";\nimport type { TaskEnvironmentVariable } from \"aws-cdk-lib/aws-stepfunctions-tasks\";\nimport { EcsFargateLaunchTarget, EcsRunTask } from \"aws-cdk-lib/aws-stepfunctions-tasks\";\nimport { Construct } from \"constructs\";\nimport type { NoMonitoring } from \"../cloudwatch\";\nimport type { GuStack } from \"../core\";\nimport { AppIdentity } from \"../core\";\nimport { GuGetDistributablePolicyStatement } from \"../iam\";\n\n/**\n * Configuration to determine what container to use for the task\n * For example, to run the task in the latest node container:\n *\n * ```typescript\n * const containerConfiguration = {\n * id: 'node:latest'\n * }\n * ```\n *\n * Alternatively you can specify a repository and version, for example for an ECR repository:\n * ```typescript\n * import { Repository } from \"aws-cdk-lib/aws-ecr\";\n * const repository = new Repository(scope, `${app}-repository`, {\n repositoryName: app,\n });\n * const containerConfiguration = {\n * repository: Repository.fromRepositoryArn(\"<repository arn>\"),\n * version: '1'\n * }\n * ```\n */\n\nexport type RepositoryContainer = {\n repository: IRepository;\n version: string;\n type: \"repository\";\n};\n\nexport type RegistryContainer = {\n id?: string;\n imageProps?: RepositoryImageProps;\n type: \"registry\";\n};\n\nexport type ContainerConfiguration = RepositoryContainer | RegistryContainer;\n\nexport type GuEcsTaskMonitoringProps = { snsTopicArn: string; noMonitoring: false };\n\n/**\n * Configuration options for the [[`GuEcsTask`]] pattern.\n *\n * Note it is recommended to use GuVpc.subnetsFromParameterFixedNumber for the subnets prop rather than\n * GuVpc.subnetsFromParameter, as using the latter can result a custom resource being required\n *\n * See [[`ContainerConfiguration`]] for details of how to configure the container used to run the task.\n *\n * `taskTimeoutInMinutes` does what is says on the tin. The default timeout is 15 minutes.\n *\n * The `taskCommand` prop allows you to specify a command to run when the task starts (this can also be done via a CMD statement in\n * your Dockerfile). For example:\n *\n * const props = {\n * //other props\n * taskCommand: `aws s3 cp s3://${distbucket}/${stack}/${stage}/${app}/task.sh . && ./task.sh\n }\n *\n * It is advisable to configure alarms for when the job fails/times out. To do this specify the alarmSnsTopicArn prop.\n *\n * `customTaskPolicies` allows your task to interact with other AWS services. By default a task\n * will have read access to the distribution bucket for your account.\n *\n * You can specify security groups to apply to task using the `securityGroups` prop.\n *\n * You can also set the memory and cpu units for your task. See https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_size\n * for further details.\n *\n * If you want to pass input from the step function into your EcsTask you can do so via the `environmentOverrides` prop, which allows you to wire up\n * step function input JSON to environment variables set on the container. For example,\n * const props = {\n * ...otherProps\n * environmentOverrides: [\n {\n name: \"VERSION\",\n value: JsonPath.stringAt(\"$.version\"),\n },\n }\n * With the above override, your task will attempt to find a `version` property in the JSON input passed to the step function, and apply it to the\n * VERSION environment variable. Alternatively, you could hard code a value for the variable in CDK.\n * See https://docs.aws.amazon.com/step-functions/latest/dg/connect-ecs.html for further detail and other override options - this construct currently\n * only supports environment variables.\n */\nexport interface GuEcsTaskProps extends AppIdentity {\n vpc: IVpc;\n subnets: ISubnet[];\n assignPublicIp?: boolean;\n containerConfiguration: ContainerConfiguration;\n taskTimeoutInMinutes?: number;\n cpu?: number;\n memory?: number;\n taskCommand?: string;\n monitoringConfiguration: NoMonitoring | GuEcsTaskMonitoringProps;\n securityGroups?: ISecurityGroup[];\n customTaskPolicies?: PolicyStatement[];\n environmentOverrides?: TaskEnvironmentVariable[];\n storage?: number;\n /**\n * Whether to give the task IAM role access to the account's dist bucket.\n * This is enabled by default to avoid breaking changes, but consumers of this pattern\n * that pull a container image that doesn't need extra dependencies from S3\n * shoud set this value to `false`.\n */\n enableDistributablePolicy?: boolean;\n\n /**\n * The CloudWatch Container Insights setting\n *\n * @see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cloudwatch-container-insights.html\n */\n containerInsights: ContainerInsights;\n}\n\n/**\n * Containers can be specified either via a repository and version or by container id (in which case it will\n * be fetched from docker hub).\n */\nconst getContainer = (config: ContainerConfiguration) => {\n if (config.type == \"repository\") {\n return ContainerImage.fromEcrRepository(config.repository, config.version);\n } else {\n return ContainerImage.fromRegistry(config.id ?? \"ubuntu:jammy\", config.imageProps);\n }\n};\n\n/**\n * Pattern which creates all of the resources needed for a fargate task\n *\n * The task will be wrapped in a step function to allow for easier triggering and alarming on failure.\n *\n * For all configuration options, see [[`GuEcsTaskProps`]].\n *\n * Note that if your task reliably completes in less than 15 minutes then you should probably use a [[`GuLambda`]] instead. This\n * pattern was mainly created to work around the 15 minute lambda timeout.\n *\n */\nexport class GuEcsTask extends Construct {\n public readonly stateMachine: StateMachine;\n public readonly taskDefinition: TaskDefinition;\n public readonly containerDefinition: ContainerDefinition;\n public readonly task: EcsRunTask;\n\n constructor(scope: GuStack, id: string, props: GuEcsTaskProps) {\n super(scope, id);\n\n const {\n app,\n\n // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html#cfn-ecs-taskdefinition-cpu for details\n cpu = 2048, // 2 cores and from 4-16GB memory\n memory = 4096, // 4GB\n storage, // default is 20 GB when not provided in props\n containerConfiguration,\n taskCommand,\n taskTimeoutInMinutes = 15,\n customTaskPolicies,\n vpc,\n subnets,\n monitoringConfiguration,\n securityGroups = [],\n environmentOverrides,\n enableDistributablePolicy = true,\n containerInsights,\n } = props;\n\n if (storage && storage < 21) {\n throw new Error(\n \"Storage must be at least 21. See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-ephemeralstorage.html\",\n );\n }\n\n const { stack, stage } = scope;\n\n const cluster = new Cluster(scope, `${id}-Cluster`, {\n clusterName: `${app}-cluster-${stage}`,\n enableFargateCapacityProviders: true,\n vpc,\n containerInsightsV2: containerInsights,\n });\n\n const taskDefinition = new TaskDefinition(scope, `${id}-TaskDefinition`, {\n compatibility: Compatibility.FARGATE,\n cpu: cpu.toString(),\n memoryMiB: memory.toString(),\n family: `${stack}-${stage}-${app}`,\n ephemeralStorageGiB: storage,\n runtimePlatform: {\n cpuArchitecture: CpuArchitecture.ARM64,\n operatingSystemFamily: OperatingSystemFamily.of(\"LINUX\"),\n },\n });\n this.taskDefinition = taskDefinition;\n\n const containerDefinition = taskDefinition.addContainer(`${id}-TaskContainer`, {\n image: getContainer(containerConfiguration),\n entryPoint: taskCommand ? [\"/bin/sh\"] : undefined,\n command: taskCommand ? [\"-c\", taskCommand] : undefined, // if unset, falls back to CMD in docker file, or no command will be run\n cpu,\n memoryLimitMiB: memory,\n logging: LogDrivers.awsLogs({\n streamPrefix: app,\n logRetention: 14,\n }),\n readonlyRootFilesystem: true,\n });\n this.containerDefinition = containerDefinition;\n\n if (enableDistributablePolicy) {\n const distPolicy = new GuGetDistributablePolicyStatement(scope, { app });\n taskDefinition.addToTaskRolePolicy(distPolicy);\n }\n\n // these policies are needed for guard duty runtime monitoring\n // See https://docs.aws.amazon.com/guardduty/latest/ug/prereq-runtime-monitoring-ecs-support.html#before-enable-runtime-monitoring-ecs\n const getAuthTokenPolicy = new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"ecr:GetAuthorizationToken\"],\n resources: [\"*\"],\n });\n const guardDutyContainerPolicy = new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"ecr:BatchCheckLayerAvailability\", \"ecr:GetDownloadUrlForLayer\", \"ecr:BatchGetImage\"],\n // See https://docs.aws.amazon.com/guardduty/latest/ug/runtime-monitoring-ecr-repository-gdu-agent.html\n // note that if you are using a region other than eu-west-1 you'll need to add extra repositories here\n resources: [\"arn:aws:ecr:eu-west-1:694911143906:repository/aws-guardduty-agent-fargate\"],\n });\n\n taskDefinition.addToExecutionRolePolicy(getAuthTokenPolicy);\n taskDefinition.addToExecutionRolePolicy(guardDutyContainerPolicy);\n\n (customTaskPolicies ?? []).forEach((p) => taskDefinition.addToTaskRolePolicy(p));\n\n const task = new EcsRunTask(scope, `${id}-task`, {\n cluster,\n launchTarget: new EcsFargateLaunchTarget({\n platformVersion: FargatePlatformVersion.LATEST,\n }),\n taskDefinition,\n subnets: { subnets },\n assignPublicIp: false,\n integrationPattern: IntegrationPattern.RUN_JOB,\n resultPath: JsonPath.DISCARD,\n taskTimeout: Timeout.duration(Duration.minutes(taskTimeoutInMinutes)),\n securityGroups,\n containerOverrides: [\n {\n containerDefinition: containerDefinition,\n environment: environmentOverrides,\n },\n ],\n });\n this.task = task;\n\n this.stateMachine = new StateMachine(scope, `${id}-StateMachine`, {\n definitionBody: DefinitionBody.fromChainable(task),\n stateMachineName: `${app}-${stage}`,\n });\n\n if (!monitoringConfiguration.noMonitoring) {\n const alarmTopic = Topic.fromTopicArn(\n scope,\n AppIdentity.addAppToStringEnd(props, \"AlarmTopic\"),\n monitoringConfiguration.snsTopicArn,\n );\n const alarms = [\n {\n name: `${app}-execution-failed`,\n description: `${app}-${stage} job failed `,\n metric: this.stateMachine.metricFailed({\n period: Duration.hours(1),\n statistic: \"sum\",\n }),\n },\n {\n name: `${app}-timeout`,\n description: `${app}-${stage} job timed out `,\n metric: this.stateMachine.metricTimedOut({\n period: Duration.hours(1),\n statistic: \"sum\",\n }),\n },\n ];\n\n alarms.forEach(({ name, description, metric }) => {\n const alarm = new Alarm(scope, name, {\n alarmDescription: description,\n actionsEnabled: true,\n metric: metric,\n // default for comparisonOperator is GreaterThanOrEqualToThreshold\n threshold: 1,\n evaluationPeriods: 1,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n });\n alarm.addAlarmAction(new SnsAction(alarmTopic));\n AppIdentity.taggedConstruct({ app }, alarm);\n });\n }\n\n // Tag all constructs with correct app tag\n [cluster, task, taskDefinition, this.stateMachine].forEach((c) => AppIdentity.taggedConstruct({ app }, c));\n\n new CfnOutput(scope, `${id}-StateMachineArnOutput`, {\n value: this.stateMachine.stateMachineArn,\n });\n }\n}\n"]}
@@ -42,7 +42,7 @@ class GuApplicationLoadBalancer extends (0, app_aware_construct_1.GuAppAwareCons
42
42
  cfnLb.addPropertyDeletionOverride("Type");
43
43
  }
44
44
  if (withAccessLogging) {
45
- const bucket = aws_s3_1.Bucket.fromBucketName(scope, core_1.AppIdentity.suffixText(props, "AccessLoggingBucket"), core_1.GuAccessLoggingBucketParameter.getInstance(scope).valueAsString);
45
+ const bucket = aws_s3_1.Bucket.fromBucketName(scope, core_1.AppIdentity.addAppToStringEnd(props, "AccessLoggingBucket"), core_1.GuAccessLoggingBucketParameter.getInstance(scope).valueAsString);
46
46
  const prefix = `application-load-balancer/${stage}/${stack}/${app}`;
47
47
  this.logAccessLogs(bucket, prefix);
48
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"application-load-balancer.js","sourceRoot":"","sources":["../../../../src/constructs/loadbalancing/alb/application-load-balancer.ts"],"names":[],"mappings":";;;AAAA,6CAAqD;AACrD,uFAAiF;AAEjF,+CAA4C;AAC5C,iDAAwF;AACxF,kFAA+E;AAE/E,qCAAyE;AAEzE;;;;;;GAMG;AACU,QAAA,4CAA4C,GAAG,0DAA0D,CAAC;AAEvH;;;GAGG;AACU,QAAA,kCAAkC,GAAG,iDAAiD,CAAC;AA0BpG;;;;;;;;;GASG;AACH,MAAa,yBAA0B,SAAQ,IAAA,yCAAmB,EAAC,oDAAuB,CAAC;IAGzF,YAAY,KAAc,EAAE,EAAU,EAAE,KAAqC;QAC3E,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,iBAAiB,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;QACjE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;QAE/B,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;QAEzD,IAAI,CAAC,YAAY,CAAC,oDAA4C,EAAE,MAAM,CAAC,CAAC;QACxE,IAAI,CAAC,YAAY,CAAC,0CAAkC,EAAE,MAAM,CAAC,CAAC;QAE9D,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,YAA+B,CAAC;YACxD,KAAK,CAAC,2BAA2B,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,iBAAiB,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,eAAM,CAAC,cAAc,CAClC,KAAK,EACL,kBAAW,CAAC,UAAU,CAAC,KAAK,EAAE,qBAAqB,CAAC,EACpD,qCAA8B,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,aAAa,CAChE,CAAC;YACF,MAAM,MAAM,GAAG,6BAA6B,KAAK,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;YACpE,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,YAAY,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;YACrD,yBAAW,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC;QACzE,CAAC;QAED,IAAI,uBAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,UAAU,EAAE;YAC/C,WAAW,EAAE,iBAAiB,IAAI,CAAC,SAAS,EAAE;YAC9C,KAAK,EAAE,IAAI,CAAC,mBAAmB;SAChC,CAAC,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC,SAAS,SAAS,CAAC,CAAC;QAEjD,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YACzB,IAAI,CAAC,GAAG,GAAG,IAAI,yBAAe,CAAC,IAAI,EAAE,aAAa,EAAE;gBAClD,aAAa,EAAE,yBAAyB,KAAK,IAAI,GAAG,UAAU;gBAC9D,WAAW,EAAE,0BAA0B,KAAK,IAAI,GAAG,GAAG;gBACtD,UAAU,EAAE,KAAK;gBACjB,WAAW,EAAE,IAAI,CAAC,eAAe;gBACjC,IAAI,EAAE,uBAAa,CAAC,QAAQ;gBAC5B,QAAQ,EAAE,2BAAiB,CAAC,IAAI;aACjC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF;AA9CD,8DA8CC","sourcesContent":["import { Annotations, CfnOutput } from \"aws-cdk-lib\";\nimport { ApplicationLoadBalancer } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport type { ApplicationLoadBalancerProps, CfnLoadBalancer } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport { Bucket } from \"aws-cdk-lib/aws-s3\";\nimport { ParameterDataType, ParameterTier, StringParameter } from \"aws-cdk-lib/aws-ssm\";\nimport { GuAppAwareConstruct } from \"../../../utils/mixin/app-aware-construct\";\nimport type { GuStack } from \"../../core\";\nimport { AppIdentity, GuAccessLoggingBucketParameter } from \"../../core\";\n\n/**\n * Adds the following headers to each request before forwarding it to the target:\n * - `x-amzn-tls-version`, which has information about the TLS protocol version negotiated with the client\n * - `x-amzn-tls-cipher-suite`, which has information about the cipher suite negotiated with the client\n *\n * Both headers are in OpenSSL format.\n */\nexport const TLS_VERSION_AND_CIPHER_SUITE_HEADERS_ENABLED = \"routing.http.x_amzn_tls_version_and_cipher_suite.enabled\";\n\n/**\n * Indicates whether HTTP headers with invalid header fields are removed by the load balancer.\n * Invalid headers are described as HTTP header names that do not conform to the regular expression [-A-Za-z0-9]+\n */\nexport const DROP_INVALID_HEADER_FIELDS_ENABLED = \"routing.http.drop_invalid_header_fields.enabled\";\n\ninterface GuApplicationLoadBalancerProps extends ApplicationLoadBalancerProps, AppIdentity {\n /**\n * If your CloudFormation does not define the Type of your Load Balancer, you must set this boolean to true to avoid\n * resource [replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-loadbalancer.html#cfn-elasticloadbalancingv2-loadbalancer-type).\n * If a Load Balancer is replaced it is likely to lead to downtime.\n */\n removeType?: boolean;\n\n /**\n * Enable access logging for this load balancer.\n * Access logs are written to an S3 bucket within your AWS account.\n * The bucket is created by {@link https://github.com/guardian/aws-account-setup}.\n * The logs are queryable via the `gucdk_access_logs` Athena database.\n *\n * @default true\n */\n withAccessLogging?: boolean;\n\n /**\n * Configuration for WAF protection, if desired\n */\n waf?: WafProps;\n}\n\n/**\n * Construct which creates an Application Load Balancer.\n *\n * This construct should be used in conjunction with [[`GuApplicationListener`]] and [[`GuApplicationTargetGroup`]]\n * to route traffic to your application. For more details on these three components, see the\n * [AWS documentation](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html#application-load-balancer-components).\n *\n * This resource is stateful.\n * @see https://github.com/guardian/cdk/blob/main/docs/stateful-resources.md\n */\nexport class GuApplicationLoadBalancer extends GuAppAwareConstruct(ApplicationLoadBalancer) {\n public readonly waf?: StringParameter;\n\n constructor(scope: GuStack, id: string, props: GuApplicationLoadBalancerProps) {\n const { app, removeType, waf, withAccessLogging = true } = props;\n const { stack, stage } = scope;\n\n super(scope, id, { deletionProtection: true, ...props });\n\n this.setAttribute(TLS_VERSION_AND_CIPHER_SUITE_HEADERS_ENABLED, \"true\");\n this.setAttribute(DROP_INVALID_HEADER_FIELDS_ENABLED, \"true\");\n\n if (removeType) {\n const cfnLb = this.node.defaultChild as CfnLoadBalancer;\n cfnLb.addPropertyDeletionOverride(\"Type\");\n }\n\n if (withAccessLogging) {\n const bucket = Bucket.fromBucketName(\n scope,\n AppIdentity.suffixText(props, \"AccessLoggingBucket\"),\n GuAccessLoggingBucketParameter.getInstance(scope).valueAsString,\n );\n const prefix = `application-load-balancer/${stage}/${stack}/${app}`;\n this.logAccessLogs(bucket, prefix);\n } else {\n this.setAttribute(\"access_logs.s3.enabled\", \"false\");\n Annotations.of(this).addInfo(`Access logs disabled for load balancer`);\n }\n\n new CfnOutput(this, `${this.idWithApp}-DnsName`, {\n description: `DNS entry for ${this.idWithApp}`,\n value: this.loadBalancerDnsName,\n }).overrideLogicalId(`${this.idWithApp}DnsName`);\n\n if (!!waf && waf.enabled) {\n this.waf = new StringParameter(this, \"AlbSsmParam\", {\n parameterName: `/infosec/waf/services/${stage}/${app}-alb-arn`,\n description: `The ARN of the ALB for ${stage}-${app}.`,\n simpleName: false,\n stringValue: this.loadBalancerArn,\n tier: ParameterTier.STANDARD,\n dataType: ParameterDataType.TEXT,\n });\n }\n }\n}\n\nexport interface WafProps {\n enabled: boolean;\n}\n"]}
1
+ {"version":3,"file":"application-load-balancer.js","sourceRoot":"","sources":["../../../../src/constructs/loadbalancing/alb/application-load-balancer.ts"],"names":[],"mappings":";;;AAAA,6CAAqD;AACrD,uFAAiF;AAEjF,+CAA4C;AAC5C,iDAAwF;AACxF,kFAA+E;AAE/E,qCAAyE;AAEzE;;;;;;GAMG;AACU,QAAA,4CAA4C,GAAG,0DAA0D,CAAC;AAEvH;;;GAGG;AACU,QAAA,kCAAkC,GAAG,iDAAiD,CAAC;AA0BpG;;;;;;;;;GASG;AACH,MAAa,yBAA0B,SAAQ,IAAA,yCAAmB,EAAC,oDAAuB,CAAC;IAGzF,YAAY,KAAc,EAAE,EAAU,EAAE,KAAqC;QAC3E,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,iBAAiB,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;QACjE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;QAE/B,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;QAEzD,IAAI,CAAC,YAAY,CAAC,oDAA4C,EAAE,MAAM,CAAC,CAAC;QACxE,IAAI,CAAC,YAAY,CAAC,0CAAkC,EAAE,MAAM,CAAC,CAAC;QAE9D,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,YAA+B,CAAC;YACxD,KAAK,CAAC,2BAA2B,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,iBAAiB,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,eAAM,CAAC,cAAc,CAClC,KAAK,EACL,kBAAW,CAAC,iBAAiB,CAAC,KAAK,EAAE,qBAAqB,CAAC,EAC3D,qCAA8B,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,aAAa,CAChE,CAAC;YACF,MAAM,MAAM,GAAG,6BAA6B,KAAK,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;YACpE,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,YAAY,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;YACrD,yBAAW,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC;QACzE,CAAC;QAED,IAAI,uBAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,UAAU,EAAE;YAC/C,WAAW,EAAE,iBAAiB,IAAI,CAAC,SAAS,EAAE;YAC9C,KAAK,EAAE,IAAI,CAAC,mBAAmB;SAChC,CAAC,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC,SAAS,SAAS,CAAC,CAAC;QAEjD,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YACzB,IAAI,CAAC,GAAG,GAAG,IAAI,yBAAe,CAAC,IAAI,EAAE,aAAa,EAAE;gBAClD,aAAa,EAAE,yBAAyB,KAAK,IAAI,GAAG,UAAU;gBAC9D,WAAW,EAAE,0BAA0B,KAAK,IAAI,GAAG,GAAG;gBACtD,UAAU,EAAE,KAAK;gBACjB,WAAW,EAAE,IAAI,CAAC,eAAe;gBACjC,IAAI,EAAE,uBAAa,CAAC,QAAQ;gBAC5B,QAAQ,EAAE,2BAAiB,CAAC,IAAI;aACjC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF;AA9CD,8DA8CC","sourcesContent":["import { Annotations, CfnOutput } from \"aws-cdk-lib\";\nimport { ApplicationLoadBalancer } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport type { ApplicationLoadBalancerProps, CfnLoadBalancer } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport { Bucket } from \"aws-cdk-lib/aws-s3\";\nimport { ParameterDataType, ParameterTier, StringParameter } from \"aws-cdk-lib/aws-ssm\";\nimport { GuAppAwareConstruct } from \"../../../utils/mixin/app-aware-construct\";\nimport type { GuStack } from \"../../core\";\nimport { AppIdentity, GuAccessLoggingBucketParameter } from \"../../core\";\n\n/**\n * Adds the following headers to each request before forwarding it to the target:\n * - `x-amzn-tls-version`, which has information about the TLS protocol version negotiated with the client\n * - `x-amzn-tls-cipher-suite`, which has information about the cipher suite negotiated with the client\n *\n * Both headers are in OpenSSL format.\n */\nexport const TLS_VERSION_AND_CIPHER_SUITE_HEADERS_ENABLED = \"routing.http.x_amzn_tls_version_and_cipher_suite.enabled\";\n\n/**\n * Indicates whether HTTP headers with invalid header fields are removed by the load balancer.\n * Invalid headers are described as HTTP header names that do not conform to the regular expression [-A-Za-z0-9]+\n */\nexport const DROP_INVALID_HEADER_FIELDS_ENABLED = \"routing.http.drop_invalid_header_fields.enabled\";\n\ninterface GuApplicationLoadBalancerProps extends ApplicationLoadBalancerProps, AppIdentity {\n /**\n * If your CloudFormation does not define the Type of your Load Balancer, you must set this boolean to true to avoid\n * resource [replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-loadbalancer.html#cfn-elasticloadbalancingv2-loadbalancer-type).\n * If a Load Balancer is replaced it is likely to lead to downtime.\n */\n removeType?: boolean;\n\n /**\n * Enable access logging for this load balancer.\n * Access logs are written to an S3 bucket within your AWS account.\n * The bucket is created by {@link https://github.com/guardian/aws-account-setup}.\n * The logs are queryable via the `gucdk_access_logs` Athena database.\n *\n * @default true\n */\n withAccessLogging?: boolean;\n\n /**\n * Configuration for WAF protection, if desired\n */\n waf?: WafProps;\n}\n\n/**\n * Construct which creates an Application Load Balancer.\n *\n * This construct should be used in conjunction with [[`GuApplicationListener`]] and [[`GuApplicationTargetGroup`]]\n * to route traffic to your application. For more details on these three components, see the\n * [AWS documentation](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html#application-load-balancer-components).\n *\n * This resource is stateful.\n * @see https://github.com/guardian/cdk/blob/main/docs/stateful-resources.md\n */\nexport class GuApplicationLoadBalancer extends GuAppAwareConstruct(ApplicationLoadBalancer) {\n public readonly waf?: StringParameter;\n\n constructor(scope: GuStack, id: string, props: GuApplicationLoadBalancerProps) {\n const { app, removeType, waf, withAccessLogging = true } = props;\n const { stack, stage } = scope;\n\n super(scope, id, { deletionProtection: true, ...props });\n\n this.setAttribute(TLS_VERSION_AND_CIPHER_SUITE_HEADERS_ENABLED, \"true\");\n this.setAttribute(DROP_INVALID_HEADER_FIELDS_ENABLED, \"true\");\n\n if (removeType) {\n const cfnLb = this.node.defaultChild as CfnLoadBalancer;\n cfnLb.addPropertyDeletionOverride(\"Type\");\n }\n\n if (withAccessLogging) {\n const bucket = Bucket.fromBucketName(\n scope,\n AppIdentity.addAppToStringEnd(props, \"AccessLoggingBucket\"),\n GuAccessLoggingBucketParameter.getInstance(scope).valueAsString,\n );\n const prefix = `application-load-balancer/${stage}/${stack}/${app}`;\n this.logAccessLogs(bucket, prefix);\n } else {\n this.setAttribute(\"access_logs.s3.enabled\", \"false\");\n Annotations.of(this).addInfo(`Access logs disabled for load balancer`);\n }\n\n new CfnOutput(this, `${this.idWithApp}-DnsName`, {\n description: `DNS entry for ${this.idWithApp}`,\n value: this.loadBalancerDnsName,\n }).overrideLogicalId(`${this.idWithApp}DnsName`);\n\n if (!!waf && waf.enabled) {\n this.waf = new StringParameter(this, \"AlbSsmParam\", {\n parameterName: `/infosec/waf/services/${stage}/${app}-alb-arn`,\n description: `The ARN of the ALB for ${stage}-${app}.`,\n simpleName: false,\n stringValue: this.loadBalancerArn,\n tier: ParameterTier.STANDARD,\n dataType: ParameterDataType.TEXT,\n });\n }\n }\n}\n\nexport interface WafProps {\n enabled: boolean;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"gu-load-balanced-app.d.ts","sourceRoot":"","sources":["../../../src/experimental/patterns/gu-load-balanced-app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gu-load-balanced-app.d.ts","sourceRoot":"","sources":["../../../src/experimental/patterns/gu-load-balanced-app.ts"],"names":[],"mappings":"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"}