@guardian/cdk 50.0.0-beta.1 → 50.1.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 (43) hide show
  1. package/lib/bin/commands/new-project/index.js +9 -9
  2. package/lib/bin/commands/new-project/index.js.map +1 -1
  3. package/lib/constants/ssm-parameter-paths.d.ts +1 -0
  4. package/lib/constants/ssm-parameter-paths.d.ts.map +1 -1
  5. package/lib/constants/ssm-parameter-paths.js +4 -0
  6. package/lib/constants/ssm-parameter-paths.js.map +1 -1
  7. package/lib/constructs/autoscaling/asg.d.ts +2 -1
  8. package/lib/constructs/autoscaling/asg.d.ts.map +1 -1
  9. package/lib/constructs/autoscaling/asg.js +26 -10
  10. package/lib/constructs/autoscaling/asg.js.map +1 -1
  11. package/lib/constructs/cloudwatch/alarm.d.ts +1 -0
  12. package/lib/constructs/cloudwatch/alarm.d.ts.map +1 -1
  13. package/lib/constructs/cloudwatch/alarm.js +4 -1
  14. package/lib/constructs/cloudwatch/alarm.js.map +1 -1
  15. package/lib/constructs/lambda/lambda.d.ts +33 -22
  16. package/lib/constructs/lambda/lambda.d.ts.map +1 -1
  17. package/lib/constructs/lambda/lambda.js +29 -19
  18. package/lib/constructs/lambda/lambda.js.map +1 -1
  19. package/lib/constructs/loadbalancing/alb/application-listener.d.ts +1 -1
  20. package/lib/constructs/loadbalancing/alb/application-listener.d.ts.map +1 -1
  21. package/lib/constructs/loadbalancing/alb/application-listener.js +9 -7
  22. package/lib/constructs/loadbalancing/alb/application-listener.js.map +1 -1
  23. package/lib/experimental/riff-raff-yaml-file/deployments/cloudformation.d.ts.map +1 -1
  24. package/lib/experimental/riff-raff-yaml-file/deployments/cloudformation.js +3 -0
  25. package/lib/experimental/riff-raff-yaml-file/deployments/cloudformation.js.map +1 -1
  26. package/lib/experimental/riff-raff-yaml-file/index.d.ts.map +1 -1
  27. package/lib/experimental/riff-raff-yaml-file/index.js +1 -4
  28. package/lib/experimental/riff-raff-yaml-file/index.js.map +1 -1
  29. package/lib/patterns/ec2-app/base.d.ts +112 -243
  30. package/lib/patterns/ec2-app/base.d.ts.map +1 -1
  31. package/lib/patterns/ec2-app/base.js +14 -176
  32. package/lib/patterns/ec2-app/base.js.map +1 -1
  33. package/lib/patterns/ec2-app/framework.d.ts +13 -1
  34. package/lib/patterns/ec2-app/framework.d.ts.map +1 -1
  35. package/lib/patterns/ec2-app/framework.js +17 -1
  36. package/lib/patterns/ec2-app/framework.js.map +1 -1
  37. package/lib/patterns/scheduled-lambda.d.ts.map +1 -1
  38. package/lib/patterns/scheduled-lambda.js +1 -3
  39. package/lib/patterns/scheduled-lambda.js.map +1 -1
  40. package/lib/types/amigo.d.ts +12 -0
  41. package/lib/types/amigo.d.ts.map +1 -1
  42. package/lib/types/amigo.js.map +1 -1
  43. package/package.json +18 -17
@@ -101,30 +101,30 @@ const newCdkProject = async (props) => {
101
101
  });
102
102
  const commands = (0, utils_1.getCommands)(config.packageManager, config.cdkDir);
103
103
  if (config.init) {
104
- core_1.CliUx.ux.action.start(chalk_1.default.yellow("Installing dependencies. This may take a while..."));
104
+ core_1.ux.action.start(chalk_1.default.yellow("Installing dependencies. This may take a while..."));
105
105
  await commands.installDependencies();
106
- core_1.CliUx.ux.action.stop();
106
+ core_1.ux.action.stop();
107
107
  }
108
108
  // Run `eslint --fix` on the generated files instead of trying to generate code that completely satisfies the linter
109
109
  await (0, exec_1.execute)("./node_modules/.bin/eslint", ["lib/** bin/**", "--ext .ts", "--no-error-on-unmatched-pattern", "--fix"], {
110
110
  cwd: config.cdkDir,
111
111
  });
112
- core_1.CliUx.ux.action.start(chalk_1.default.yellow("Running lint check..."));
112
+ core_1.ux.action.start(chalk_1.default.yellow("Running lint check..."));
113
113
  await commands.lint();
114
- core_1.CliUx.ux.action.stop();
115
- core_1.CliUx.ux.action.start(chalk_1.default.yellow("Running tests..."));
114
+ core_1.ux.action.stop();
115
+ core_1.ux.action.start(chalk_1.default.yellow("Running tests..."));
116
116
  await commands.test();
117
- core_1.CliUx.ux.action.stop();
118
- core_1.CliUx.ux.action.start(chalk_1.default.yellow("Running initial synthesis..."));
117
+ core_1.ux.action.stop();
118
+ core_1.ux.action.start(chalk_1.default.yellow("Running initial synthesis..."));
119
119
  await commands.synth();
120
- core_1.CliUx.ux.action.stop();
120
+ core_1.ux.action.stop();
121
121
  console.log(chalk_1.default.green("Success! Here's a summary of the created files:"));
122
122
  const tree = await (0, exec_1.execute)("tree", ["-I 'node_modules|cdk.out'"], {
123
123
  cwd: config.cdkDir,
124
124
  });
125
125
  console.log(tree);
126
126
  const docsUrl = "https://github.com/guardian/cdk/tree/main/docs";
127
- core_1.CliUx.ux.url(chalk_1.default.green(`Please see the docs (${docsUrl}) for next steps.`), docsUrl);
127
+ core_1.ux.url(chalk_1.default.green(`Please see the docs (${docsUrl}) for next steps.`), docsUrl);
128
128
  return Promise.resolve(0);
129
129
  };
130
130
  exports.newCdkProject = newCdkProject;
@@ -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 { CliUx } from \"@oclif/core\";\nimport chalk from \"chalk\";\nimport kebabCase from \"lodash.kebabcase\";\nimport type { CliCommandResponse } from \"../../../types/cli\";\nimport { execute } from \"../../../utils/exec\";\nimport { gitRootOrCwd } from \"../../../utils/git\";\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, pascalCase } 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 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, yamlTemplateLocation, packageManager } = props;\n\n const rootDir = gitRootOrCwd();\n const cdkDir = join(rootDir, \"/cdk\");\n\n const appName = pascalCase(app);\n const kebabAppName = kebabCase(appName);\n const stackName = pascalCase(stack);\n const kebabStackName = kebabCase(stackName);\n\n const config: NewProjectConfig = {\n init,\n yamlTemplateLocation,\n stages,\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 });\n\n // lib directory\n await constructStack({\n imports: Imports.newStackImports(),\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 CliUx.ux.action.start(chalk.yellow(\"Installing dependencies. This may take a while...\"));\n await commands.installDependencies();\n CliUx.ux.action.stop();\n }\n\n // Run `eslint --fix` on the generated files instead of trying to generate code that completely satisfies the linter\n await execute(\n \"./node_modules/.bin/eslint\",\n [\"lib/** bin/**\", \"--ext .ts\", \"--no-error-on-unmatched-pattern\", \"--fix\"],\n {\n cwd: config.cdkDir,\n }\n );\n\n CliUx.ux.action.start(chalk.yellow(\"Running lint check...\"));\n await commands.lint();\n CliUx.ux.action.stop();\n\n CliUx.ux.action.start(chalk.yellow(\"Running tests...\"));\n await commands.test();\n CliUx.ux.action.stop();\n\n CliUx.ux.action.start(chalk.yellow(\"Running initial synthesis...\"));\n await commands.synth();\n CliUx.ux.action.stop();\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 CliUx.ux.url(chalk.green(`Please see the docs (${docsUrl}) for next steps.`), docsUrl);\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 { ux } from \"@oclif/core\";\nimport chalk from \"chalk\";\nimport kebabCase from \"lodash.kebabcase\";\nimport type { CliCommandResponse } from \"../../../types/cli\";\nimport { execute } from \"../../../utils/exec\";\nimport { gitRootOrCwd } from \"../../../utils/git\";\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, pascalCase } 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 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, yamlTemplateLocation, packageManager } = props;\n\n const rootDir = gitRootOrCwd();\n const cdkDir = join(rootDir, \"/cdk\");\n\n const appName = pascalCase(app);\n const kebabAppName = kebabCase(appName);\n const stackName = pascalCase(stack);\n const kebabStackName = kebabCase(stackName);\n\n const config: NewProjectConfig = {\n init,\n yamlTemplateLocation,\n stages,\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 });\n\n // lib directory\n await constructStack({\n imports: Imports.newStackImports(),\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 ux.action.start(chalk.yellow(\"Installing dependencies. This may take a while...\"));\n await commands.installDependencies();\n ux.action.stop();\n }\n\n // Run `eslint --fix` on the generated files instead of trying to generate code that completely satisfies the linter\n await execute(\n \"./node_modules/.bin/eslint\",\n [\"lib/** bin/**\", \"--ext .ts\", \"--no-error-on-unmatched-pattern\", \"--fix\"],\n {\n cwd: config.cdkDir,\n }\n );\n\n ux.action.start(chalk.yellow(\"Running lint check...\"));\n await commands.lint();\n ux.action.stop();\n\n ux.action.start(chalk.yellow(\"Running tests...\"));\n await commands.test();\n ux.action.stop();\n\n ux.action.start(chalk.yellow(\"Running initial synthesis...\"));\n await commands.synth();\n ux.action.stop();\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 ux.url(chalk.green(`Please see the docs (${docsUrl}) for next steps.`), docsUrl);\n\n return Promise.resolve(0);\n};\n"]}
@@ -14,6 +14,7 @@ interface NamedSsmParameterPaths {
14
14
  PrimaryVpcPrivateSubnets: SsmParameterPath;
15
15
  PrimaryVpcPublicSubnets: SsmParameterPath;
16
16
  FastlyCustomerId: SsmParameterPath;
17
+ OrganisationDistributionBucket: SsmParameterPath;
17
18
  }
18
19
  export declare const VPC_SSM_PARAMETER_PREFIX = "/account/vpc";
19
20
  export declare const NAMED_SSM_PARAMETER_PATHS: NamedSsmParameterPaths;
@@ -1 +1 @@
1
- {"version":3,"file":"ssm-parameter-paths.d.ts","sourceRoot":"","sources":["../../src/constants/ssm-parameter-paths.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAInB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,sBAAsB;IAC9B,WAAW,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,EAAE,gBAAgB,CAAC;IACpC,kBAAkB,EAAE,gBAAgB,CAAC;IACrC,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,wBAAwB,EAAE,gBAAgB,CAAC;IAC3C,uBAAuB,EAAE,gBAAgB,CAAC;IAC1C,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAED,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AAEvD,eAAO,MAAM,yBAAyB,EAAE,sBA0CvC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,gBAAgB,EAE/B,CAAC"}
1
+ {"version":3,"file":"ssm-parameter-paths.d.ts","sourceRoot":"","sources":["../../src/constants/ssm-parameter-paths.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAInB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,sBAAsB;IAC9B,WAAW,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,EAAE,gBAAgB,CAAC;IACpC,kBAAkB,EAAE,gBAAgB,CAAC;IACrC,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,wBAAwB,EAAE,gBAAgB,CAAC;IAC3C,uBAAuB,EAAE,gBAAgB,CAAC;IAC1C,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,8BAA8B,EAAE,gBAAgB,CAAC;CAClD;AAED,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AAEvD,eAAO,MAAM,yBAAyB,EAAE,sBA8CvC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,gBAAgB,EAE/B,CAAC"}
@@ -38,6 +38,10 @@ exports.NAMED_SSM_PARAMETER_PATHS = {
38
38
  path: `${exports.VPC_SSM_PARAMETER_PREFIX}/primary/subnets/public`,
39
39
  description: "A comma-separated list of public subnets",
40
40
  },
41
+ OrganisationDistributionBucket: {
42
+ path: "/organisation/services/artifact.bucket",
43
+ description: "SSM parameter containing the S3 bucket name holding organisation-level DevX artifacts",
44
+ },
41
45
  FastlyCustomerId: {
42
46
  path: "/account/external/fastly/customer.id",
43
47
  description: "SSM parameter containing the Fastly Customer ID. Can be obtained from https://manage.fastly.com/account/company by an admin",
@@ -1 +1 @@
1
- {"version":3,"file":"ssm-parameter-paths.js","sourceRoot":"","sources":["../../src/constants/ssm-parameter-paths.ts"],"names":[],"mappings":";;;AAsBa,QAAA,wBAAwB,GAAG,cAAc,CAAC;AAE1C,QAAA,yBAAyB,GAA2B;IAC/D,WAAW,EAAE;QACX,IAAI,EAAE,yCAAyC;QAC/C,WAAW,EAAE,+DAA+D;QAC5E,QAAQ,EAAE,IAAI;KACf;IACD,iBAAiB,EAAE;QACjB,IAAI,EAAE,uCAAuC;QAC7C,WAAW,EAAE,mEAAmE;KACjF;IACD,kBAAkB,EAAE;QAClB,IAAI,EAAE,mCAAmC;QACzC,WAAW,EAAE,4EAA4E;QACzF,aAAa,EAAE,2BAA2B;KAC3C;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,yCAAyC;QAC/C,WAAW,EAAE,qCAAqC;KACnD;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,yCAAyC;QAC/C,WAAW,EAAE,qFAAqF;QAClG,aAAa,EAAE,yBAAyB;KACzC;IACD,YAAY,EAAE;QACZ,IAAI,EAAE,GAAG,gCAAwB,aAAa;QAC9C,WAAW,EAAE,2FAA2F;KACzG;IACD,wBAAwB,EAAE;QACxB,IAAI,EAAE,GAAG,gCAAwB,0BAA0B;QAC3D,WAAW,EAAE,2CAA2C;KACzD;IACD,uBAAuB,EAAE;QACvB,IAAI,EAAE,GAAG,gCAAwB,yBAAyB;QAC1D,WAAW,EAAE,0CAA0C;KACxD;IACD,gBAAgB,EAAE;QAChB,IAAI,EAAE,sCAAsC;QAC5C,WAAW,EACT,6HAA6H;QAC/H,QAAQ,EAAE,IAAI;KACf;CACF,CAAC;AAEW,QAAA,uBAAuB,GAAuB,MAAM,CAAC,MAAM,CACtE,iCAAyB,CACJ,CAAC","sourcesContent":["export interface SsmParameterPath {\n path: string;\n description: string;\n optional?: boolean;\n\n // Recommended naming convention for target resource, such as an S3 bucket.\n // $account is substituted as the account name.\n namingPattern?: string;\n}\n\ninterface NamedSsmParameterPaths {\n Anghammarad: SsmParameterPath;\n LoggingStreamName: SsmParameterPath;\n DistributionBucket: SsmParameterPath;\n AccessLoggingBucket: SsmParameterPath;\n ConfigurationBucket: SsmParameterPath;\n PrimaryVpcId: SsmParameterPath;\n PrimaryVpcPrivateSubnets: SsmParameterPath;\n PrimaryVpcPublicSubnets: SsmParameterPath;\n FastlyCustomerId: SsmParameterPath;\n}\n\nexport const VPC_SSM_PARAMETER_PREFIX = \"/account/vpc\";\n\nexport const NAMED_SSM_PARAMETER_PATHS: NamedSsmParameterPaths = {\n Anghammarad: {\n path: \"/account/services/anghammarad.topic.arn\",\n description: \"SSM parameter containing the ARN of the Anghammarad SNS topic\",\n optional: true,\n },\n LoggingStreamName: {\n path: \"/account/services/logging.stream.name\",\n description: \"SSM parameter containing the Name (not ARN) on the kinesis stream\",\n },\n DistributionBucket: {\n path: \"/account/services/artifact.bucket\",\n description: \"SSM parameter containing the S3 bucket name holding distribution artifacts\",\n namingPattern: \"com-gu-$account-artifacts\",\n },\n AccessLoggingBucket: {\n path: \"/account/services/access-logging/bucket\",\n description: \"S3 bucket to store your access logs\",\n },\n ConfigurationBucket: {\n path: \"/account/services/private.config.bucket\",\n description: \"SSM parameter containing the S3 bucket name holding the app's private configuration\",\n namingPattern: \"com-gu-$account-configs\",\n },\n PrimaryVpcId: {\n path: `${VPC_SSM_PARAMETER_PREFIX}/primary/id`,\n description: \"Virtual Private Cloud to run EC2 instances within. Should NOT be the account default VPC.\",\n },\n PrimaryVpcPrivateSubnets: {\n path: `${VPC_SSM_PARAMETER_PREFIX}/primary/subnets/private`,\n description: \"A comma-separated list of private subnets\",\n },\n PrimaryVpcPublicSubnets: {\n path: `${VPC_SSM_PARAMETER_PREFIX}/primary/subnets/public`,\n description: \"A comma-separated list of public subnets\",\n },\n FastlyCustomerId: {\n path: \"/account/external/fastly/customer.id\",\n description:\n \"SSM parameter containing the Fastly Customer ID. Can be obtained from https://manage.fastly.com/account/company by an admin\",\n optional: true,\n },\n};\n\nexport const ALL_SSM_PARAMETER_PATHS: SsmParameterPath[] = Object.values(\n NAMED_SSM_PARAMETER_PATHS\n) as SsmParameterPath[];\n"]}
1
+ {"version":3,"file":"ssm-parameter-paths.js","sourceRoot":"","sources":["../../src/constants/ssm-parameter-paths.ts"],"names":[],"mappings":";;;AAuBa,QAAA,wBAAwB,GAAG,cAAc,CAAC;AAE1C,QAAA,yBAAyB,GAA2B;IAC/D,WAAW,EAAE;QACX,IAAI,EAAE,yCAAyC;QAC/C,WAAW,EAAE,+DAA+D;QAC5E,QAAQ,EAAE,IAAI;KACf;IACD,iBAAiB,EAAE;QACjB,IAAI,EAAE,uCAAuC;QAC7C,WAAW,EAAE,mEAAmE;KACjF;IACD,kBAAkB,EAAE;QAClB,IAAI,EAAE,mCAAmC;QACzC,WAAW,EAAE,4EAA4E;QACzF,aAAa,EAAE,2BAA2B;KAC3C;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,yCAAyC;QAC/C,WAAW,EAAE,qCAAqC;KACnD;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,yCAAyC;QAC/C,WAAW,EAAE,qFAAqF;QAClG,aAAa,EAAE,yBAAyB;KACzC;IACD,YAAY,EAAE;QACZ,IAAI,EAAE,GAAG,gCAAwB,aAAa;QAC9C,WAAW,EAAE,2FAA2F;KACzG;IACD,wBAAwB,EAAE;QACxB,IAAI,EAAE,GAAG,gCAAwB,0BAA0B;QAC3D,WAAW,EAAE,2CAA2C;KACzD;IACD,uBAAuB,EAAE;QACvB,IAAI,EAAE,GAAG,gCAAwB,yBAAyB;QAC1D,WAAW,EAAE,0CAA0C;KACxD;IACD,8BAA8B,EAAE;QAC9B,IAAI,EAAE,wCAAwC;QAC9C,WAAW,EAAE,uFAAuF;KACrG;IACD,gBAAgB,EAAE;QAChB,IAAI,EAAE,sCAAsC;QAC5C,WAAW,EACT,6HAA6H;QAC/H,QAAQ,EAAE,IAAI;KACf;CACF,CAAC;AAEW,QAAA,uBAAuB,GAAuB,MAAM,CAAC,MAAM,CACtE,iCAAyB,CACJ,CAAC","sourcesContent":["export interface SsmParameterPath {\n path: string;\n description: string;\n optional?: boolean;\n\n // Recommended naming convention for target resource, such as an S3 bucket.\n // $account is substituted as the account name.\n namingPattern?: string;\n}\n\ninterface NamedSsmParameterPaths {\n Anghammarad: SsmParameterPath;\n LoggingStreamName: SsmParameterPath;\n DistributionBucket: SsmParameterPath;\n AccessLoggingBucket: SsmParameterPath;\n ConfigurationBucket: SsmParameterPath;\n PrimaryVpcId: SsmParameterPath;\n PrimaryVpcPrivateSubnets: SsmParameterPath;\n PrimaryVpcPublicSubnets: SsmParameterPath;\n FastlyCustomerId: SsmParameterPath;\n OrganisationDistributionBucket: SsmParameterPath;\n}\n\nexport const VPC_SSM_PARAMETER_PREFIX = \"/account/vpc\";\n\nexport const NAMED_SSM_PARAMETER_PATHS: NamedSsmParameterPaths = {\n Anghammarad: {\n path: \"/account/services/anghammarad.topic.arn\",\n description: \"SSM parameter containing the ARN of the Anghammarad SNS topic\",\n optional: true,\n },\n LoggingStreamName: {\n path: \"/account/services/logging.stream.name\",\n description: \"SSM parameter containing the Name (not ARN) on the kinesis stream\",\n },\n DistributionBucket: {\n path: \"/account/services/artifact.bucket\",\n description: \"SSM parameter containing the S3 bucket name holding distribution artifacts\",\n namingPattern: \"com-gu-$account-artifacts\",\n },\n AccessLoggingBucket: {\n path: \"/account/services/access-logging/bucket\",\n description: \"S3 bucket to store your access logs\",\n },\n ConfigurationBucket: {\n path: \"/account/services/private.config.bucket\",\n description: \"SSM parameter containing the S3 bucket name holding the app's private configuration\",\n namingPattern: \"com-gu-$account-configs\",\n },\n PrimaryVpcId: {\n path: `${VPC_SSM_PARAMETER_PREFIX}/primary/id`,\n description: \"Virtual Private Cloud to run EC2 instances within. Should NOT be the account default VPC.\",\n },\n PrimaryVpcPrivateSubnets: {\n path: `${VPC_SSM_PARAMETER_PREFIX}/primary/subnets/private`,\n description: \"A comma-separated list of private subnets\",\n },\n PrimaryVpcPublicSubnets: {\n path: `${VPC_SSM_PARAMETER_PREFIX}/primary/subnets/public`,\n description: \"A comma-separated list of public subnets\",\n },\n OrganisationDistributionBucket: {\n path: \"/organisation/services/artifact.bucket\",\n description: \"SSM parameter containing the S3 bucket name holding organisation-level DevX artifacts\",\n },\n FastlyCustomerId: {\n path: \"/account/external/fastly/customer.id\",\n description:\n \"SSM parameter containing the Fastly Customer ID. Can be obtained from https://manage.fastly.com/account/company by an admin\",\n optional: true,\n },\n};\n\nexport const ALL_SSM_PARAMETER_PATHS: SsmParameterPath[] = Object.values(\n NAMED_SSM_PARAMETER_PATHS\n) as SsmParameterPath[];\n"]}
@@ -1,7 +1,7 @@
1
1
  import { AutoScalingGroup } from "aws-cdk-lib/aws-autoscaling";
2
2
  import type { AutoScalingGroupProps } from "aws-cdk-lib/aws-autoscaling";
3
3
  import { UserData } from "aws-cdk-lib/aws-ec2";
4
- import type { ISecurityGroup } from "aws-cdk-lib/aws-ec2";
4
+ import type { InstanceType, ISecurityGroup } from "aws-cdk-lib/aws-ec2";
5
5
  import type { ApplicationTargetGroup } from "aws-cdk-lib/aws-elasticloadbalancingv2";
6
6
  import type { GuAsgCapacity } from "../../types";
7
7
  import type { AmigoProps } from "../../types/amigo";
@@ -10,6 +10,7 @@ import type { AppIdentity, GuStack } from "../core";
10
10
  export interface GuAutoScalingGroupProps extends Omit<AutoScalingGroupProps, "imageId" | "osType" | "machineImage" | "userData" | "minCapacity" | "maxCapacity" | "desiredCapacity" | "requireImdsv2" | "securityGroup">, AppIdentity, GuAsgCapacity {
11
11
  imageId?: GuAmiParameter;
12
12
  imageRecipe?: string | AmigoProps;
13
+ instanceType: InstanceType;
13
14
  userData: UserData | string;
14
15
  additionalSecurityGroups?: ISecurityGroup[];
15
16
  targetGroup?: ApplicationTargetGroup;
@@ -1 +1 @@
1
- {"version":3,"file":"asg.d.ts","sourceRoot":"","sources":["../../../src/constructs/autoscaling/asg.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAuB,MAAM,6BAA6B,CAAC;AAC9F,OAAO,EAAuB,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAsB,MAAM,qBAAqB,CAAC;AAC9E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAOpD,MAAM,WAAW,uBACf,SAAQ,IAAI,CACR,qBAAqB,EACnB,SAAS,GACT,QAAQ,GACR,cAAc,GACd,UAAU,GACV,aAAa,GACb,aAAa,GACb,iBAAiB,GACjB,eAAe,GACf,eAAe,CAClB,EACD,WAAW,EACX,aAAa;IACf,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAClC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC5B,wBAAwB,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5C,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;;;;;;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,kBAAmB,SAAQ,uBAAqC;IAC3E,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,SAAgB,YAAY,EAAE,cAAc,CAAC;IAC7C,SAAgB,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;gBAEtC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB;CA4DvE"}
1
+ {"version":3,"file":"asg.d.ts","sourceRoot":"","sources":["../../../src/constructs/autoscaling/asg.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAuB,MAAM,6BAA6B,CAAC;AAC9F,OAAO,EAAuC,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAsB,MAAM,qBAAqB,CAAC;AAC5F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAQpD,MAAM,WAAW,uBACf,SAAQ,IAAI,CACR,qBAAqB,EACnB,SAAS,GACT,QAAQ,GACR,cAAc,GACd,UAAU,GACV,aAAa,GACb,aAAa,GACb,iBAAiB,GACjB,eAAe,GACf,eAAe,CAClB,EACD,WAAW,EACX,aAAa;IACf,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAClC,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC5B,wBAAwB,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5C,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;;;;;;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,kBAAmB,SAAQ,uBAAqC;IAC3E,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,SAAgB,YAAY,EAAE,cAAc,CAAC;IAC7C,SAAgB,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;gBAEtC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB;CAoFvE"}
@@ -30,18 +30,17 @@ const iam_1 = require("../iam");
30
30
  */
31
31
  class GuAutoScalingGroup extends (0, app_aware_construct_1.GuAppAwareConstruct)(aws_autoscaling_1.AutoScalingGroup) {
32
32
  constructor(scope, id, props) {
33
- const { app, additionalSecurityGroups = [], imageId = new core_1.GuAmiParameter(scope, { app }), imageRecipe, minimumInstances, maximumInstances, role = new iam_1.GuInstanceRole(scope, { app }), targetGroup, userData: userDataLike, vpc, withoutImdsv2 = false, } = props;
33
+ const { app, additionalSecurityGroups = [], blockDevices, imageId = new core_1.GuAmiParameter(scope, { app }), imageRecipe, instanceType, minimumInstances, maximumInstances, role = new iam_1.GuInstanceRole(scope, { app }), targetGroup, userData: userDataLike, vpc, withoutImdsv2 = false, } = props;
34
34
  // Ensure min and max are defined in the same way. Throwing an `Error` when necessary. For example when min is defined via a Mapping, but max is not.
35
35
  if (aws_cdk_lib_1.Token.isUnresolved(minimumInstances) && !aws_cdk_lib_1.Token.isUnresolved(maximumInstances)) {
36
36
  throw new Error("minimumInstances is defined via a Mapping, but maximumInstances is not. Create maximumInstances via a Mapping too.");
37
37
  }
38
38
  const userData = userDataLike instanceof aws_ec2_1.UserData ? userDataLike : aws_ec2_1.UserData.custom(userDataLike);
39
- const mergedProps = {
40
- ...props,
41
- minCapacity: minimumInstances,
42
- maxCapacity: maximumInstances ?? minimumInstances * 2,
43
- role,
44
- requireImdsv2: !withoutImdsv2,
39
+ // Generate an ID unique to this app
40
+ const launchTemplateId = `${scope.stack}-${scope.stage}-${app}`;
41
+ const launchTemplate = new aws_ec2_1.LaunchTemplate(scope, launchTemplateId, {
42
+ blockDevices,
43
+ instanceType,
45
44
  machineImage: {
46
45
  getImage: () => {
47
46
  return {
@@ -51,17 +50,34 @@ class GuAutoScalingGroup extends (0, app_aware_construct_1.GuAppAwareConstruct)(
51
50
  };
52
51
  },
53
52
  },
54
- userData,
55
53
  // Do not use the default AWS security group which allows egress on any port.
56
54
  // Favour HTTPS only egress rules by default.
57
55
  securityGroup: ec2_1.GuHttpsEgressSecurityGroup.forVpc(scope, { app, vpc }),
56
+ requireImdsv2: !withoutImdsv2,
57
+ userData,
58
+ role,
59
+ });
60
+ // Add Wazuh & additional consumer specified Security Groups
61
+ // Note: Launch templates via CDK allow specifying only one SG, so use connections
62
+ // https://github.com/aws/aws-cdk/issues/18712
63
+ [ec2_1.GuWazuhAccess.getInstance(scope, vpc), ...additionalSecurityGroups].forEach((sg) => launchTemplate.connections.addSecurityGroup(sg));
64
+ const asgProps = {
65
+ ...props,
66
+ launchTemplate,
67
+ maxCapacity: maximumInstances ?? minimumInstances * 2,
68
+ minCapacity: minimumInstances,
69
+ // Omit userData, instanceType, blockDevices & role from asgProps
70
+ // As this are specified by the LaunchTemplate and must not be duplicated
71
+ blockDevices: undefined,
72
+ instanceType: undefined,
73
+ role: undefined,
74
+ userData: undefined,
58
75
  };
59
- super(scope, id, mergedProps);
76
+ super(scope, id, asgProps);
60
77
  this.app = app;
61
78
  this.amiParameter = imageId;
62
79
  this.imageRecipe = imageRecipe;
63
80
  targetGroup && this.attachToApplicationTargetGroup(targetGroup);
64
- [ec2_1.GuWazuhAccess.getInstance(scope, vpc), ...additionalSecurityGroups].forEach((sg) => this.addSecurityGroup(sg));
65
81
  const cfnAsg = this.node.defaultChild;
66
82
  // A CDK AutoScalingGroup comes with this update policy, whereas the CFN autscaling group
67
83
  // leaves it to the default value, which is actually false.
@@ -1 +1 @@
1
- {"version":3,"file":"asg.js","sourceRoot":"","sources":["../../../src/constructs/autoscaling/asg.ts"],"names":[],"mappings":";;;AAAA,6CAAoC;AACpC,iEAA+D;AAE/D,iDAAoE;AAKpE,+EAA4E;AAC5E,kCAAyC;AAEzC,gCAAmE;AACnE,gCAAwC;AA4BxC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAa,kBAAmB,SAAQ,IAAA,yCAAmB,EAAC,kCAAgB,CAAC;IAK3E,YAAY,KAAc,EAAE,EAAU,EAAE,KAA8B;QACpE,MAAM,EACJ,GAAG,EACH,wBAAwB,GAAG,EAAE,EAC7B,OAAO,GAAG,IAAI,qBAAc,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,EAC5C,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,IAAI,GAAG,IAAI,oBAAc,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,EACzC,WAAW,EACX,QAAQ,EAAE,YAAY,EACtB,GAAG,EACH,aAAa,GAAG,KAAK,GACtB,GAAG,KAAK,CAAC;QAEV,qJAAqJ;QACrJ,IAAI,mBAAK,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,CAAC,mBAAK,CAAC,YAAY,CAAC,gBAAgB,CAAC,EAAE;YACjF,MAAM,IAAI,KAAK,CACb,oHAAoH,CACrH,CAAC;SACH;QAED,MAAM,QAAQ,GAAG,YAAY,YAAY,kBAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,kBAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAEjG,MAAM,WAAW,GAA0B;YACzC,GAAG,KAAK;YACR,WAAW,EAAE,gBAAgB;YAC7B,WAAW,EAAE,gBAAgB,IAAI,gBAAgB,GAAG,CAAC;YACrD,IAAI;YACJ,aAAa,EAAE,CAAC,aAAa;YAC7B,YAAY,EAAE;gBACZ,QAAQ,EAAE,GAAuB,EAAE;oBACjC,OAAO;wBACL,MAAM,EAAE,6BAAmB,CAAC,KAAK;wBACjC,QAAQ;wBACR,OAAO,EAAE,OAAO,CAAC,aAAa;qBAC/B,CAAC;gBACJ,CAAC;aACF;YACD,QAAQ;YACR,6EAA6E;YAC7E,6CAA6C;YAC7C,aAAa,EAAE,gCAA0B,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;SACtE,CAAC;QAEF,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;QAC5B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAE/B,WAAW,IAAI,IAAI,CAAC,8BAA8B,CAAC,WAAW,CAAC,CAAC;QAEhE,CAAC,mBAAa,CAAC,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,wBAAwB,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC;QAEhH,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,YAAmC,CAAC;QAC7D,yFAAyF;QACzF,2DAA2D;QAC3D,+FAA+F;QAC/F,MAAM,CAAC,mBAAmB,CAAC,cAAc,CAAC,CAAC;IAC7C,CAAC;CACF;AAjED,gDAiEC","sourcesContent":["import { Token } from \"aws-cdk-lib\";\nimport { AutoScalingGroup } from \"aws-cdk-lib/aws-autoscaling\";\nimport type { AutoScalingGroupProps, CfnAutoScalingGroup } from \"aws-cdk-lib/aws-autoscaling\";\nimport { OperatingSystemType, UserData } from \"aws-cdk-lib/aws-ec2\";\nimport type { ISecurityGroup, MachineImageConfig } from \"aws-cdk-lib/aws-ec2\";\nimport type { ApplicationTargetGroup } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport type { GuAsgCapacity } from \"../../types\";\nimport type { AmigoProps } from \"../../types/amigo\";\nimport { GuAppAwareConstruct } from \"../../utils/mixin/app-aware-construct\";\nimport { GuAmiParameter } from \"../core\";\nimport type { AppIdentity, GuStack } from \"../core\";\nimport { GuHttpsEgressSecurityGroup, GuWazuhAccess } from \"../ec2\";\nimport { GuInstanceRole } from \"../iam\";\n\n// Since we want to override the types of what gets passed in for the below props,\n// we need to use Omit<T, U> to remove them from the interface this extends\n// https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys\nexport interface GuAutoScalingGroupProps\n extends Omit<\n AutoScalingGroupProps,\n | \"imageId\"\n | \"osType\"\n | \"machineImage\"\n | \"userData\"\n | \"minCapacity\"\n | \"maxCapacity\"\n | \"desiredCapacity\"\n | \"requireImdsv2\"\n | \"securityGroup\"\n >,\n AppIdentity,\n GuAsgCapacity {\n imageId?: GuAmiParameter;\n imageRecipe?: string | AmigoProps;\n userData: UserData | string;\n additionalSecurityGroups?: ISecurityGroup[];\n targetGroup?: ApplicationTargetGroup;\n withoutImdsv2?: boolean;\n}\n\n/**\n * Construct which creates an Auto Scaling group.\n *\n * By default, all EC2 instances in this group will use [[`GuInstanceRole`]],\n * which provides common permissions (e.g. the ability to download an artifact and write logs to the account's logging Kinesis stream).\n *\n * If additional IAM permissions are required, a custom role can be provided via the `role` prop.\n * You may wish to instantiate [[`GuInstanceRole`]] yourself as a basis for this custom role, as it allows custom permissions\n * to be passed in.\n *\n * All EC2 instances in this group will be automatically associated with two security groups:\n * 1. [[`GuHttpsEgressSecurityGroup`]], which allows outbound traffic over HTTPS.\n * 2. [[`GuWazuhAccess`]], which allows instances to communicate with Wazuh (for security monitoring).\n *\n * If additional ingress or egress rules are required, define custom security groups and pass them in via the\n * `additionalSecurityGroups` prop.\n *\n * All EC2 instances provisioned via this construct will use\n * [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html).\n */\nexport class GuAutoScalingGroup extends GuAppAwareConstruct(AutoScalingGroup) {\n public readonly app: string;\n public readonly amiParameter: GuAmiParameter;\n public readonly imageRecipe?: string | AmigoProps;\n\n constructor(scope: GuStack, id: string, props: GuAutoScalingGroupProps) {\n const {\n app,\n additionalSecurityGroups = [],\n imageId = new GuAmiParameter(scope, { app }),\n imageRecipe,\n minimumInstances,\n maximumInstances,\n role = new GuInstanceRole(scope, { app }),\n targetGroup,\n userData: userDataLike,\n vpc,\n withoutImdsv2 = false,\n } = props;\n\n // Ensure min and max are defined in the same way. Throwing an `Error` when necessary. For example when min is defined via a Mapping, but max is not.\n if (Token.isUnresolved(minimumInstances) && !Token.isUnresolved(maximumInstances)) {\n throw new Error(\n \"minimumInstances is defined via a Mapping, but maximumInstances is not. Create maximumInstances via a Mapping too.\"\n );\n }\n\n const userData = userDataLike instanceof UserData ? userDataLike : UserData.custom(userDataLike);\n\n const mergedProps: AutoScalingGroupProps = {\n ...props,\n minCapacity: minimumInstances,\n maxCapacity: maximumInstances ?? minimumInstances * 2,\n role,\n requireImdsv2: !withoutImdsv2,\n machineImage: {\n getImage: (): MachineImageConfig => {\n return {\n osType: OperatingSystemType.LINUX,\n userData,\n imageId: imageId.valueAsString,\n };\n },\n },\n userData,\n // Do not use the default AWS security group which allows egress on any port.\n // Favour HTTPS only egress rules by default.\n securityGroup: GuHttpsEgressSecurityGroup.forVpc(scope, { app, vpc }),\n };\n\n super(scope, id, mergedProps);\n this.app = app;\n this.amiParameter = imageId;\n this.imageRecipe = imageRecipe;\n\n targetGroup && this.attachToApplicationTargetGroup(targetGroup);\n\n [GuWazuhAccess.getInstance(scope, vpc), ...additionalSecurityGroups].forEach((sg) => this.addSecurityGroup(sg));\n\n const cfnAsg = this.node.defaultChild as CfnAutoScalingGroup;\n // A CDK AutoScalingGroup comes with this update policy, whereas the CFN autscaling group\n // leaves it to the default value, which is actually false.\n // { UpdatePolicy: { autoScalingScheduledAction: { IgnoreUnmodifiedGroupSizeProperties: true }}\n cfnAsg.addDeletionOverride(\"UpdatePolicy\");\n }\n}\n"]}
1
+ {"version":3,"file":"asg.js","sourceRoot":"","sources":["../../../src/constructs/autoscaling/asg.ts"],"names":[],"mappings":"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","sourcesContent":["import { Token } from \"aws-cdk-lib\";\nimport { AutoScalingGroup } from \"aws-cdk-lib/aws-autoscaling\";\nimport type { AutoScalingGroupProps, CfnAutoScalingGroup } from \"aws-cdk-lib/aws-autoscaling\";\nimport { LaunchTemplate, OperatingSystemType, UserData } from \"aws-cdk-lib/aws-ec2\";\nimport type { InstanceType, ISecurityGroup, MachineImageConfig } from \"aws-cdk-lib/aws-ec2\";\nimport type { ApplicationTargetGroup } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport type { GuAsgCapacity } from \"../../types\";\nimport type { AmigoProps } from \"../../types/amigo\";\nimport { GuAppAwareConstruct } from \"../../utils/mixin/app-aware-construct\";\nimport { GuAmiParameter } from \"../core\";\nimport type { AppIdentity, GuStack } from \"../core\";\nimport { GuHttpsEgressSecurityGroup, GuWazuhAccess } from \"../ec2\";\nimport { GuInstanceRole } from \"../iam\";\n\n// Since we want to override the types of what gets passed in for the below props,\n// we need to use Omit<T, U> to remove them from the interface this extends\n// https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys\n// TODO avoid prop nesting to improve discoverability. See https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md#flat.\nexport interface GuAutoScalingGroupProps\n extends Omit<\n AutoScalingGroupProps,\n | \"imageId\"\n | \"osType\"\n | \"machineImage\"\n | \"userData\"\n | \"minCapacity\"\n | \"maxCapacity\"\n | \"desiredCapacity\"\n | \"requireImdsv2\"\n | \"securityGroup\"\n >,\n AppIdentity,\n GuAsgCapacity {\n imageId?: GuAmiParameter;\n imageRecipe?: string | AmigoProps;\n instanceType: InstanceType;\n userData: UserData | string;\n additionalSecurityGroups?: ISecurityGroup[];\n targetGroup?: ApplicationTargetGroup;\n withoutImdsv2?: boolean;\n}\n\n/**\n * Construct which creates an Auto Scaling group.\n *\n * By default, all EC2 instances in this group will use [[`GuInstanceRole`]],\n * which provides common permissions (e.g. the ability to download an artifact and write logs to the account's logging Kinesis stream).\n *\n * If additional IAM permissions are required, a custom role can be provided via the `role` prop.\n * You may wish to instantiate [[`GuInstanceRole`]] yourself as a basis for this custom role, as it allows custom permissions\n * to be passed in.\n *\n * All EC2 instances in this group will be automatically associated with two security groups:\n * 1. [[`GuHttpsEgressSecurityGroup`]], which allows outbound traffic over HTTPS.\n * 2. [[`GuWazuhAccess`]], which allows instances to communicate with Wazuh (for security monitoring).\n *\n * If additional ingress or egress rules are required, define custom security groups and pass them in via the\n * `additionalSecurityGroups` prop.\n *\n * All EC2 instances provisioned via this construct will use\n * [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html).\n */\nexport class GuAutoScalingGroup extends GuAppAwareConstruct(AutoScalingGroup) {\n public readonly app: string;\n public readonly amiParameter: GuAmiParameter;\n public readonly imageRecipe?: string | AmigoProps;\n\n constructor(scope: GuStack, id: string, props: GuAutoScalingGroupProps) {\n const {\n app,\n additionalSecurityGroups = [],\n blockDevices,\n imageId = new GuAmiParameter(scope, { app }),\n imageRecipe,\n instanceType,\n minimumInstances,\n maximumInstances,\n role = new GuInstanceRole(scope, { app }),\n targetGroup,\n userData: userDataLike,\n vpc,\n withoutImdsv2 = false,\n } = props;\n\n // Ensure min and max are defined in the same way. Throwing an `Error` when necessary. For example when min is defined via a Mapping, but max is not.\n if (Token.isUnresolved(minimumInstances) && !Token.isUnresolved(maximumInstances)) {\n throw new Error(\n \"minimumInstances is defined via a Mapping, but maximumInstances is not. Create maximumInstances via a Mapping too.\"\n );\n }\n\n const userData = userDataLike instanceof UserData ? userDataLike : UserData.custom(userDataLike);\n\n // Generate an ID unique to this app\n const launchTemplateId = `${scope.stack}-${scope.stage}-${app}`;\n const launchTemplate = new LaunchTemplate(scope, launchTemplateId, {\n blockDevices,\n instanceType,\n machineImage: {\n getImage: (): MachineImageConfig => {\n return {\n osType: OperatingSystemType.LINUX,\n userData,\n imageId: imageId.valueAsString,\n };\n },\n },\n // Do not use the default AWS security group which allows egress on any port.\n // Favour HTTPS only egress rules by default.\n securityGroup: GuHttpsEgressSecurityGroup.forVpc(scope, { app, vpc }),\n requireImdsv2: !withoutImdsv2,\n userData,\n role,\n });\n\n // Add Wazuh & additional consumer specified Security Groups\n // Note: Launch templates via CDK allow specifying only one SG, so use connections\n // https://github.com/aws/aws-cdk/issues/18712\n [GuWazuhAccess.getInstance(scope, vpc), ...additionalSecurityGroups].forEach((sg) =>\n launchTemplate.connections.addSecurityGroup(sg)\n );\n\n const asgProps = {\n ...props,\n launchTemplate,\n maxCapacity: maximumInstances ?? minimumInstances * 2,\n minCapacity: minimumInstances,\n\n // Omit userData, instanceType, blockDevices & role from asgProps\n // As this are specified by the LaunchTemplate and must not be duplicated\n blockDevices: undefined,\n instanceType: undefined,\n role: undefined,\n userData: undefined,\n };\n\n super(scope, id, asgProps);\n\n this.app = app;\n this.amiParameter = imageId;\n this.imageRecipe = imageRecipe;\n\n targetGroup && this.attachToApplicationTargetGroup(targetGroup);\n\n const cfnAsg = this.node.defaultChild as CfnAutoScalingGroup;\n\n // A CDK AutoScalingGroup comes with this update policy, whereas the CFN autscaling group\n // leaves it to the default value, which is actually false.\n // { UpdatePolicy: { autoScalingScheduledAction: { IgnoreUnmodifiedGroupSizeProperties: true }}\n cfnAsg.addDeletionOverride(\"UpdatePolicy\");\n }\n}\n"]}
@@ -3,6 +3,7 @@ import type { AlarmProps } from "aws-cdk-lib/aws-cloudwatch";
3
3
  import type { AppIdentity, GuStack } from "../core";
4
4
  export interface GuAlarmProps extends AlarmProps, AppIdentity {
5
5
  snsTopicName: string;
6
+ okAction?: boolean;
6
7
  }
7
8
  export interface Http5xxAlarmProps extends Omit<GuAlarmProps, "snsTopicName" | "evaluationPeriods" | "metric" | "period" | "threshold" | "treatMissingData" | "app"> {
8
9
  tolerated5xxPercentage: number;
@@ -1 +1 @@
1
- {"version":3,"file":"alarm.d.ts","sourceRoot":"","sources":["../../../src/constructs/cloudwatch/alarm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAI7D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEpD,MAAM,WAAW,YAAa,SAAQ,UAAU,EAAE,WAAW;IAC3D,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBACf,SAAQ,IAAI,CACV,YAAY,EACZ,cAAc,GAAG,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,kBAAkB,GAAG,KAAK,CACtG;IACD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wCAAwC,CAAC,EAAE,MAAM,CAAC;CACnD;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,OAAQ,SAAQ,KAAK;gBACpB,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY;CAU5D"}
1
+ {"version":3,"file":"alarm.d.ts","sourceRoot":"","sources":["../../../src/constructs/cloudwatch/alarm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAI7D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEpD,MAAM,WAAW,YAAa,SAAQ,UAAU,EAAE,WAAW;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,iBACf,SAAQ,IAAI,CACV,YAAY,EACZ,cAAc,GAAG,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,kBAAkB,GAAG,KAAK,CACtG;IACD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wCAAwC,CAAC,EAAE,MAAM,CAAC;CACnD;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,OAAQ,SAAQ,KAAK;gBACpB,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY;CAa5D"}
@@ -23,11 +23,14 @@ const aws_sns_1 = require("aws-cdk-lib/aws-sns");
23
23
  class GuAlarm extends aws_cloudwatch_1.Alarm {
24
24
  constructor(scope, id, props) {
25
25
  const { region, account } = scope;
26
- const { snsTopicName, actionsEnabled = true } = props;
26
+ const { snsTopicName, actionsEnabled = true, okAction } = props;
27
27
  super(scope, id, { ...props, actionsEnabled });
28
28
  const topicArn = `arn:aws:sns:${region}:${account}:${snsTopicName}`;
29
29
  const snsTopic = aws_sns_1.Topic.fromTopicArn(scope, `SnsTopicFor${id}`, topicArn);
30
30
  this.addAlarmAction(new aws_cloudwatch_actions_1.SnsAction(snsTopic));
31
+ if (okAction) {
32
+ this.addOkAction(new aws_cloudwatch_actions_1.SnsAction(snsTopic));
33
+ }
31
34
  }
32
35
  }
33
36
  exports.GuAlarm = GuAlarm;
@@ -1 +1 @@
1
- {"version":3,"file":"alarm.js","sourceRoot":"","sources":["../../../src/constructs/cloudwatch/alarm.ts"],"names":[],"mappings":";;;AAAA,+DAAmD;AAEnD,+EAA+D;AAC/D,iDAA4C;AAiB5C;;;;;;;;;;;;;;;GAeG;AACH,MAAa,OAAQ,SAAQ,sBAAK;IAChC,YAAY,KAAc,EAAE,EAAU,EAAE,KAAmB;QACzD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;QAClC,MAAM,EAAE,YAAY,EAAE,cAAc,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;QAEtD,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QAE/C,MAAM,QAAQ,GAAW,eAAe,MAAM,IAAI,OAAO,IAAI,YAAY,EAAE,CAAC;QAC5E,MAAM,QAAQ,GAAW,eAAK,CAAC,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;QACjF,IAAI,CAAC,cAAc,CAAC,IAAI,kCAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/C,CAAC;CACF;AAXD,0BAWC","sourcesContent":["import { Alarm } from \"aws-cdk-lib/aws-cloudwatch\";\nimport type { AlarmProps } from \"aws-cdk-lib/aws-cloudwatch\";\nimport { SnsAction } from \"aws-cdk-lib/aws-cloudwatch-actions\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport type { ITopic } from \"aws-cdk-lib/aws-sns\";\nimport type { AppIdentity, GuStack } from \"../core\";\n\nexport interface GuAlarmProps extends AlarmProps, AppIdentity {\n snsTopicName: string;\n}\n\nexport interface Http5xxAlarmProps\n extends Omit<\n GuAlarmProps,\n \"snsTopicName\" | \"evaluationPeriods\" | \"metric\" | \"period\" | \"threshold\" | \"treatMissingData\" | \"app\"\n > {\n tolerated5xxPercentage: number;\n numberOfMinutesAboveThresholdBeforeAlarm?: number;\n}\n\n/**\n * Creates a CloudWatch alarm which sends notifications to the specified SNS topic.\n *\n * Alarm actions are enabled by default.\n *\n * To enable the alarm only in PROD, use the value of `Stage`:\n * ```typescript\n * new GuAlarm(stack, \"alarm\", {\n * // other required props\n * actionsEnabled: this.stage === \"PROD\",\n * });\n * ```\n *\n * This library provides an implementation of some commonly used alarms, which require less boilerplate than this construct,\n * for example the [[`GuAlb5xxPercentageAlarm`]]. Prefer using these more specific implementations where possible.\n */\nexport class GuAlarm extends Alarm {\n constructor(scope: GuStack, id: string, props: GuAlarmProps) {\n const { region, account } = scope;\n const { snsTopicName, actionsEnabled = true } = props;\n\n super(scope, id, { ...props, actionsEnabled });\n\n const topicArn: string = `arn:aws:sns:${region}:${account}:${snsTopicName}`;\n const snsTopic: ITopic = Topic.fromTopicArn(scope, `SnsTopicFor${id}`, topicArn);\n this.addAlarmAction(new SnsAction(snsTopic));\n }\n}\n"]}
1
+ {"version":3,"file":"alarm.js","sourceRoot":"","sources":["../../../src/constructs/cloudwatch/alarm.ts"],"names":[],"mappings":";;;AAAA,+DAAmD;AAEnD,+EAA+D;AAC/D,iDAA4C;AAkB5C;;;;;;;;;;;;;;;GAeG;AACH,MAAa,OAAQ,SAAQ,sBAAK;IAChC,YAAY,KAAc,EAAE,EAAU,EAAE,KAAmB;QACzD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;QAClC,MAAM,EAAE,YAAY,EAAE,cAAc,GAAG,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;QAEhE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QAE/C,MAAM,QAAQ,GAAW,eAAe,MAAM,IAAI,OAAO,IAAI,YAAY,EAAE,CAAC;QAC5E,MAAM,QAAQ,GAAW,eAAK,CAAC,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;QACjF,IAAI,CAAC,cAAc,CAAC,IAAI,kCAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC7C,IAAI,QAAQ,EAAE;YACZ,IAAI,CAAC,WAAW,CAAC,IAAI,kCAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;SAC3C;IACH,CAAC;CACF;AAdD,0BAcC","sourcesContent":["import { Alarm } from \"aws-cdk-lib/aws-cloudwatch\";\nimport type { AlarmProps } from \"aws-cdk-lib/aws-cloudwatch\";\nimport { SnsAction } from \"aws-cdk-lib/aws-cloudwatch-actions\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport type { ITopic } from \"aws-cdk-lib/aws-sns\";\nimport type { AppIdentity, GuStack } from \"../core\";\n\nexport interface GuAlarmProps extends AlarmProps, AppIdentity {\n snsTopicName: string;\n okAction?: boolean;\n}\n\nexport interface Http5xxAlarmProps\n extends Omit<\n GuAlarmProps,\n \"snsTopicName\" | \"evaluationPeriods\" | \"metric\" | \"period\" | \"threshold\" | \"treatMissingData\" | \"app\"\n > {\n tolerated5xxPercentage: number;\n numberOfMinutesAboveThresholdBeforeAlarm?: number;\n}\n\n/**\n * Creates a CloudWatch alarm which sends notifications to the specified SNS topic.\n *\n * Alarm actions are enabled by default.\n *\n * To enable the alarm only in PROD, use the value of `Stage`:\n * ```typescript\n * new GuAlarm(stack, \"alarm\", {\n * // other required props\n * actionsEnabled: this.stage === \"PROD\",\n * });\n * ```\n *\n * This library provides an implementation of some commonly used alarms, which require less boilerplate than this construct,\n * for example the [[`GuAlb5xxPercentageAlarm`]]. Prefer using these more specific implementations where possible.\n */\nexport class GuAlarm extends Alarm {\n constructor(scope: GuStack, id: string, props: GuAlarmProps) {\n const { region, account } = scope;\n const { snsTopicName, actionsEnabled = true, okAction } = props;\n\n super(scope, id, { ...props, actionsEnabled });\n\n const topicArn: string = `arn:aws:sns:${region}:${account}:${snsTopicName}`;\n const snsTopic: ITopic = Topic.fromTopicArn(scope, `SnsTopicFor${id}`, topicArn);\n this.addAlarmAction(new SnsAction(snsTopic));\n if (okAction) {\n this.addOkAction(new SnsAction(snsTopic));\n }\n }\n}\n"]}
@@ -1,18 +1,10 @@
1
+ import { Function } from "aws-cdk-lib/aws-lambda";
1
2
  import type { FunctionProps } from "aws-cdk-lib/aws-lambda";
2
- import { Alias, Function } from "aws-cdk-lib/aws-lambda";
3
3
  import { GuDistributable } from "../../types";
4
4
  import type { GuLambdaErrorPercentageMonitoringProps, GuLambdaThrottlingMonitoringProps } from "../cloudwatch";
5
5
  import type { GuStack } from "../core";
6
6
  import { AppIdentity } from "../core";
7
7
  export interface GuFunctionProps extends GuDistributable, Omit<FunctionProps, "code">, AppIdentity {
8
- /**
9
- * Create a new Lambda version and alias. This is only necessary if you want to use features which rely
10
- * on versioning (e.g. SnapStart or Provisioned Concurrency).
11
- *
12
- * If you enable versioning you must ensure that your Lambda function whenever a new build is deployed via
13
- * CloudFormation. The simplest way to do this is to include the build number in the `fileName` prop.
14
- */
15
- enableVersioning?: boolean;
16
8
  /**
17
9
  * Alarm if error percentage exceeds a threshold.
18
10
  */
@@ -25,32 +17,51 @@ export interface GuFunctionProps extends GuDistributable, Omit<FunctionProps, "c
25
17
  * @see https://docs.aws.amazon.com/lambda/latest/dg/concurrent-executions.html
26
18
  */
27
19
  throttlingMonitoring?: GuLambdaThrottlingMonitoringProps;
20
+ /**
21
+ * SSM parameter for the S3 bucket that contains your lambda file.
22
+ *
23
+ * Typically you should not override this but you may need to if, for example,
24
+ * you are referencing a file that is shared across many apps and/or AWS
25
+ * accounts.
26
+ *
27
+ * @defaultValue [[`GuDistributionBucketParameter`]]
28
+ */
29
+ bucketNamePath?: string;
28
30
  }
29
31
  /**
30
32
  * Construct which creates a Lambda function.
31
33
  *
32
- * This Lambda relies on the code artifact residing in a standard location in S3. For more details on the bucket used,
33
- * see [[`GuDistributionBucketParameter`]]. By default, the path used will be `<stack>/<stage>/<app</<fileName>`.
34
+ * This Lambda relies on the code artifact residing in a standard location in
35
+ * S3. For more details on the bucket used, see
36
+ * [[`GuDistributionBucketParameter`]]. By default, the path used will be
37
+ * `<stack>/<stage>/<app</<fileName>`. If required, e.g. if you are sharing
38
+ * lambda code across apps or accounts, override the source bucket using the
39
+ * `bucketNamePath` prop.
34
40
  *
35
- * The default memory size of this Lambda will vary depending on the runtime chosen.
36
- * For Java runtimes (i.e. resource hungry Scala Lambdas!), 1024MB will be used. For all other runtimes,
37
- * the memory size defaults to 512MB. This can be overridden via the `memorySize` prop.
41
+ * The default memory size of this Lambda will vary depending on the runtime
42
+ * chosen. For Java runtimes (i.e. resource hungry Scala Lambdas!), 1024MB will
43
+ * be used. For all other runtimes, the memory size defaults to 512MB. This can
44
+ * be overridden via the `memorySize` prop.
38
45
  *
39
- * By default, the timeout for this Lambda is 30 seconds. This can be overridden via the `timeout` prop.
46
+ * By default, the timeout for this Lambda is 30 seconds. This can be overridden
47
+ * via the `timeout` prop.
40
48
  *
41
- * By default the Lambda is granted permission to read from the SSM parameter store subtree specific to this Lambda
42
- * (i.e. it can read all keys under `/<stage>/<stack>/<app>/`). If you need to add additional permissions, you can use
43
- * [`addToRolePolicy`](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.FunctionBase.html#addwbrtowbrrolewbrpolicystatement).
49
+ * By default the Lambda is granted permission to read from the SSM parameter
50
+ * store subtree specific to this Lambda (i.e. it can read all keys under
51
+ * `/<stage>/<stack>/<app>/`). If you need to add additional permissions, you
52
+ * can use
53
+ * [`addToRolePolicy`](`https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.FunctionBase.html#addwbrtowbrrolewbrpolicystatement`).
44
54
  *
45
- * The Lambda has `STACK`, `STAGE` and `APP` environment variables which can be used to determine its identity.
55
+ * The Lambda has `STACK`, `STAGE` and `APP` environment variables which can be
56
+ * used to determine its identity.
46
57
  *
47
- * Note that this construct creates a Lambda without an event source. Depending on your use-case, you may wish to
48
- * consider using a pattern which instantiates a Lambda with an event source e.g. [[`GuScheduledLambda`]].
58
+ * Note that this construct creates a Lambda without an event source. Depending
59
+ * on your use-case, you may wish to consider using a pattern which instantiates
60
+ * a Lambda with an event source e.g. [[`GuScheduledLambda`]].
49
61
  */
50
62
  export declare class GuLambdaFunction extends Function {
51
63
  readonly app: string;
52
64
  readonly fileName: string;
53
- readonly alias?: Alias;
54
65
  constructor(scope: GuStack, id: string, props: GuFunctionProps);
55
66
  }
56
67
  //# sourceMappingURL=lambda.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lambda.d.ts","sourceRoot":"","sources":["../../../src/constructs/lambda/lambda.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,aAAa,EAAU,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAC,KAAK,EAAQ,QAAQ,EAAgB,MAAM,wBAAwB,CAAC;AAE5E,OAAO,EAAC,eAAe,EAAC,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAC,sCAAsC,EAAE,iCAAiC,EAAC,MAAM,eAAe,CAAC;AAE7G,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,SAAS,CAAC;AACrC,OAAO,EAAC,WAAW,EAAgC,MAAM,SAAS,CAAC;AAGnE,MAAM,WAAW,eAAgB,SAAQ,eAAe,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,WAAW;IAChG;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;OAEG;IACH,yBAAyB,CAAC,EAAE,sCAAsC,CAAC;IAEnE;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE,iCAAiC,CAAC;CAC1D;AAeD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,gBAAiB,SAAQ,QAAQ;IAC5C,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,KAAK,CAAC,EAAE,KAAK,CAAC;gBAElB,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe;CA6D/D"}
1
+ {"version":3,"file":"lambda.d.ts","sourceRoot":"","sources":["../../../src/constructs/lambda/lambda.ts"],"names":[],"mappings":"AAGA,OAAO,EAAQ,QAAQ,EAAiB,MAAM,wBAAwB,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAW,MAAM,wBAAwB,CAAC;AAGrE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,KAAK,EAAE,sCAAsC,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC;AAC/G,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,WAAW,EAAiC,MAAM,SAAS,CAAC;AAGrE,MAAM,WAAW,eAAgB,SAAQ,eAAe,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,WAAW;IAChG;;OAEG;IACH,yBAAyB,CAAC,EAAE,sCAAsC,CAAC;IACnE;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE,iCAAiC,CAAC;IACzD;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAeD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,gBAAiB,SAAQ,QAAQ;IAC5C,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,SAAgB,QAAQ,EAAE,MAAM,CAAC;gBAErB,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe;CAuD/D"}
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GuLambdaFunction = void 0;
4
+ /* eslint "@guardian/tsdoc-required/tsdoc-required": 2 -- to begin rolling this out for public APIs. */
4
5
  const aws_cdk_lib_1 = require("aws-cdk-lib");
5
6
  const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
6
7
  const aws_s3_1 = require("aws-cdk-lib/aws-s3");
8
+ const aws_ssm_1 = require("aws-cdk-lib/aws-ssm");
7
9
  const types_1 = require("../../types");
8
10
  const cloudwatch_1 = require("../cloudwatch");
9
11
  const core_1 = require("../core");
@@ -24,33 +26,46 @@ function defaultMemorySize(runtime, memorySize) {
24
26
  /**
25
27
  * Construct which creates a Lambda function.
26
28
  *
27
- * This Lambda relies on the code artifact residing in a standard location in S3. For more details on the bucket used,
28
- * see [[`GuDistributionBucketParameter`]]. By default, the path used will be `<stack>/<stage>/<app</<fileName>`.
29
+ * This Lambda relies on the code artifact residing in a standard location in
30
+ * S3. For more details on the bucket used, see
31
+ * [[`GuDistributionBucketParameter`]]. By default, the path used will be
32
+ * `<stack>/<stage>/<app</<fileName>`. If required, e.g. if you are sharing
33
+ * lambda code across apps or accounts, override the source bucket using the
34
+ * `bucketNamePath` prop.
29
35
  *
30
- * The default memory size of this Lambda will vary depending on the runtime chosen.
31
- * For Java runtimes (i.e. resource hungry Scala Lambdas!), 1024MB will be used. For all other runtimes,
32
- * the memory size defaults to 512MB. This can be overridden via the `memorySize` prop.
36
+ * The default memory size of this Lambda will vary depending on the runtime
37
+ * chosen. For Java runtimes (i.e. resource hungry Scala Lambdas!), 1024MB will
38
+ * be used. For all other runtimes, the memory size defaults to 512MB. This can
39
+ * be overridden via the `memorySize` prop.
33
40
  *
34
- * By default, the timeout for this Lambda is 30 seconds. This can be overridden via the `timeout` prop.
41
+ * By default, the timeout for this Lambda is 30 seconds. This can be overridden
42
+ * via the `timeout` prop.
35
43
  *
36
- * By default the Lambda is granted permission to read from the SSM parameter store subtree specific to this Lambda
37
- * (i.e. it can read all keys under `/<stage>/<stack>/<app>/`). If you need to add additional permissions, you can use
38
- * [`addToRolePolicy`](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.FunctionBase.html#addwbrtowbrrolewbrpolicystatement).
44
+ * By default the Lambda is granted permission to read from the SSM parameter
45
+ * store subtree specific to this Lambda (i.e. it can read all keys under
46
+ * `/<stage>/<stack>/<app>/`). If you need to add additional permissions, you
47
+ * can use
48
+ * [`addToRolePolicy`](`https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.FunctionBase.html#addwbrtowbrrolewbrpolicystatement`).
39
49
  *
40
- * The Lambda has `STACK`, `STAGE` and `APP` environment variables which can be used to determine its identity.
50
+ * The Lambda has `STACK`, `STAGE` and `APP` environment variables which can be
51
+ * used to determine its identity.
41
52
  *
42
- * Note that this construct creates a Lambda without an event source. Depending on your use-case, you may wish to
43
- * consider using a pattern which instantiates a Lambda with an event source e.g. [[`GuScheduledLambda`]].
53
+ * Note that this construct creates a Lambda without an event source. Depending
54
+ * on your use-case, you may wish to consider using a pattern which instantiates
55
+ * a Lambda with an event source e.g. [[`GuScheduledLambda`]].
44
56
  */
45
57
  class GuLambdaFunction extends aws_lambda_1.Function {
46
58
  constructor(scope, id, props) {
47
- const { app, fileName, runtime, memorySize, timeout } = props;
59
+ const { app, fileName, runtime, memorySize, timeout, bucketNamePath } = props;
60
+ const bucketName = bucketNamePath
61
+ ? aws_ssm_1.StringParameter.fromStringParameterName(scope, "bucketoverride", bucketNamePath).stringValue
62
+ : core_1.GuDistributionBucketParameter.getInstance(scope).valueAsString;
48
63
  const defaultEnvironmentVariables = {
49
64
  STACK: scope.stack,
50
65
  STAGE: scope.stage,
51
66
  APP: app,
52
67
  };
53
- const bucket = aws_s3_1.Bucket.fromBucketName(scope, `${id}-bucket`, core_1.GuDistributionBucketParameter.getInstance(scope).valueAsString);
68
+ const bucket = aws_s3_1.Bucket.fromBucketName(scope, `${id}-bucket`, bucketName);
54
69
  const objectKey = types_1.GuDistributable.getObjectKey(scope, { app }, { fileName });
55
70
  const code = aws_lambda_1.Code.fromBucket(bucket, objectKey);
56
71
  super(scope, id, {
@@ -65,11 +80,6 @@ class GuLambdaFunction extends aws_lambda_1.Function {
65
80
  });
66
81
  this.app = app;
67
82
  this.fileName = fileName;
68
- if (props.enableVersioning) {
69
- this.alias = new aws_lambda_1.Alias(scope, `${id}-AliasForLambda`, {
70
- aliasName: scope.stage, version: this.currentVersion
71
- });
72
- }
73
83
  if (props.errorPercentageMonitoring) {
74
84
  new cloudwatch_1.GuLambdaErrorPercentageAlarm(scope, `${id}-ErrorPercentageAlarmForLambda`, {
75
85
  ...props.errorPercentageMonitoring,
@@ -1 +1 @@
1
- {"version":3,"file":"lambda.js","sourceRoot":"","sources":["../../../src/constructs/lambda/lambda.ts"],"names":[],"mappings":"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","sourcesContent":["import {Duration} from \"aws-cdk-lib\";\nimport type {PolicyStatement} from \"aws-cdk-lib/aws-iam\";\nimport type {FunctionProps, Runtime} from \"aws-cdk-lib/aws-lambda\";\nimport {Alias, Code, Function, RuntimeFamily} from \"aws-cdk-lib/aws-lambda\";\nimport {Bucket} from \"aws-cdk-lib/aws-s3\";\nimport {GuDistributable} from \"../../types\";\nimport type {GuLambdaErrorPercentageMonitoringProps, GuLambdaThrottlingMonitoringProps} from \"../cloudwatch\";\nimport {GuLambdaErrorPercentageAlarm, GuLambdaThrottlingAlarm} from \"../cloudwatch\";\nimport type {GuStack} from \"../core\";\nimport {AppIdentity, GuDistributionBucketParameter} from \"../core\";\nimport {ReadParametersByName, ReadParametersByPath} from \"../iam\";\n\nexport interface GuFunctionProps extends GuDistributable, Omit<FunctionProps, \"code\">, AppIdentity {\n /**\n * Create a new Lambda version and alias. This is only necessary if you want to use features which rely\n * on versioning (e.g. SnapStart or Provisioned Concurrency).\n *\n * If you enable versioning you must ensure that your Lambda function whenever a new build is deployed via\n * CloudFormation. The simplest way to do this is to include the build number in the `fileName` prop.\n */\n enableVersioning?: boolean;\n\n /**\n * Alarm if error percentage exceeds a threshold.\n */\n errorPercentageMonitoring?: GuLambdaErrorPercentageMonitoringProps;\n\n /**\n * Alarm if throttling occurs. Note, it is also worth considering a\n * concurrency limit (the `reservedConcurrentExecutions` prop) if you are\n * concerned about throttling.\n *\n * @see https://docs.aws.amazon.com/lambda/latest/dg/concurrent-executions.html\n */\n throttlingMonitoring?: GuLambdaThrottlingMonitoringProps;\n}\n\nfunction defaultMemorySize(runtime: Runtime, memorySize?: number): number {\n if (memorySize) {\n return memorySize;\n } else {\n switch (runtime.family) {\n case RuntimeFamily.JAVA:\n return 1024;\n default:\n return 512;\n }\n }\n}\n\n/**\n * Construct which creates a Lambda function.\n *\n * This Lambda relies on the code artifact residing in a standard location in S3. For more details on the bucket used,\n * see [[`GuDistributionBucketParameter`]]. By default, the path used will be `<stack>/<stage>/<app</<fileName>`.\n *\n * The default memory size of this Lambda will vary depending on the runtime chosen.\n * For Java runtimes (i.e. resource hungry Scala Lambdas!), 1024MB will be used. For all other runtimes,\n * the memory size defaults to 512MB. This can be overridden via the `memorySize` prop.\n *\n * By default, the timeout for this Lambda is 30 seconds. This can be overridden via the `timeout` prop.\n *\n * By default the Lambda is granted permission to read from the SSM parameter store subtree specific to this Lambda\n * (i.e. it can read all keys under `/<stage>/<stack>/<app>/`). If you need to add additional permissions, you can use\n * [`addToRolePolicy`](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.FunctionBase.html#addwbrtowbrrolewbrpolicystatement).\n *\n * The Lambda has `STACK`, `STAGE` and `APP` environment variables which can be used to determine its identity.\n *\n * Note that this construct creates a Lambda without an event source. Depending on your use-case, you may wish to\n * consider using a pattern which instantiates a Lambda with an event source e.g. [[`GuScheduledLambda`]].\n */\nexport class GuLambdaFunction extends Function {\n public readonly app: string;\n public readonly fileName: string;\n public readonly alias?: Alias;\n\n constructor(scope: GuStack, id: string, props: GuFunctionProps) {\n const { app, fileName, runtime, memorySize, timeout } = props;\n\n const defaultEnvironmentVariables = {\n STACK: scope.stack,\n STAGE: scope.stage,\n APP: app,\n };\n\n const bucket = Bucket.fromBucketName(\n scope,\n `${id}-bucket`,\n GuDistributionBucketParameter.getInstance(scope).valueAsString\n );\n const objectKey = GuDistributable.getObjectKey(scope, { app }, { fileName });\n const code = Code.fromBucket(bucket, objectKey);\n super(scope, id, {\n ...props,\n environment: {\n ...props.environment,\n ...defaultEnvironmentVariables,\n },\n memorySize: defaultMemorySize(runtime, memorySize),\n timeout: timeout ?? Duration.seconds(30),\n code,\n });\n\n this.app = app;\n this.fileName = fileName;\n\n if (props.enableVersioning) {\n this.alias = new Alias(scope, `${id}-AliasForLambda`, {\n aliasName: scope.stage, version: this.currentVersion\n });\n }\n\n if (props.errorPercentageMonitoring) {\n new GuLambdaErrorPercentageAlarm(scope, `${id}-ErrorPercentageAlarmForLambda`, {\n ...props.errorPercentageMonitoring,\n lambda: this,\n });\n }\n\n if (props.throttlingMonitoring) {\n new GuLambdaThrottlingAlarm(scope, `${id}-ThrottlingAlarmForLambda`, {\n ...props.throttlingMonitoring,\n lambda: this,\n });\n }\n\n bucket.grantRead(this, objectKey);\n\n const ssmParamReadPolicies: PolicyStatement[] = [\n new ReadParametersByPath(scope, props),\n new ReadParametersByName(scope, props),\n ];\n\n ssmParamReadPolicies.map((policy) => this.addToRolePolicy(policy));\n\n AppIdentity.taggedConstruct(props, this);\n }\n}\n"]}
1
+ {"version":3,"file":"lambda.js","sourceRoot":"","sources":["../../../src/constructs/lambda/lambda.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint \"@guardian/tsdoc-required/tsdoc-required\": 2 -- to begin rolling this out for public APIs. */\nimport { Duration } from \"aws-cdk-lib\";\nimport type { PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport { Code, Function, RuntimeFamily } from \"aws-cdk-lib/aws-lambda\";\nimport type { FunctionProps, Runtime } from \"aws-cdk-lib/aws-lambda\";\nimport { Bucket } from \"aws-cdk-lib/aws-s3\";\nimport { StringParameter } from \"aws-cdk-lib/aws-ssm\";\nimport { GuDistributable } from \"../../types\";\nimport { GuLambdaErrorPercentageAlarm, GuLambdaThrottlingAlarm } from \"../cloudwatch\";\nimport type { GuLambdaErrorPercentageMonitoringProps, GuLambdaThrottlingMonitoringProps } from \"../cloudwatch\";\nimport type { GuStack } from \"../core\";\nimport { AppIdentity, GuDistributionBucketParameter } from \"../core\";\nimport { ReadParametersByName, ReadParametersByPath } from \"../iam\";\n\nexport interface GuFunctionProps extends GuDistributable, Omit<FunctionProps, \"code\">, AppIdentity {\n /**\n * Alarm if error percentage exceeds a threshold.\n */\n errorPercentageMonitoring?: GuLambdaErrorPercentageMonitoringProps;\n /**\n * Alarm if throttling occurs. Note, it is also worth considering a\n * concurrency limit (the `reservedConcurrentExecutions` prop) if you are\n * concerned about throttling.\n *\n * @see https://docs.aws.amazon.com/lambda/latest/dg/concurrent-executions.html\n */\n throttlingMonitoring?: GuLambdaThrottlingMonitoringProps;\n /**\n * SSM parameter for the S3 bucket that contains your lambda file.\n *\n * Typically you should not override this but you may need to if, for example,\n * you are referencing a file that is shared across many apps and/or AWS\n * accounts.\n *\n * @defaultValue [[`GuDistributionBucketParameter`]]\n */\n bucketNamePath?: string;\n}\n\nfunction defaultMemorySize(runtime: Runtime, memorySize?: number): number {\n if (memorySize) {\n return memorySize;\n } else {\n switch (runtime.family) {\n case RuntimeFamily.JAVA:\n return 1024;\n default:\n return 512;\n }\n }\n}\n\n/**\n * Construct which creates a Lambda function.\n *\n * This Lambda relies on the code artifact residing in a standard location in\n * S3. For more details on the bucket used, see\n * [[`GuDistributionBucketParameter`]]. By default, the path used will be\n * `<stack>/<stage>/<app</<fileName>`. If required, e.g. if you are sharing\n * lambda code across apps or accounts, override the source bucket using the\n * `bucketNamePath` prop.\n *\n * The default memory size of this Lambda will vary depending on the runtime\n * chosen. For Java runtimes (i.e. resource hungry Scala Lambdas!), 1024MB will\n * be used. For all other runtimes, the memory size defaults to 512MB. This can\n * be overridden via the `memorySize` prop.\n *\n * By default, the timeout for this Lambda is 30 seconds. This can be overridden\n * via the `timeout` prop.\n *\n * By default the Lambda is granted permission to read from the SSM parameter\n * store subtree specific to this Lambda (i.e. it can read all keys under\n * `/<stage>/<stack>/<app>/`). If you need to add additional permissions, you\n * can use\n * [`addToRolePolicy`](`https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.FunctionBase.html#addwbrtowbrrolewbrpolicystatement`).\n *\n * The Lambda has `STACK`, `STAGE` and `APP` environment variables which can be\n * used to determine its identity.\n *\n * Note that this construct creates a Lambda without an event source. Depending\n * on your use-case, you may wish to consider using a pattern which instantiates\n * a Lambda with an event source e.g. [[`GuScheduledLambda`]].\n */\nexport class GuLambdaFunction extends Function {\n public readonly app: string;\n public readonly fileName: string;\n\n constructor(scope: GuStack, id: string, props: GuFunctionProps) {\n const { app, fileName, runtime, memorySize, timeout, bucketNamePath } = props;\n\n const bucketName = bucketNamePath\n ? StringParameter.fromStringParameterName(scope, \"bucketoverride\", bucketNamePath).stringValue\n : GuDistributionBucketParameter.getInstance(scope).valueAsString;\n\n const defaultEnvironmentVariables = {\n STACK: scope.stack,\n STAGE: scope.stage,\n APP: app,\n };\n\n const bucket = Bucket.fromBucketName(scope, `${id}-bucket`, bucketName);\n const objectKey = GuDistributable.getObjectKey(scope, { app }, { fileName });\n const code = Code.fromBucket(bucket, objectKey);\n super(scope, id, {\n ...props,\n environment: {\n ...props.environment,\n ...defaultEnvironmentVariables,\n },\n memorySize: defaultMemorySize(runtime, memorySize),\n timeout: timeout ?? Duration.seconds(30),\n code,\n });\n\n this.app = app;\n this.fileName = fileName;\n\n if (props.errorPercentageMonitoring) {\n new GuLambdaErrorPercentageAlarm(scope, `${id}-ErrorPercentageAlarmForLambda`, {\n ...props.errorPercentageMonitoring,\n lambda: this,\n });\n }\n\n if (props.throttlingMonitoring) {\n new GuLambdaThrottlingAlarm(scope, `${id}-ThrottlingAlarmForLambda`, {\n ...props.throttlingMonitoring,\n lambda: this,\n });\n }\n\n bucket.grantRead(this, objectKey);\n\n const ssmParamReadPolicies: PolicyStatement[] = [\n new ReadParametersByPath(scope, props),\n new ReadParametersByName(scope, props),\n ];\n\n ssmParamReadPolicies.map((policy) => this.addToRolePolicy(policy));\n\n AppIdentity.taggedConstruct(props, this);\n }\n}\n"]}
@@ -28,7 +28,7 @@ export declare class GuApplicationListener extends GuApplicationListener_base {
28
28
  }
29
29
  export interface GuHttpsApplicationListenerProps extends Omit<GuApplicationListenerProps, "defaultAction" | "certificates">, AppIdentity {
30
30
  targetGroup: GuApplicationTargetGroup;
31
- certificate: GuCertificate;
31
+ certificate?: GuCertificate;
32
32
  }
33
33
  declare const GuHttpsApplicationListener_base: {
34
34
  new (...args: any[]): {
@@ -1 +1 @@
1
- {"version":3,"file":"application-listener.d.ts","sourceRoot":"","sources":["../../../../src/constructs/loadbalancing/alb/application-listener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAuC,MAAM,wCAAwC,CAAC;AAClH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AAEvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAE3E,MAAM,WAAW,0BAA2B,SAAQ,wBAAwB,EAAE,WAAW;CAAG;;;;;;AAE5F;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAsB,SAAQ,0BAAwC;gBACrE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,0BAA0B;CAG1E;AAED,MAAM,WAAW,+BACf,SAAQ,IAAI,CAAC,0BAA0B,EAAE,eAAe,GAAG,cAAc,CAAC,EACxE,WAAW;IACb,WAAW,EAAE,wBAAwB,CAAC;IACtC,WAAW,EAAE,aAAa,CAAC;CAC5B;;;;;;AAED;;;;;;GAMG;AACH,qBAAa,0BAA2B,SAAQ,+BAAwC;gBAC1E,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,+BAA+B;CAiB/E"}
1
+ {"version":3,"file":"application-listener.d.ts","sourceRoot":"","sources":["../../../../src/constructs/loadbalancing/alb/application-listener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAuC,MAAM,wCAAwC,CAAC;AAClH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AAEvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAE3E,MAAM,WAAW,0BAA2B,SAAQ,wBAAwB,EAAE,WAAW;CAAG;;;;;;AAE5F;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAsB,SAAQ,0BAAwC;gBACrE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,0BAA0B;CAG1E;AAED,MAAM,WAAW,+BACf,SAAQ,IAAI,CAAC,0BAA0B,EAAE,eAAe,GAAG,cAAc,CAAC,EACxE,WAAW;IACb,WAAW,EAAE,wBAAwB,CAAC;IACtC,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B;;;;;;AAED;;;;;;GAMG;AACH,qBAAa,0BAA2B,SAAQ,+BAAwC;gBAC1E,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,+BAA+B;CAmB/E"}
@@ -33,14 +33,16 @@ class GuHttpsApplicationListener extends (0, app_aware_construct_1.GuAppAwareCon
33
33
  constructor(scope, id, props) {
34
34
  const { certificate, targetGroup } = props;
35
35
  const mergedProps = {
36
- port: 443,
37
- protocol: aws_elasticloadbalancingv2_1.ApplicationProtocol.HTTPS,
36
+ port: certificate ? 443 : 8080,
37
+ protocol: certificate ? aws_elasticloadbalancingv2_1.ApplicationProtocol.HTTPS : aws_elasticloadbalancingv2_1.ApplicationProtocol.HTTP,
38
38
  ...props,
39
- certificates: [
40
- {
41
- certificateArn: certificate.certificateArn,
42
- },
43
- ],
39
+ certificates: certificate
40
+ ? [
41
+ {
42
+ certificateArn: certificate.certificateArn,
43
+ },
44
+ ]
45
+ : [],
44
46
  defaultAction: aws_elasticloadbalancingv2_1.ListenerAction.forward([targetGroup]),
45
47
  };
46
48
  super(scope, id, mergedProps);