@guardian/cdk 50.9.0 → 50.10.1

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.
@@ -1,10 +1,18 @@
1
- import { Function } from "aws-cdk-lib/aws-lambda";
2
1
  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 is updated 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;
8
16
  /**
9
17
  * Alarm if error percentage exceeds a threshold.
10
18
  */
@@ -81,6 +89,7 @@ export declare class GuLambdaFunction extends Function {
81
89
  readonly bucketNamePath: string | undefined;
82
90
  readonly withoutArtifactUpload: boolean;
83
91
  readonly withoutFilePrefix: boolean;
92
+ readonly alias?: Alias;
84
93
  constructor(scope: GuStack, id: string, props: GuFunctionProps);
85
94
  }
86
95
  //# sourceMappingURL=lambda.d.ts.map
@@ -1 +1 @@
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;IACxB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAeD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,gBAAiB,SAAQ,QAAQ;IAC5C,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnD,SAAgB,qBAAqB,EAAE,OAAO,CAAC;IAC/C,SAAgB,iBAAiB,EAAE,OAAO,CAAC;gBAE/B,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe;CAmE/D"}
1
+ {"version":3,"file":"lambda.d.ts","sourceRoot":"","sources":["../../../src/constructs/lambda/lambda.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAW,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,KAAK,EAAQ,QAAQ,EAAiB,MAAM,wBAAwB,CAAC;AAG9E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,sCAAsC,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC;AAE/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;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;OAEG;IACH,yBAAyB,CAAC,EAAE,sCAAsC,CAAC;IACnE;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE,iCAAiC,CAAC;IACzD;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAeD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,gBAAiB,SAAQ,QAAQ;IAC5C,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnD,SAAgB,qBAAqB,EAAE,OAAO,CAAC;IAC/C,SAAgB,iBAAiB,EAAE,OAAO,CAAC;IAC3C,SAAgB,KAAK,CAAC,EAAE,KAAK,CAAC;gBAElB,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe;CA0E/D"}
@@ -83,6 +83,12 @@ class GuLambdaFunction extends aws_lambda_1.Function {
83
83
  this.bucketNamePath = bucketNamePath;
84
84
  this.withoutArtifactUpload = withoutArtifactUpload;
85
85
  this.withoutFilePrefix = withoutFilePrefix;
86
+ if (props.enableVersioning) {
87
+ this.alias = new aws_lambda_1.Alias(scope, `${id}-AliasForLambda`, {
88
+ aliasName: scope.stage,
89
+ version: this.currentVersion,
90
+ });
91
+ }
86
92
  if (props.errorPercentageMonitoring) {
87
93
  new cloudwatch_1.GuLambdaErrorPercentageAlarm(scope, `${id}-ErrorPercentageAlarmForLambda`, {
88
94
  ...props.errorPercentageMonitoring,
@@ -1 +1 @@
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 * Set to `true` to use the filename *without* the stage/stack/app prefix.\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 withoutFilePrefix?: boolean;\n /**\n * Set to `true` this informs consumers of this function that upload is\n * managed elsewhere by DevX.\n *\n * This is used by RiffRaffYamlFileExperimental to skip generating\n * an uploadLambda step.\n */\n withoutArtifactUpload?: boolean;\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 public readonly bucketNamePath: string | undefined;\n public readonly withoutArtifactUpload: boolean;\n public readonly withoutFilePrefix: boolean;\n\n constructor(scope: GuStack, id: string, props: GuFunctionProps) {\n const {\n app,\n fileName,\n runtime,\n memorySize,\n timeout,\n bucketNamePath,\n withoutFilePrefix = false,\n withoutArtifactUpload = false,\n } = 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 = withoutFilePrefix ? fileName : 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 this.bucketNamePath = bucketNamePath;\n this.withoutArtifactUpload = withoutArtifactUpload;\n this.withoutFilePrefix = withoutFilePrefix;\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 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 { StringParameter } from \"aws-cdk-lib/aws-ssm\";\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 is updated 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 * 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 * Set to `true` to use the filename *without* the stage/stack/app prefix.\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 withoutFilePrefix?: boolean;\n /**\n * Set to `true` this informs consumers of this function that upload is\n * managed elsewhere by DevX.\n *\n * This is used by RiffRaffYamlFileExperimental to skip generating\n * an uploadLambda step.\n */\n withoutArtifactUpload?: boolean;\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 public readonly bucketNamePath: string | undefined;\n public readonly withoutArtifactUpload: boolean;\n public readonly withoutFilePrefix: boolean;\n public readonly alias?: Alias;\n\n constructor(scope: GuStack, id: string, props: GuFunctionProps) {\n const {\n app,\n fileName,\n runtime,\n memorySize,\n timeout,\n bucketNamePath,\n withoutFilePrefix = false,\n withoutArtifactUpload = false,\n } = 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 = withoutFilePrefix ? fileName : 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 this.bucketNamePath = bucketNamePath;\n this.withoutArtifactUpload = withoutArtifactUpload;\n this.withoutFilePrefix = withoutFilePrefix;\n\n if (props.enableVersioning) {\n this.alias = new Alias(scope, `${id}-AliasForLambda`, {\n aliasName: scope.stage,\n 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 +1 @@
1
- {"version":3,"file":"kinesis-lambda.d.ts","sourceRoot":"","sources":["../../../src/experimental/patterns/kinesis-lambda.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAIpE,OAAO,KAAK,EAAE,sCAAsC,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAExG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,KAAK,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE1F;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,yBAAyB,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,eAAe,EAAE,2BAA2B,CAAC;IAC9F,uBAAuB,EAAE,YAAY,GAAG,sCAAsC,CAAC;IAC/E,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,0BAA0B,EAAE,wBAAwB,CAAC;IACrD,kBAAkB,CAAC,EAAE,WAAW,CAAC;IACjC,eAAe,CAAC,EAAE,qBAAqB,CAAC;CACzC;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,2BAA4B,SAAQ,gBAAgB;IAC/D,SAAgB,aAAa,EAAE,OAAO,CAAC;gBAE3B,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,oBAAoB;CA6BpE"}
1
+ {"version":3,"file":"kinesis-lambda.d.ts","sourceRoot":"","sources":["../../../src/experimental/patterns/kinesis-lambda.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAIpE,OAAO,KAAK,EAAE,sCAAsC,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAExG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,KAAK,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE1F;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,yBAAyB,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,eAAe,EAAE,2BAA2B,CAAC;IAC9F,uBAAuB,EAAE,YAAY,GAAG,sCAAsC,CAAC;IAC/E,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,0BAA0B,EAAE,wBAAwB,CAAC;IACrD,kBAAkB,CAAC,EAAE,WAAW,CAAC;IACjC,eAAe,CAAC,EAAE,qBAAqB,CAAC;CACzC;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,2BAA4B,SAAQ,gBAAgB;IAC/D,SAAgB,aAAa,EAAE,OAAO,CAAC;gBAE3B,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,oBAAoB;CAiCpE"}
@@ -38,7 +38,10 @@ class GuKinesisLambdaExperimental extends lambda_1.GuLambdaFunction {
38
38
  ...props.processingProps,
39
39
  ...errorHandlingPropsToAwsProps,
40
40
  };
41
- this.addEventSource(new aws_lambda_event_sources_1.KinesisEventSource(this.kinesisStream, eventSourceProps));
41
+ // If we have an alias, use this to ensure that all events are sent to a published Lambda version.
42
+ // Otherwise, send all events to the latest unpublished version ($LATEST)
43
+ const eventSourceTarget = this.alias ?? this;
44
+ eventSourceTarget.addEventSource(new aws_lambda_event_sources_1.KinesisEventSource(this.kinesisStream, eventSourceProps));
42
45
  }
43
46
  }
44
47
  exports.GuKinesisLambdaExperimental = GuKinesisLambdaExperimental;
@@ -1 +1 @@
1
- {"version":3,"file":"kinesis-lambda.js","sourceRoot":"","sources":["../../../src/experimental/patterns/kinesis-lambda.ts"],"names":[],"mappings":";;;AAAA,yDAAmE;AAEnE,uDAA0D;AAC1D,mFAA0E;AAG1E,gDAAoD;AAEpD,sDAA2D;AAC3D,oDAA2D;AAE3D,+CAA6D;AAwD7D;;;;;;;;;;;;GAYG;AACH,MAAa,2BAA4B,SAAQ,yBAAgB;IAG/D,YAAY,KAAc,EAAE,EAAU,EAAE,KAA2B;QACjE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,GAAG,KAAK;YACR,yBAAyB,EAAE,KAAK,CAAC,uBAAuB,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,uBAAuB;SAClH,CAAC,CAAC;QAEH,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;QAClC,MAAM,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,GAAG,KAAK,CAAC;QAE5D,IAAI,CAAC,aAAa,GAAG,qBAAqB;YACxC,CAAC,CAAC,oBAAM,CAAC,aAAa,CAClB,KAAK,EACL,qBAAqB,CAAC,yBAAyB,EAC/C,mBAAmB,MAAM,IAAI,OAAO,WAAW,qBAAqB,CAAC,yBAAyB,EAAE,CACjG;YACH,CAAC,CAAC,kBAAW,CAAC,eAAe,CACzB,KAAK,EACL,IAAI,yBAAe,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,UAAU,EAAE,8BAAgB,CAAC,OAAO,EAAE,GAAG,kBAAkB,EAAE,CAAC,CAC7G,CAAC;QAEN,MAAM,4BAA4B,GAAG,IAAA,gCAAuB,EAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAE/F,MAAM,gBAAgB,GAA4B;YAChD,gBAAgB,EAAE,6BAAgB,CAAC,MAAM;YACzC,GAAG,KAAK,CAAC,eAAe;YACxB,GAAG,4BAA4B;SAChC,CAAC;QACF,IAAI,CAAC,cAAc,CAAC,IAAI,6CAAkB,CAAC,IAAI,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACpF,CAAC;CACF;AAhCD,kEAgCC","sourcesContent":["import { Stream, StreamEncryption } from \"aws-cdk-lib/aws-kinesis\";\nimport type { IStream, StreamProps } from \"aws-cdk-lib/aws-kinesis\";\nimport { StartingPosition } from \"aws-cdk-lib/aws-lambda\";\nimport { KinesisEventSource } from \"aws-cdk-lib/aws-lambda-event-sources\";\nimport type { KinesisEventSourceProps } from \"aws-cdk-lib/aws-lambda-event-sources\";\nimport type { GuLambdaErrorPercentageMonitoringProps, NoMonitoring } from \"../../constructs/cloudwatch\";\nimport { AppIdentity } from \"../../constructs/core\";\nimport type { GuStack } from \"../../constructs/core\";\nimport { GuKinesisStream } from \"../../constructs/kinesis\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport type { GuFunctionProps } from \"../../constructs/lambda\";\nimport { toAwsErrorHandlingProps } from \"../../utils/lambda\";\nimport type { StreamErrorHandlingProps, StreamProcessingProps } from \"../../utils/lambda\";\n\n/**\n * Used to provide information about an existing Kinesis stream to the [[`GuKinesisLambda`]] pattern.\n *\n * Specify an `externalKinesisStreamName` to link the lambda to a Kinesis stream owned by a different stack\n * (or created outside of version control).\n */\nexport interface ExistingKinesisStream {\n externalKinesisStreamName: string;\n}\n\n/**\n * Configuration options for the [[`GuKinesisLambda`]] pattern.\n *\n * For all lambda function configuration options, see [[`GuFunctionProps`]].\n *\n * The `existingKinesisStream` property can be used to reference a Kinesis stream which\n * has been created outside of this pattern (i.e. via CloudFormation, or via a different `cdk` pattern, or stack).\n * For more details see [[`ExistingKinesisStream`]].\n *\n * If you have specific stream configuration requirements (e.g. data retention period), these can be set via\n * `kinesisStreamProps`.\n *\n * If you need to override the default stream processing options (e.g. batch size and parallelization), pass\n * [[`StreamProcessingProps`]] via `processingProps`.\n *\n * You must provide `errorHandlingConfiguration` to this pattern. Retry conditions can be configured\n * via [[`StreamErrorHandlingProps`]].\n *\n * It is advisable to configure an alarm based on the lambda's error percentage.\n * To do this, add the `monitoringConfiguration` property. The required properties for this are:\n *\n * ```typescript\n * monitoringConfiguration: {\n * toleratedErrorPercentage: <sensible_error_percentage_threshold>,\n * snsTopicName: \"my-topic-for-cloudwatch-alerts\",\n * }\n * ```\n * Other alarm properties (e.g. alarm name and description) will be pre-populated with sensible defaults.\n * For a full list of optional properties, see [[`GuLambdaErrorPercentageMonitoringProps`]].\n *\n * If your team do not use CloudWatch, it's possible to opt-out with the following configuration:\n * ```typescript\n * monitoringConfiguration: { noMonitoring: true } as NoMonitoring\n * ```\n */\nexport interface GuKinesisLambdaProps extends Omit<GuFunctionProps, \"errorPercentageMonitoring\"> {\n monitoringConfiguration: NoMonitoring | GuLambdaErrorPercentageMonitoringProps;\n existingKinesisStream?: ExistingKinesisStream;\n errorHandlingConfiguration: StreamErrorHandlingProps;\n kinesisStreamProps?: StreamProps;\n processingProps?: StreamProcessingProps;\n}\n\n/**\n * Pattern which creates all of the resources needed to invoke a lambda function whenever a record is\n * put onto a Kinesis stream.\n *\n * This pattern will create a new Kinesis stream by default. If you are migrating a stack from CloudFormation,\n * you will need to opt-out of this behaviour. For information on overriding the default behaviour,\n * see [[`GuKinesisLambdaProps`]].\n *\n * The Kinesis stream is stateful, and is accessible via `kinesisStream`.\n * @see https://github.com/guardian/cdk/blob/main/docs/stateful-resources.md\n *\n * @experimental This pattern is in early development. The API is likely to change in future releases.\n */\nexport class GuKinesisLambdaExperimental extends GuLambdaFunction {\n public readonly kinesisStream: IStream;\n\n constructor(scope: GuStack, id: string, props: GuKinesisLambdaProps) {\n super(scope, id, {\n ...props,\n errorPercentageMonitoring: props.monitoringConfiguration.noMonitoring ? undefined : props.monitoringConfiguration,\n });\n\n const { account, region } = scope;\n const { existingKinesisStream, kinesisStreamProps } = props;\n\n this.kinesisStream = existingKinesisStream\n ? Stream.fromStreamArn(\n scope,\n existingKinesisStream.externalKinesisStreamName,\n `arn:aws:kinesis:${region}:${account}:stream/${existingKinesisStream.externalKinesisStreamName}`\n )\n : AppIdentity.taggedConstruct(\n props,\n new GuKinesisStream(scope, \"KinesisStream\", { encryption: StreamEncryption.MANAGED, ...kinesisStreamProps })\n );\n\n const errorHandlingPropsToAwsProps = toAwsErrorHandlingProps(props.errorHandlingConfiguration);\n\n const eventSourceProps: KinesisEventSourceProps = {\n startingPosition: StartingPosition.LATEST,\n ...props.processingProps,\n ...errorHandlingPropsToAwsProps,\n };\n this.addEventSource(new KinesisEventSource(this.kinesisStream, eventSourceProps));\n }\n}\n"]}
1
+ {"version":3,"file":"kinesis-lambda.js","sourceRoot":"","sources":["../../../src/experimental/patterns/kinesis-lambda.ts"],"names":[],"mappings":";;;AAAA,yDAAmE;AAEnE,uDAA0D;AAC1D,mFAA0E;AAG1E,gDAAoD;AAEpD,sDAA2D;AAC3D,oDAA2D;AAE3D,+CAA6D;AAwD7D;;;;;;;;;;;;GAYG;AACH,MAAa,2BAA4B,SAAQ,yBAAgB;IAG/D,YAAY,KAAc,EAAE,EAAU,EAAE,KAA2B;QACjE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,GAAG,KAAK;YACR,yBAAyB,EAAE,KAAK,CAAC,uBAAuB,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,uBAAuB;SAClH,CAAC,CAAC;QAEH,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;QAClC,MAAM,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,GAAG,KAAK,CAAC;QAE5D,IAAI,CAAC,aAAa,GAAG,qBAAqB;YACxC,CAAC,CAAC,oBAAM,CAAC,aAAa,CAClB,KAAK,EACL,qBAAqB,CAAC,yBAAyB,EAC/C,mBAAmB,MAAM,IAAI,OAAO,WAAW,qBAAqB,CAAC,yBAAyB,EAAE,CACjG;YACH,CAAC,CAAC,kBAAW,CAAC,eAAe,CACzB,KAAK,EACL,IAAI,yBAAe,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,UAAU,EAAE,8BAAgB,CAAC,OAAO,EAAE,GAAG,kBAAkB,EAAE,CAAC,CAC7G,CAAC;QAEN,MAAM,4BAA4B,GAAG,IAAA,gCAAuB,EAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAE/F,MAAM,gBAAgB,GAA4B;YAChD,gBAAgB,EAAE,6BAAgB,CAAC,MAAM;YACzC,GAAG,KAAK,CAAC,eAAe;YACxB,GAAG,4BAA4B;SAChC,CAAC;QAEF,kGAAkG;QAClG,yEAAyE;QACzE,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;QAC7C,iBAAiB,CAAC,cAAc,CAAC,IAAI,6CAAkB,CAAC,IAAI,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACjG,CAAC;CACF;AApCD,kEAoCC","sourcesContent":["import { Stream, StreamEncryption } from \"aws-cdk-lib/aws-kinesis\";\nimport type { IStream, StreamProps } from \"aws-cdk-lib/aws-kinesis\";\nimport { StartingPosition } from \"aws-cdk-lib/aws-lambda\";\nimport { KinesisEventSource } from \"aws-cdk-lib/aws-lambda-event-sources\";\nimport type { KinesisEventSourceProps } from \"aws-cdk-lib/aws-lambda-event-sources\";\nimport type { GuLambdaErrorPercentageMonitoringProps, NoMonitoring } from \"../../constructs/cloudwatch\";\nimport { AppIdentity } from \"../../constructs/core\";\nimport type { GuStack } from \"../../constructs/core\";\nimport { GuKinesisStream } from \"../../constructs/kinesis\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport type { GuFunctionProps } from \"../../constructs/lambda\";\nimport { toAwsErrorHandlingProps } from \"../../utils/lambda\";\nimport type { StreamErrorHandlingProps, StreamProcessingProps } from \"../../utils/lambda\";\n\n/**\n * Used to provide information about an existing Kinesis stream to the [[`GuKinesisLambda`]] pattern.\n *\n * Specify an `externalKinesisStreamName` to link the lambda to a Kinesis stream owned by a different stack\n * (or created outside of version control).\n */\nexport interface ExistingKinesisStream {\n externalKinesisStreamName: string;\n}\n\n/**\n * Configuration options for the [[`GuKinesisLambda`]] pattern.\n *\n * For all lambda function configuration options, see [[`GuFunctionProps`]].\n *\n * The `existingKinesisStream` property can be used to reference a Kinesis stream which\n * has been created outside of this pattern (i.e. via CloudFormation, or via a different `cdk` pattern, or stack).\n * For more details see [[`ExistingKinesisStream`]].\n *\n * If you have specific stream configuration requirements (e.g. data retention period), these can be set via\n * `kinesisStreamProps`.\n *\n * If you need to override the default stream processing options (e.g. batch size and parallelization), pass\n * [[`StreamProcessingProps`]] via `processingProps`.\n *\n * You must provide `errorHandlingConfiguration` to this pattern. Retry conditions can be configured\n * via [[`StreamErrorHandlingProps`]].\n *\n * It is advisable to configure an alarm based on the lambda's error percentage.\n * To do this, add the `monitoringConfiguration` property. The required properties for this are:\n *\n * ```typescript\n * monitoringConfiguration: {\n * toleratedErrorPercentage: <sensible_error_percentage_threshold>,\n * snsTopicName: \"my-topic-for-cloudwatch-alerts\",\n * }\n * ```\n * Other alarm properties (e.g. alarm name and description) will be pre-populated with sensible defaults.\n * For a full list of optional properties, see [[`GuLambdaErrorPercentageMonitoringProps`]].\n *\n * If your team do not use CloudWatch, it's possible to opt-out with the following configuration:\n * ```typescript\n * monitoringConfiguration: { noMonitoring: true } as NoMonitoring\n * ```\n */\nexport interface GuKinesisLambdaProps extends Omit<GuFunctionProps, \"errorPercentageMonitoring\"> {\n monitoringConfiguration: NoMonitoring | GuLambdaErrorPercentageMonitoringProps;\n existingKinesisStream?: ExistingKinesisStream;\n errorHandlingConfiguration: StreamErrorHandlingProps;\n kinesisStreamProps?: StreamProps;\n processingProps?: StreamProcessingProps;\n}\n\n/**\n * Pattern which creates all of the resources needed to invoke a lambda function whenever a record is\n * put onto a Kinesis stream.\n *\n * This pattern will create a new Kinesis stream by default. If you are migrating a stack from CloudFormation,\n * you will need to opt-out of this behaviour. For information on overriding the default behaviour,\n * see [[`GuKinesisLambdaProps`]].\n *\n * The Kinesis stream is stateful, and is accessible via `kinesisStream`.\n * @see https://github.com/guardian/cdk/blob/main/docs/stateful-resources.md\n *\n * @experimental This pattern is in early development. The API is likely to change in future releases.\n */\nexport class GuKinesisLambdaExperimental extends GuLambdaFunction {\n public readonly kinesisStream: IStream;\n\n constructor(scope: GuStack, id: string, props: GuKinesisLambdaProps) {\n super(scope, id, {\n ...props,\n errorPercentageMonitoring: props.monitoringConfiguration.noMonitoring ? undefined : props.monitoringConfiguration,\n });\n\n const { account, region } = scope;\n const { existingKinesisStream, kinesisStreamProps } = props;\n\n this.kinesisStream = existingKinesisStream\n ? Stream.fromStreamArn(\n scope,\n existingKinesisStream.externalKinesisStreamName,\n `arn:aws:kinesis:${region}:${account}:stream/${existingKinesisStream.externalKinesisStreamName}`\n )\n : AppIdentity.taggedConstruct(\n props,\n new GuKinesisStream(scope, \"KinesisStream\", { encryption: StreamEncryption.MANAGED, ...kinesisStreamProps })\n );\n\n const errorHandlingPropsToAwsProps = toAwsErrorHandlingProps(props.errorHandlingConfiguration);\n\n const eventSourceProps: KinesisEventSourceProps = {\n startingPosition: StartingPosition.LATEST,\n ...props.processingProps,\n ...errorHandlingPropsToAwsProps,\n };\n\n // If we have an alias, use this to ensure that all events are sent to a published Lambda version.\n // Otherwise, send all events to the latest unpublished version ($LATEST)\n const eventSourceTarget = this.alias ?? this;\n eventSourceTarget.addEventSource(new KinesisEventSource(this.kinesisStream, eventSourceProps));\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"sns-lambda.d.ts","sourceRoot":"","sources":["../../../src/experimental/patterns/sns-lambda.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,KAAK,EAAE,sCAAsC,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAExG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,eAAe,EAAE,2BAA2B,CAAC;IAC1F,uBAAuB,EAAE,YAAY,GAAG,sCAAsC,CAAC;IAC/E,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,uBAAwB,SAAQ,gBAAgB;IAC3D,SAAgB,QAAQ,EAAE,MAAM,CAAC;gBAErB,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB;CAoBhE"}
1
+ {"version":3,"file":"sns-lambda.d.ts","sourceRoot":"","sources":["../../../src/experimental/patterns/sns-lambda.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,KAAK,EAAE,sCAAsC,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAExG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,eAAe,EAAE,2BAA2B,CAAC;IAC1F,uBAAuB,EAAE,YAAY,GAAG,sCAAsC,CAAC;IAC/E,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,uBAAwB,SAAQ,gBAAgB;IAC3D,SAAgB,QAAQ,EAAE,MAAM,CAAC;gBAErB,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB;CAuBhE"}
@@ -30,7 +30,10 @@ class GuSnsLambdaExperimental extends lambda_1.GuLambdaFunction {
30
30
  this.snsTopic = existingSnsTopic
31
31
  ? aws_sns_1.Topic.fromTopicArn(scope, `${id}-SnsExistingIncomingEventsTopic`, `arn:aws:sns:${region}:${account}:${existingSnsTopic.externalTopicName}`)
32
32
  : core_1.AppIdentity.taggedConstruct(props, new aws_sns_1.Topic(scope, "SnsIncomingEventsTopic"));
33
- this.addEventSource(new aws_lambda_event_sources_1.SnsEventSource(this.snsTopic));
33
+ // If we have an alias, use this to ensure that all events are sent to a published Lambda version.
34
+ // Otherwise, send all events to the latest unpublished version ($LATEST)
35
+ const eventSourceTarget = this.alias ?? this;
36
+ eventSourceTarget.addEventSource(new aws_lambda_event_sources_1.SnsEventSource(this.snsTopic));
34
37
  new aws_cdk_lib_1.CfnOutput(this, "TopicName", { value: this.snsTopic.topicName });
35
38
  }
36
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sns-lambda.js","sourceRoot":"","sources":["../../../src/experimental/patterns/sns-lambda.ts"],"names":[],"mappings":";;;AAAA,6CAAwC;AACxC,mFAAsE;AAEtE,iDAA4C;AAE5C,gDAAoD;AAEpD,oDAA2D;AA4C3D;;;;;;;;;;;;GAYG;AACH,MAAa,uBAAwB,SAAQ,yBAAgB;IAG3D,YAAY,KAAc,EAAE,EAAU,EAAE,KAAuB;QAC7D,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,GAAG,KAAK;YACR,yBAAyB,EAAE,KAAK,CAAC,uBAAuB,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,uBAAuB;SAClH,CAAC,CAAC;QAEH,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;QAClC,MAAM,EAAE,gBAAgB,EAAE,GAAG,KAAK,CAAC;QAEnC,IAAI,CAAC,QAAQ,GAAG,gBAAgB;YAC9B,CAAC,CAAC,eAAK,CAAC,YAAY,CAChB,KAAK,EACL,GAAG,EAAE,iCAAiC,EACtC,eAAe,MAAM,IAAI,OAAO,IAAI,gBAAgB,CAAC,iBAAiB,EAAE,CACzE;YACH,CAAC,CAAC,kBAAW,CAAC,eAAe,CAAC,KAAK,EAAE,IAAI,eAAK,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAEnF,IAAI,CAAC,cAAc,CAAC,IAAI,yCAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QACvD,IAAI,uBAAS,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IACvE,CAAC;CACF;AAvBD,0DAuBC","sourcesContent":["import { CfnOutput } from \"aws-cdk-lib\";\nimport { SnsEventSource } from \"aws-cdk-lib/aws-lambda-event-sources\";\nimport type { ITopic } from \"aws-cdk-lib/aws-sns\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport type { GuLambdaErrorPercentageMonitoringProps, NoMonitoring } from \"../../constructs/cloudwatch\";\nimport { AppIdentity } from \"../../constructs/core\";\nimport type { GuStack } from \"../../constructs/core\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport type { GuFunctionProps } from \"../../constructs/lambda\";\n\n/**\n * Used to provide information about an existing SNS topic to the [[`GuSnsLambda`]] pattern.\n *\n * Specify an `externalTopicName` to link the lambda to an SNS topic owned by a different stack\n * (or created outside of version control).\n */\nexport interface ExistingSnsTopic {\n externalTopicName: string;\n}\n\n/**\n * Configuration options for the [[`GuSnsLambda`]] pattern.\n *\n * For all lambda function configuration options, see [[`GuFunctionProps`]].\n *\n * The `existingSnsTopic` property can be used to inherit or reference an SNS topic which\n * has been created outside of `cdk`. If this property is omitted, the [[`GuSnsLambda`]] pattern\n * will create a new topic. For more details and example usage, see [[`ExistingSnsTopic`]].\n *\n * It is advisable to configure an alarm based on the lambda's error percentage.\n * To do this, add the `monitoringConfiguration` property. The required properties for this are:\n *\n * ```typescript\n * monitoringConfiguration: {\n * toleratedErrorPercentage: <sensible_error_percentage_threshold>,\n * snsTopicName: \"my-topic-for-cloudwatch-alerts\",\n * }\n * ```\n * Other alarm properties (e.g. alarm name and description) will be pre-populated with sensible defaults.\n * For a full list of optional properties, see [[`GuLambdaErrorPercentageMonitoringProps`]].\n *\n * If your team do not use CloudWatch, it's possible to opt-out with the following configuration:\n * ```typescript\n * monitoringConfiguration: { noMonitoring: true } as NoMonitoring\n * ```\n */\nexport interface GuSnsLambdaProps extends Omit<GuFunctionProps, \"errorPercentageMonitoring\"> {\n monitoringConfiguration: NoMonitoring | GuLambdaErrorPercentageMonitoringProps;\n existingSnsTopic?: ExistingSnsTopic;\n}\n\n/**\n * Pattern which creates all of the resources needed to invoke a lambda function whenever a message\n * is published onto an SNS topic.\n *\n * This pattern will create a new SNS topic by default. If you are migrating a stack from CloudFormation,\n * you will need to opt-out of this behaviour. For information on overriding the default behaviour,\n * see [[`GuSnsLambdaProps`]].\n *\n * The SNS topic is stateful, and is accessible via `snsTopic`.\n * @see https://github.com/guardian/cdk/blob/main/docs/stateful-resources.md\n *\n * @experimental This pattern is in early development. The API is likely to change in future releases.\n */\nexport class GuSnsLambdaExperimental extends GuLambdaFunction {\n public readonly snsTopic: ITopic;\n\n constructor(scope: GuStack, id: string, props: GuSnsLambdaProps) {\n super(scope, id, {\n ...props,\n errorPercentageMonitoring: props.monitoringConfiguration.noMonitoring ? undefined : props.monitoringConfiguration,\n });\n\n const { account, region } = scope;\n const { existingSnsTopic } = props;\n\n this.snsTopic = existingSnsTopic\n ? Topic.fromTopicArn(\n scope,\n `${id}-SnsExistingIncomingEventsTopic`,\n `arn:aws:sns:${region}:${account}:${existingSnsTopic.externalTopicName}`\n )\n : AppIdentity.taggedConstruct(props, new Topic(scope, \"SnsIncomingEventsTopic\"));\n\n this.addEventSource(new SnsEventSource(this.snsTopic));\n new CfnOutput(this, \"TopicName\", { value: this.snsTopic.topicName });\n }\n}\n"]}
1
+ {"version":3,"file":"sns-lambda.js","sourceRoot":"","sources":["../../../src/experimental/patterns/sns-lambda.ts"],"names":[],"mappings":";;;AAAA,6CAAwC;AACxC,mFAAsE;AAEtE,iDAA4C;AAE5C,gDAAoD;AAEpD,oDAA2D;AA4C3D;;;;;;;;;;;;GAYG;AACH,MAAa,uBAAwB,SAAQ,yBAAgB;IAG3D,YAAY,KAAc,EAAE,EAAU,EAAE,KAAuB;QAC7D,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,GAAG,KAAK;YACR,yBAAyB,EAAE,KAAK,CAAC,uBAAuB,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,uBAAuB;SAClH,CAAC,CAAC;QAEH,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;QAClC,MAAM,EAAE,gBAAgB,EAAE,GAAG,KAAK,CAAC;QAEnC,IAAI,CAAC,QAAQ,GAAG,gBAAgB;YAC9B,CAAC,CAAC,eAAK,CAAC,YAAY,CAChB,KAAK,EACL,GAAG,EAAE,iCAAiC,EACtC,eAAe,MAAM,IAAI,OAAO,IAAI,gBAAgB,CAAC,iBAAiB,EAAE,CACzE;YACH,CAAC,CAAC,kBAAW,CAAC,eAAe,CAAC,KAAK,EAAE,IAAI,eAAK,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAEnF,kGAAkG;QAClG,yEAAyE;QACzE,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;QAC7C,iBAAiB,CAAC,cAAc,CAAC,IAAI,yCAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QACpE,IAAI,uBAAS,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IACvE,CAAC;CACF;AA1BD,0DA0BC","sourcesContent":["import { CfnOutput } from \"aws-cdk-lib\";\nimport { SnsEventSource } from \"aws-cdk-lib/aws-lambda-event-sources\";\nimport type { ITopic } from \"aws-cdk-lib/aws-sns\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport type { GuLambdaErrorPercentageMonitoringProps, NoMonitoring } from \"../../constructs/cloudwatch\";\nimport { AppIdentity } from \"../../constructs/core\";\nimport type { GuStack } from \"../../constructs/core\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport type { GuFunctionProps } from \"../../constructs/lambda\";\n\n/**\n * Used to provide information about an existing SNS topic to the [[`GuSnsLambda`]] pattern.\n *\n * Specify an `externalTopicName` to link the lambda to an SNS topic owned by a different stack\n * (or created outside of version control).\n */\nexport interface ExistingSnsTopic {\n externalTopicName: string;\n}\n\n/**\n * Configuration options for the [[`GuSnsLambda`]] pattern.\n *\n * For all lambda function configuration options, see [[`GuFunctionProps`]].\n *\n * The `existingSnsTopic` property can be used to inherit or reference an SNS topic which\n * has been created outside of `cdk`. If this property is omitted, the [[`GuSnsLambda`]] pattern\n * will create a new topic. For more details and example usage, see [[`ExistingSnsTopic`]].\n *\n * It is advisable to configure an alarm based on the lambda's error percentage.\n * To do this, add the `monitoringConfiguration` property. The required properties for this are:\n *\n * ```typescript\n * monitoringConfiguration: {\n * toleratedErrorPercentage: <sensible_error_percentage_threshold>,\n * snsTopicName: \"my-topic-for-cloudwatch-alerts\",\n * }\n * ```\n * Other alarm properties (e.g. alarm name and description) will be pre-populated with sensible defaults.\n * For a full list of optional properties, see [[`GuLambdaErrorPercentageMonitoringProps`]].\n *\n * If your team do not use CloudWatch, it's possible to opt-out with the following configuration:\n * ```typescript\n * monitoringConfiguration: { noMonitoring: true } as NoMonitoring\n * ```\n */\nexport interface GuSnsLambdaProps extends Omit<GuFunctionProps, \"errorPercentageMonitoring\"> {\n monitoringConfiguration: NoMonitoring | GuLambdaErrorPercentageMonitoringProps;\n existingSnsTopic?: ExistingSnsTopic;\n}\n\n/**\n * Pattern which creates all of the resources needed to invoke a lambda function whenever a message\n * is published onto an SNS topic.\n *\n * This pattern will create a new SNS topic by default. If you are migrating a stack from CloudFormation,\n * you will need to opt-out of this behaviour. For information on overriding the default behaviour,\n * see [[`GuSnsLambdaProps`]].\n *\n * The SNS topic is stateful, and is accessible via `snsTopic`.\n * @see https://github.com/guardian/cdk/blob/main/docs/stateful-resources.md\n *\n * @experimental This pattern is in early development. The API is likely to change in future releases.\n */\nexport class GuSnsLambdaExperimental extends GuLambdaFunction {\n public readonly snsTopic: ITopic;\n\n constructor(scope: GuStack, id: string, props: GuSnsLambdaProps) {\n super(scope, id, {\n ...props,\n errorPercentageMonitoring: props.monitoringConfiguration.noMonitoring ? undefined : props.monitoringConfiguration,\n });\n\n const { account, region } = scope;\n const { existingSnsTopic } = props;\n\n this.snsTopic = existingSnsTopic\n ? Topic.fromTopicArn(\n scope,\n `${id}-SnsExistingIncomingEventsTopic`,\n `arn:aws:sns:${region}:${account}:${existingSnsTopic.externalTopicName}`\n )\n : AppIdentity.taggedConstruct(props, new Topic(scope, \"SnsIncomingEventsTopic\"));\n\n // If we have an alias, use this to ensure that all events are sent to a published Lambda version.\n // Otherwise, send all events to the latest unpublished version ($LATEST)\n const eventSourceTarget = this.alias ?? this;\n eventSourceTarget.addEventSource(new SnsEventSource(this.snsTopic));\n new CfnOutput(this, \"TopicName\", { value: this.snsTopic.topicName });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAqBvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,4BAA4B;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAY;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;IAEtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,OAAO,CAAC,iBAAiB;IASzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqDG;IACH,OAAO,CAAC,mBAAmB;IAiC3B,OAAO,CAAC,6BAA6B;IAQrC,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,oBAAoB;gBAKhB,GAAG,EAAE,GAAG;IAiEpB;;;OAGG;IACH,MAAM,IAAI,MAAM;IAiBhB;;;OAGG;IACH,KAAK,IAAI,IAAI;CAId"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAqBvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,4BAA4B;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAY;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;IAEtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,OAAO,CAAC,iBAAiB;IASzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqDG;IACH,OAAO,CAAC,mBAAmB;IAiC3B,OAAO,CAAC,6BAA6B;IAQrC,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,oBAAoB;gBAKhB,GAAG,EAAE,GAAG;IAoEpB;;;OAGG;IACH,MAAM,IAAI,MAAM;IAiBhB;;;OAGG;IACH,KAAK,IAAI,IAAI;CAId"}
@@ -186,7 +186,10 @@ class RiffRaffYamlFileExperimental {
186
186
  artifactUploads.forEach(({ name, props }) => deployments.set(name, props));
187
187
  const cfnDeployment = (0, cloudformation_1.cloudFormationDeployment)(stacks, artifactUploads, this.outdir);
188
188
  deployments.set(cfnDeployment.name, cfnDeployment.props);
189
- lambdas.forEach((lambda) => {
189
+ const lambdasWithoutAnAlias = lambdas.filter((lambda) => lambda.alias === undefined);
190
+ // If the Lambda has an alias it is using versioning. When using versioning, there is no need for Riff-Raff
191
+ // to modify the unpublished version of the function
192
+ lambdasWithoutAnAlias.forEach((lambda) => {
190
193
  const lambdaDeployment = (0, lambda_2.updateLambdaDeployment)(lambda, cfnDeployment);
191
194
  deployments.set(lambdaDeployment.name, lambdaDeployment.props);
192
195
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../../constructs/autoscaling\";\nimport { GuStack } from \"../../constructs/core\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport { addAmiParametersToCloudFormationDeployment, cloudFormationDeployment } from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { groupByClassNameStackRegionStage } from \"./group-by\";\nimport type {\n GroupedCdkStacks,\n Region,\n RiffRaffDeployment,\n RiffRaffDeploymentName,\n RiffRaffDeploymentProps,\n RiffRaffYaml,\n StackTag,\n StageTag,\n} from \"./types\";\n\n/**\n * A class that creates a `riff-raff.yaml` file.\n *\n * Rather than using this directly, prefer to use [[`GuRoot`]] instead.\n *\n * Supports:\n * - Multiple CloudFormation stacks\n * - Multiple regions\n * - Lambda applications\n * - EC2 (autoscaling) applications\n *\n * For lambda applications, 3 deployments will be defined:\n * 1. Lambda upload (`aws-lambda`, `action: [uploadLambda]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Lambda update (`aws-lambda`, `action: [updateLambda]`)\n *\n * For EC2 applications, 3 deployments will be defined:\n * 1. Artifact upload (`autoscaling`, `action: [uploadArtifacts]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Autoscaling deploy (`autoscaling`, `action: [deploy]`)\n *\n * It assumes a Riff-Raff bundle structure as follows:\n *\n * ```\n * .\n * ├── cdk.out\n * │ └── MyApplication.template.json\n * ├── my-application\n * │ └── my-application.deb\n * └── my-lambda\n * └── my-lambda.zip\n * ```\n *\n * That is, all CloudFormation templates are in a `cdk.out` directory, and there is a directory per app.\n * Application artifact(s) are in the app directory.\n *\n * NOTE: The file extension is decided by you, the above file tree is used for illustration purposes.\n *\n * NOTE: Resources will be looked up by tags (Stack, Stage, App). Ensure your CFN stack is tagged appropriately!\n *\n * @see https://riffraff.gutools.co.uk/docs/reference/riff-raff.yaml.md\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\nexport class RiffRaffYamlFileExperimental {\n private readonly allCdkStacks: GuStack[];\n private readonly allStackTags: StackTag[];\n private readonly allStageTags: StageTag[];\n private readonly allRegions: Region[];\n\n private readonly riffRaffYaml: RiffRaffYaml;\n private readonly outdir: string;\n\n private isCdkStackPresent(expectedStack: StackTag, expectedStage: StageTag): boolean {\n const matches = this.allCdkStacks.find((cdkStack) => {\n const { stack, stage } = cdkStack;\n return stack === expectedStack && stage === expectedStage;\n });\n\n return !!matches;\n }\n\n /**\n * Check there are the appropriate number of `GuStack`s.\n * Expect to find an instance for each combination of `stack`, and `stage`.\n *\n * If not valid, a message is logged describing what is missing to aid debugging.\n *\n * Given the following:\n *\n * ```ts\n * const app = new App();\n *\n * class MyApplicationStack extends GuStack { }\n *\n * new MyApplicationStack(app, \"App-CODE-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"CODE\"\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-media-service\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"media-service\",\n * stage: \"PROD\",\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"PROD\"\n * });\n * ```\n *\n * This will log a message like this, where ❌ denotes something missing,\n * specifically there is no `CODE` template for `media-service`.\n *\n * ```log\n * Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)\n *\n * ┌───────────────┬──────┬──────┐\n * │ (index) │ CODE │ PROD │\n * ├───────────────┼──────┼──────┤\n * │ deploy │ '✅' │ '✅' │\n * │ media-service │ '❌' │ '✅' │\n * └───────────────┴──────┴──────┘\n * ```\n *\n * @private\n */\n private validateStacksInApp(): void {\n type Found = \"✅\";\n type NotFound = \"❌\";\n type AppValidation = Record<StackTag, Record<StageTag, Found | NotFound>>;\n\n const { allStackTags, allStageTags } = this;\n\n const checks: AppValidation = allStackTags.reduce((accStackTag, stackTag) => {\n return {\n ...accStackTag,\n [stackTag]: allStageTags.reduce((accStageTag, stageTag) => {\n return {\n ...accStageTag,\n [stageTag]: this.isCdkStackPresent(stackTag, stageTag) ? \"✅\" : \"❌\",\n };\n }, {}),\n };\n }, {});\n\n const missingDefinitions: Array<Found | NotFound> = Object.values(checks).flatMap((groupedByStackTag) => {\n return Object.values(groupedByStackTag).filter((_) => _ === \"❌\");\n });\n\n if (missingDefinitions.length > 0) {\n const message = `Unable to produce a working riff-raff.yaml file; missing ${missingDefinitions.length} definitions`;\n\n console.log(`${message} (details below)`);\n console.table(checks);\n\n throw new Error(message);\n }\n }\n\n private validateAllRegionsAreResolved(): void {\n const unresolved = this.allRegions.filter((region) => Token.isUnresolved(region));\n\n if (unresolved.length !== 0) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; all stacks must have an explicit region set`);\n }\n }\n\n private getLambdas(cdkStack: GuStack): GuLambdaFunction[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuLambdaFunction) as GuLambdaFunction[];\n }\n\n private getAutoScalingGroups(cdkStack: GuStack): GuAutoScalingGroup[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuAutoScalingGroup) as GuAutoScalingGroup[];\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree\n constructor(app: App) {\n this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));\n this.allStageTags = Array.from(allowedStages);\n this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));\n this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));\n\n this.validateStacksInApp();\n this.validateAllRegionsAreResolved();\n\n this.outdir = app.outdir;\n\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n const groupedStacks: GroupedCdkStacks = groupByClassNameStackRegionStage(this.allCdkStacks);\n\n Object.values(groupedStacks).forEach((stackTagGroup) => {\n Object.values(stackTagGroup).forEach((regionGroup) => {\n Object.values(regionGroup).forEach((stageGroup) => {\n const stacks: GuStack[] = Object.values(stageGroup).flat();\n\n if (stacks.length === 0) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `stacks` is checked above\n const stack = stacks[0]!;\n\n const lambdas = this.getLambdas(stack);\n const autoscalingGroups = this.getAutoScalingGroups(stack);\n\n const artifactUploads: RiffRaffDeployment[] = [\n lambdas.filter((_) => !_.withoutArtifactUpload).map(uploadLambdaArtifact),\n autoscalingGroups.map(uploadAutoscalingArtifact),\n ].flat();\n artifactUploads.forEach(({ name, props }) => deployments.set(name, props));\n\n const cfnDeployment = cloudFormationDeployment(stacks, artifactUploads, this.outdir);\n deployments.set(cfnDeployment.name, cfnDeployment.props);\n\n lambdas.forEach((lambda) => {\n const lambdaDeployment = updateLambdaDeployment(lambda, cfnDeployment);\n deployments.set(lambdaDeployment.name, lambdaDeployment.props);\n });\n\n autoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n });\n\n deployments.set(\n cfnDeployment.name,\n addAmiParametersToCloudFormationDeployment(cfnDeployment, autoscalingGroups)\n );\n });\n });\n });\n\n this.riffRaffYaml = {\n allowedStages,\n deployments,\n };\n }\n\n /**\n * The `riff-raff.yaml` file as a string.\n * Useful for testing.\n */\n toYAML(): string {\n // Add support for ES6 Set and Map. See https://github.com/nodeca/js-yaml/issues/436.\n const replacer = (_key: string, value: unknown) => {\n if (value instanceof Set) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Array.from(value);\n }\n if (value instanceof Map) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Object.fromEntries(value);\n }\n return value;\n };\n\n return dump(this.riffRaffYaml, { replacer });\n }\n\n /**\n * Write the `riff-raff.yaml` file to disk.\n * It'll be located with the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n const outPath = path.join(this.outdir, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML());\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../../constructs/autoscaling\";\nimport { GuStack } from \"../../constructs/core\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport { addAmiParametersToCloudFormationDeployment, cloudFormationDeployment } from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { groupByClassNameStackRegionStage } from \"./group-by\";\nimport type {\n GroupedCdkStacks,\n Region,\n RiffRaffDeployment,\n RiffRaffDeploymentName,\n RiffRaffDeploymentProps,\n RiffRaffYaml,\n StackTag,\n StageTag,\n} from \"./types\";\n\n/**\n * A class that creates a `riff-raff.yaml` file.\n *\n * Rather than using this directly, prefer to use [[`GuRoot`]] instead.\n *\n * Supports:\n * - Multiple CloudFormation stacks\n * - Multiple regions\n * - Lambda applications\n * - EC2 (autoscaling) applications\n *\n * For lambda applications, 3 deployments will be defined:\n * 1. Lambda upload (`aws-lambda`, `action: [uploadLambda]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Lambda update (`aws-lambda`, `action: [updateLambda]`)\n *\n * For EC2 applications, 3 deployments will be defined:\n * 1. Artifact upload (`autoscaling`, `action: [uploadArtifacts]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Autoscaling deploy (`autoscaling`, `action: [deploy]`)\n *\n * It assumes a Riff-Raff bundle structure as follows:\n *\n * ```\n * .\n * ├── cdk.out\n * │ └── MyApplication.template.json\n * ├── my-application\n * │ └── my-application.deb\n * └── my-lambda\n * └── my-lambda.zip\n * ```\n *\n * That is, all CloudFormation templates are in a `cdk.out` directory, and there is a directory per app.\n * Application artifact(s) are in the app directory.\n *\n * NOTE: The file extension is decided by you, the above file tree is used for illustration purposes.\n *\n * NOTE: Resources will be looked up by tags (Stack, Stage, App). Ensure your CFN stack is tagged appropriately!\n *\n * @see https://riffraff.gutools.co.uk/docs/reference/riff-raff.yaml.md\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\nexport class RiffRaffYamlFileExperimental {\n private readonly allCdkStacks: GuStack[];\n private readonly allStackTags: StackTag[];\n private readonly allStageTags: StageTag[];\n private readonly allRegions: Region[];\n\n private readonly riffRaffYaml: RiffRaffYaml;\n private readonly outdir: string;\n\n private isCdkStackPresent(expectedStack: StackTag, expectedStage: StageTag): boolean {\n const matches = this.allCdkStacks.find((cdkStack) => {\n const { stack, stage } = cdkStack;\n return stack === expectedStack && stage === expectedStage;\n });\n\n return !!matches;\n }\n\n /**\n * Check there are the appropriate number of `GuStack`s.\n * Expect to find an instance for each combination of `stack`, and `stage`.\n *\n * If not valid, a message is logged describing what is missing to aid debugging.\n *\n * Given the following:\n *\n * ```ts\n * const app = new App();\n *\n * class MyApplicationStack extends GuStack { }\n *\n * new MyApplicationStack(app, \"App-CODE-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"CODE\"\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-media-service\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"media-service\",\n * stage: \"PROD\",\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"PROD\"\n * });\n * ```\n *\n * This will log a message like this, where ❌ denotes something missing,\n * specifically there is no `CODE` template for `media-service`.\n *\n * ```log\n * Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)\n *\n * ┌───────────────┬──────┬──────┐\n * │ (index) │ CODE │ PROD │\n * ├───────────────┼──────┼──────┤\n * │ deploy │ '✅' │ '✅' │\n * │ media-service │ '❌' │ '✅' │\n * └───────────────┴──────┴──────┘\n * ```\n *\n * @private\n */\n private validateStacksInApp(): void {\n type Found = \"✅\";\n type NotFound = \"❌\";\n type AppValidation = Record<StackTag, Record<StageTag, Found | NotFound>>;\n\n const { allStackTags, allStageTags } = this;\n\n const checks: AppValidation = allStackTags.reduce((accStackTag, stackTag) => {\n return {\n ...accStackTag,\n [stackTag]: allStageTags.reduce((accStageTag, stageTag) => {\n return {\n ...accStageTag,\n [stageTag]: this.isCdkStackPresent(stackTag, stageTag) ? \"✅\" : \"❌\",\n };\n }, {}),\n };\n }, {});\n\n const missingDefinitions: Array<Found | NotFound> = Object.values(checks).flatMap((groupedByStackTag) => {\n return Object.values(groupedByStackTag).filter((_) => _ === \"❌\");\n });\n\n if (missingDefinitions.length > 0) {\n const message = `Unable to produce a working riff-raff.yaml file; missing ${missingDefinitions.length} definitions`;\n\n console.log(`${message} (details below)`);\n console.table(checks);\n\n throw new Error(message);\n }\n }\n\n private validateAllRegionsAreResolved(): void {\n const unresolved = this.allRegions.filter((region) => Token.isUnresolved(region));\n\n if (unresolved.length !== 0) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; all stacks must have an explicit region set`);\n }\n }\n\n private getLambdas(cdkStack: GuStack): GuLambdaFunction[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuLambdaFunction) as GuLambdaFunction[];\n }\n\n private getAutoScalingGroups(cdkStack: GuStack): GuAutoScalingGroup[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuAutoScalingGroup) as GuAutoScalingGroup[];\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree\n constructor(app: App) {\n this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));\n this.allStageTags = Array.from(allowedStages);\n this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));\n this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));\n\n this.validateStacksInApp();\n this.validateAllRegionsAreResolved();\n\n this.outdir = app.outdir;\n\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n const groupedStacks: GroupedCdkStacks = groupByClassNameStackRegionStage(this.allCdkStacks);\n\n Object.values(groupedStacks).forEach((stackTagGroup) => {\n Object.values(stackTagGroup).forEach((regionGroup) => {\n Object.values(regionGroup).forEach((stageGroup) => {\n const stacks: GuStack[] = Object.values(stageGroup).flat();\n\n if (stacks.length === 0) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `stacks` is checked above\n const stack = stacks[0]!;\n\n const lambdas = this.getLambdas(stack);\n const autoscalingGroups = this.getAutoScalingGroups(stack);\n\n const artifactUploads: RiffRaffDeployment[] = [\n lambdas.filter((_) => !_.withoutArtifactUpload).map(uploadLambdaArtifact),\n autoscalingGroups.map(uploadAutoscalingArtifact),\n ].flat();\n artifactUploads.forEach(({ name, props }) => deployments.set(name, props));\n\n const cfnDeployment = cloudFormationDeployment(stacks, artifactUploads, this.outdir);\n deployments.set(cfnDeployment.name, cfnDeployment.props);\n\n const lambdasWithoutAnAlias = lambdas.filter((lambda) => lambda.alias === undefined);\n // If the Lambda has an alias it is using versioning. When using versioning, there is no need for Riff-Raff\n // to modify the unpublished version of the function\n lambdasWithoutAnAlias.forEach((lambda) => {\n const lambdaDeployment = updateLambdaDeployment(lambda, cfnDeployment);\n deployments.set(lambdaDeployment.name, lambdaDeployment.props);\n });\n\n autoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n });\n\n deployments.set(\n cfnDeployment.name,\n addAmiParametersToCloudFormationDeployment(cfnDeployment, autoscalingGroups)\n );\n });\n });\n });\n\n this.riffRaffYaml = {\n allowedStages,\n deployments,\n };\n }\n\n /**\n * The `riff-raff.yaml` file as a string.\n * Useful for testing.\n */\n toYAML(): string {\n // Add support for ES6 Set and Map. See https://github.com/nodeca/js-yaml/issues/436.\n const replacer = (_key: string, value: unknown) => {\n if (value instanceof Set) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Array.from(value);\n }\n if (value instanceof Map) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Object.fromEntries(value);\n }\n return value;\n };\n\n return dump(this.riffRaffYaml, { replacer });\n }\n\n /**\n * Write the `riff-raff.yaml` file to disk.\n * It'll be located with the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n const outPath = path.join(this.outdir, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML());\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"api-lambda.d.ts","sourceRoot":"","sources":["../../src/patterns/api-lambda.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,UAAU,QAAS,SAAQ,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC;IAC5D,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,eAAe,EAAE,2BAA2B,CAAC;IAC1F;;OAEG;IACH,GAAG,EAAE,QAAQ,CAAC;IACd;;;;;;;OAOG;IACH,uBAAuB,EAAE,YAAY,GAAG,gBAAgB,CAAC;CAC1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,WAAY,SAAQ,gBAAgB;IAC/C,SAAgB,GAAG,EAAE,aAAa,CAAC;gBAEvB,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB;CAuBhE"}
1
+ {"version":3,"file":"api-lambda.d.ts","sourceRoot":"","sources":["../../src/patterns/api-lambda.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,UAAU,QAAS,SAAQ,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC;IAC5D,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,eAAe,EAAE,2BAA2B,CAAC;IAC1F;;OAEG;IACH,GAAG,EAAE,QAAQ,CAAC;IACd;;;;;;;OAOG;IACH,uBAAuB,EAAE,YAAY,GAAG,gBAAgB,CAAC;CAC1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,WAAY,SAAQ,gBAAgB;IAC/C,SAAgB,GAAG,EAAE,aAAa,CAAC;gBAEvB,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB;CA2BhE"}
@@ -39,8 +39,11 @@ class GuApiLambda extends lambda_1.GuLambdaFunction {
39
39
  super(scope, id, {
40
40
  ...props,
41
41
  });
42
+ // If we have an alias, use this to ensure that all requests are routed to a published Lambda version.
43
+ // Otherwise, use the latest unpublished version ($LATEST)
44
+ const resourceToInvoke = this.alias ?? this;
42
45
  this.api = new aws_apigateway_1.LambdaRestApi(this, props.api.id, {
43
- handler: this,
46
+ handler: resourceToInvoke,
44
47
  // Override to avoid clashes as default is just api ID, which is often shared across stages.
45
48
  restApiName: `${scope.stack}-${scope.stage}-${props.api.id}`,
46
49
  ...props.api,
@@ -1 +1 @@
1
- {"version":3,"file":"api-lambda.js","sourceRoot":"","sources":["../../src/patterns/api-lambda.ts"],"names":[],"mappings":";;;AAAA,+DAA2D;AAG3D,oFAA6F;AAE7F,iDAAwD;AAwBxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAa,WAAY,SAAQ,yBAAgB;IAG/C,YAAY,KAAc,EAAE,EAAU,EAAE,KAAuB;QAC7D,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,GAAG,KAAK;SACT,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,GAAG,IAAI,8BAAa,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE;YAC/C,OAAO,EAAE,IAAI;YAEb,4FAA4F;YAC5F,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE;YAE5D,GAAG,KAAK,CAAC,GAAG;SACb,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,YAAY,EAAE;YAC/C,IAAI,mDAA8B,CAAC,KAAK,EAAE;gBACxC,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,kBAAkB,EAAE,IAAI,CAAC,GAAG;gBAC5B,YAAY,EAAE,KAAK,CAAC,uBAAuB,CAAC,YAAY;gBACxD,GAAG,KAAK,CAAC,uBAAuB,CAAC,YAAY;aAC9C,CAAC,CAAC;SACJ;IACH,CAAC;CACF;AA1BD,kCA0BC","sourcesContent":["import { LambdaRestApi } from \"aws-cdk-lib/aws-apigateway\";\nimport type { LambdaRestApiProps } from \"aws-cdk-lib/aws-apigateway\";\nimport type { NoMonitoring } from \"../constructs/cloudwatch\";\nimport { GuApiGateway5xxPercentageAlarm } from \"../constructs/cloudwatch/api-gateway-alarms\";\nimport type { GuStack } from \"../constructs/core\";\nimport { GuLambdaFunction } from \"../constructs/lambda\";\nimport type { GuFunctionProps } from \"../constructs/lambda\";\nimport type { ApiGatewayAlarms } from \"./api-multiple-lambdas\";\n\ninterface ApiProps extends Omit<LambdaRestApiProps, \"handler\"> {\n id: string;\n}\n\nexport interface GuApiLambdaProps extends Omit<GuFunctionProps, \"errorPercentageMonitoring\"> {\n /**\n * [[`LambdaRestApiProps`]] to configure for the lambda.\n */\n api: ApiProps;\n /**\n * Alarm configuration for your API. For more details, see [[`ApiGatewayAlarms`]].\n *\n * If your team do not use CloudWatch, it's possible to opt-out with the following configuration:\n * ```typescript\n * monitoringConfiguration: { noMonitoring: true }\n * ```\n */\n monitoringConfiguration: NoMonitoring | ApiGatewayAlarms;\n}\n\n/**\n * A pattern to create a Lambda triggered by API Gateway\n * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-with-lambda-integration.html\n *\n * This pattern should be used if you intend to serve all traffic via a single Lambda\n * (for example, if your Lambda uses an application framework, like https://github.com/vendia/serverless-express).\n * If you need to configure path-based routing to serve different requests with different\n * Lambdas, use the [[`GuApiGatewayWithLambdaByPath`]] pattern instead.\n *\n * For all configuration options, see [[`GuApiLambdaProps`]].\n *\n * Example usage:\n *\n * ```typescript\n * new GuApiLambda(stack, \"my-lambda\", {\n * fileName: \"my-app.zip\",\n * handler: \"handler.ts\",\n * runtime: Runtime.NODEJS_14_X,\n * monitoringConfiguration: {\n * http5xxAlarm: { tolerated5xxPercentage: 5 },\n * snsTopicName: \"alerts-topic\",\n * },\n * app: \"my-app\",\n * api: {\n * id: \"my-api\",\n * description: \"...\",\n * },\n * });\n * ```\n */\nexport class GuApiLambda extends GuLambdaFunction {\n public readonly api: LambdaRestApi;\n\n constructor(scope: GuStack, id: string, props: GuApiLambdaProps) {\n super(scope, id, {\n ...props,\n });\n\n this.api = new LambdaRestApi(this, props.api.id, {\n handler: this,\n\n // Override to avoid clashes as default is just api ID, which is often shared across stages.\n restApiName: `${scope.stack}-${scope.stage}-${props.api.id}`,\n\n ...props.api,\n });\n\n if (!props.monitoringConfiguration.noMonitoring) {\n new GuApiGateway5xxPercentageAlarm(scope, {\n app: props.app,\n apiGatewayInstance: this.api,\n snsTopicName: props.monitoringConfiguration.snsTopicName,\n ...props.monitoringConfiguration.http5xxAlarm,\n });\n }\n }\n}\n"]}
1
+ {"version":3,"file":"api-lambda.js","sourceRoot":"","sources":["../../src/patterns/api-lambda.ts"],"names":[],"mappings":";;;AAAA,+DAA2D;AAG3D,oFAA6F;AAE7F,iDAAwD;AAwBxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAa,WAAY,SAAQ,yBAAgB;IAG/C,YAAY,KAAc,EAAE,EAAU,EAAE,KAAuB;QAC7D,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,GAAG,KAAK;SACT,CAAC,CAAC;QAEH,sGAAsG;QACtG,0DAA0D;QAC1D,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;QAE5C,IAAI,CAAC,GAAG,GAAG,IAAI,8BAAa,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE;YAC/C,OAAO,EAAE,gBAAgB;YAEzB,4FAA4F;YAC5F,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE;YAE5D,GAAG,KAAK,CAAC,GAAG;SACb,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,YAAY,EAAE;YAC/C,IAAI,mDAA8B,CAAC,KAAK,EAAE;gBACxC,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,kBAAkB,EAAE,IAAI,CAAC,GAAG;gBAC5B,YAAY,EAAE,KAAK,CAAC,uBAAuB,CAAC,YAAY;gBACxD,GAAG,KAAK,CAAC,uBAAuB,CAAC,YAAY;aAC9C,CAAC,CAAC;SACJ;IACH,CAAC;CACF;AA9BD,kCA8BC","sourcesContent":["import { LambdaRestApi } from \"aws-cdk-lib/aws-apigateway\";\nimport type { LambdaRestApiProps } from \"aws-cdk-lib/aws-apigateway\";\nimport type { NoMonitoring } from \"../constructs/cloudwatch\";\nimport { GuApiGateway5xxPercentageAlarm } from \"../constructs/cloudwatch/api-gateway-alarms\";\nimport type { GuStack } from \"../constructs/core\";\nimport { GuLambdaFunction } from \"../constructs/lambda\";\nimport type { GuFunctionProps } from \"../constructs/lambda\";\nimport type { ApiGatewayAlarms } from \"./api-multiple-lambdas\";\n\ninterface ApiProps extends Omit<LambdaRestApiProps, \"handler\"> {\n id: string;\n}\n\nexport interface GuApiLambdaProps extends Omit<GuFunctionProps, \"errorPercentageMonitoring\"> {\n /**\n * [[`LambdaRestApiProps`]] to configure for the lambda.\n */\n api: ApiProps;\n /**\n * Alarm configuration for your API. For more details, see [[`ApiGatewayAlarms`]].\n *\n * If your team do not use CloudWatch, it's possible to opt-out with the following configuration:\n * ```typescript\n * monitoringConfiguration: { noMonitoring: true }\n * ```\n */\n monitoringConfiguration: NoMonitoring | ApiGatewayAlarms;\n}\n\n/**\n * A pattern to create a Lambda triggered by API Gateway\n * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-with-lambda-integration.html\n *\n * This pattern should be used if you intend to serve all traffic via a single Lambda\n * (for example, if your Lambda uses an application framework, like https://github.com/vendia/serverless-express).\n * If you need to configure path-based routing to serve different requests with different\n * Lambdas, use the [[`GuApiGatewayWithLambdaByPath`]] pattern instead.\n *\n * For all configuration options, see [[`GuApiLambdaProps`]].\n *\n * Example usage:\n *\n * ```typescript\n * new GuApiLambda(stack, \"my-lambda\", {\n * fileName: \"my-app.zip\",\n * handler: \"handler.ts\",\n * runtime: Runtime.NODEJS_14_X,\n * monitoringConfiguration: {\n * http5xxAlarm: { tolerated5xxPercentage: 5 },\n * snsTopicName: \"alerts-topic\",\n * },\n * app: \"my-app\",\n * api: {\n * id: \"my-api\",\n * description: \"...\",\n * },\n * });\n * ```\n */\nexport class GuApiLambda extends GuLambdaFunction {\n public readonly api: LambdaRestApi;\n\n constructor(scope: GuStack, id: string, props: GuApiLambdaProps) {\n super(scope, id, {\n ...props,\n });\n\n // If we have an alias, use this to ensure that all requests are routed to a published Lambda version.\n // Otherwise, use the latest unpublished version ($LATEST)\n const resourceToInvoke = this.alias ?? this;\n\n this.api = new LambdaRestApi(this, props.api.id, {\n handler: resourceToInvoke,\n\n // Override to avoid clashes as default is just api ID, which is often shared across stages.\n restApiName: `${scope.stack}-${scope.stage}-${props.api.id}`,\n\n ...props.api,\n });\n\n if (!props.monitoringConfiguration.noMonitoring) {\n new GuApiGateway5xxPercentageAlarm(scope, {\n app: props.app,\n apiGatewayInstance: this.api,\n snsTopicName: props.monitoringConfiguration.snsTopicName,\n ...props.monitoringConfiguration.http5xxAlarm,\n });\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"api-multiple-lambdas.d.ts","sourceRoot":"","sources":["../../src/patterns/api-multiple-lambdas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAqB,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAEhF,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAEhH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,UAAU,EAAE,UAAU,CAAC;IACvB;;OAEG;IACH,MAAM,EAAE,gBAAgB,CAAC;IACzB;;OAEG;IACH,cAAc,CAAC,EAAE,IAAI,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,YAAY,EAAE,iBAAiB,CAAC;IAChC;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,iCAAkC,SAAQ,YAAY,EAAE,WAAW;IAClF;;OAEG;IACH,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB;;;;;;;OAOG;IACH,uBAAuB,EAAE,YAAY,GAAG,gBAAgB,CAAC;CAC1D;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,qBAAa,4BAA6B,SAAQ,SAAS;IACzD,SAAgB,GAAG,EAAE,OAAO,CAAC;gBAEjB,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,iCAAiC;CAwBrE"}
1
+ {"version":3,"file":"api-multiple-lambdas.d.ts","sourceRoot":"","sources":["../../src/patterns/api-multiple-lambdas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAqB,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAEhF,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAEhH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,UAAU,EAAE,UAAU,CAAC;IACvB;;OAEG;IACH,MAAM,EAAE,gBAAgB,CAAC;IACzB;;OAEG;IACH,cAAc,CAAC,EAAE,IAAI,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,YAAY,EAAE,iBAAiB,CAAC;IAChC;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,iCAAkC,SAAQ,YAAY,EAAE,WAAW;IAClF;;OAEG;IACH,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB;;;;;;;OAOG;IACH,uBAAuB,EAAE,YAAY,GAAG,gBAAgB,CAAC;CAC1D;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,qBAAa,4BAA6B,SAAQ,SAAS;IACzD,SAAgB,GAAG,EAAE,OAAO,CAAC;gBAEjB,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,iCAAiC;CA2BrE"}
@@ -72,7 +72,10 @@ class GuApiGatewayWithLambdaByPath extends constructs_1.Construct {
72
72
  this.api = apiGateway;
73
73
  props.targets.map((target) => {
74
74
  const resource = apiGateway.root.resourceForPath(target.path);
75
- resource.addMethod(target.httpMethod, new aws_apigateway_1.LambdaIntegration(target.lambda), {
75
+ // If we have an alias, use this to ensure that all requests are routed to a published Lambda version.
76
+ // Otherwise, use the latest unpublished version ($LATEST)
77
+ const lambdaTarget = target.lambda.alias ?? target.lambda;
78
+ resource.addMethod(target.httpMethod, new aws_apigateway_1.LambdaIntegration(lambdaTarget), {
76
79
  apiKeyRequired: target.apiKeyRequired,
77
80
  });
78
81
  });
@@ -1 +1 @@
1
- {"version":3,"file":"api-multiple-lambdas.js","sourceRoot":"","sources":["../../src/patterns/api-multiple-lambdas.ts"],"names":[],"mappings":";;;AACA,+DAAwE;AACxE,2CAAuC;AAEvC,oFAA6F;AAiE7F,SAAS,cAAc,CACrB,uBAAwD;IAExD,OAAsB,uBAAwB,CAAC,YAAY,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,MAAa,4BAA6B,SAAQ,sBAAS;IAGzD,YAAY,KAAc,EAAE,KAAwC;QAClE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,oCAAoC;QAC7D,MAAM,UAAU,GAAG,IAAI,wBAAO,CAAC,KAAK,EAAE,SAAS,EAAE;YAC/C,4FAA4F;YAC5F,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,EAAE;YACzD,GAAG,KAAK;SACT,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,GAAG,UAAU,CAAC;QACtB,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YAC3B,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9D,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,kCAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;gBAC1E,cAAc,EAAE,MAAM,CAAC,cAAc;aACtC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,uBAAuB,CAAC,EAAE;YAClD,IAAI,mDAA8B,CAAC,KAAK,EAAE;gBACxC,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,kBAAkB,EAAE,UAAU;gBAC9B,YAAY,EAAE,KAAK,CAAC,uBAAuB,CAAC,YAAY;gBACxD,GAAG,KAAK,CAAC,uBAAuB,CAAC,YAAY;aAC9C,CAAC,CAAC;SACJ;IACH,CAAC;CACF;AA3BD,oEA2BC","sourcesContent":["import type { RestApiProps } from \"aws-cdk-lib/aws-apigateway\";\nimport { LambdaIntegration, RestApi } from \"aws-cdk-lib/aws-apigateway\";\nimport { Construct } from \"constructs\";\nimport type { Http5xxAlarmProps, NoMonitoring } from \"../constructs/cloudwatch\";\nimport { GuApiGateway5xxPercentageAlarm } from \"../constructs/cloudwatch/api-gateway-alarms\";\nimport type { AppIdentity, GuStack } from \"../constructs/core\";\nimport type { GuLambdaFunction } from \"../constructs/lambda\";\n\n/**\n * See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods\n */\nexport type HttpMethod = \"GET\" | \"HEAD\" | \"POST\" | \"PUT\" | \"DELETE\" | \"CONNECT\" | \"OPTIONS\" | \"TRACE\" | \"PATCH\";\n\n/**\n * API target props.\n */\nexport interface ApiTarget {\n /**\n * The path for the request (e.g. /test).\n */\n path: string;\n /**\n * The [[`HttpMethod`]] for the target (e.g. GET, POST, PUT).\n */\n httpMethod: HttpMethod;\n /**\n * The Lambda function responsible for handling the request.\n */\n lambda: GuLambdaFunction;\n /**\n * Whether an apiKey is required for this method.\n */\n apiKeyRequired?: true;\n}\n\n/**\n * Alarm props.\n */\nexport interface ApiGatewayAlarms {\n /**\n * (SNS) Topic name where alarm notifications will be sent.\n */\n snsTopicName: string;\n /**\n * Configuration the 5xx alarm.\n */\n http5xxAlarm: Http5xxAlarmProps;\n /**\n * Internal flag - users of this library should ignore this setting.\n */\n noMonitoring?: false;\n}\n\nexport interface GuApiGatewayWithLambdaByPathProps extends RestApiProps, AppIdentity {\n /**\n * A list of [[`ApiTarget`]]s to configure for the API Gateway instance.\n */\n targets: ApiTarget[];\n /**\n * Alarm configuration for your API. For more details, see [[`ApiGatewayAlarms`]].\n *\n * If your team do not use CloudWatch, it's possible to opt-out with the following configuration:\n * ```typescript\n * monitoringConfiguration: { noMonitoring: true }\n * ```\n */\n monitoringConfiguration: NoMonitoring | ApiGatewayAlarms;\n}\n\nfunction isNoMonitoring(\n monitoringConfiguration: NoMonitoring | ApiGatewayAlarms\n): monitoringConfiguration is NoMonitoring {\n return (<NoMonitoring>monitoringConfiguration).noMonitoring;\n}\n\n/**\n * A pattern to create an API Gateway instance which uses path-based routing to route requests\n * to two or more Lambda functions.\n *\n * This pattern should be used if you need to configure path-based routing to serve different\n * requests with different Lambdas. If you intend to serve all traffic via a single Lambda, use\n * the [[`GuApiLambda`]] pattern instead.\n *\n * Example usage:\n *\n * ```typescript\n * // Configure lambdas\n * const lambdaOne = new GuLambdaFunction(this, \"lambda-one\", {\n * app: \"example-lambda-one\",\n * runtime: Runtime.NODEJS_14_X,\n * handler: \"lambda-one.handler\",\n * fileName: \"lambda-one.zip\",\n * });\n * const lambdaTwo = new GuLambdaFunction(this, \"lambda-two\", {\n * app: \"example-lambda-two\",\n * runtime: Runtime.NODEJS_14_X,\n * handler: \"lambda-two.handler\",\n * fileName: \"lambda-two.zip\",\n * });\n *\n * // Wire up the API\n * new GuApiGatewayWithLambdaByPath(this, {\n * app: \"example-api-gateway-instance\",\n * targets: [\n * {\n * path: \"lambda-one\",\n * httpMethod: \"GET\",\n * lambda: lambdaOne,\n * },\n * {\n * path: \"lambda-two\",\n * httpMethod: \"GET\",\n * lambda: lambdaTwo,\n * },\n * ],\n * // Create an alarm\n * monitoringConfiguration: {\n * snsTopicName: \"my-topic-for-cloudwatch-alerts\",\n * http5xxAlarm: {\n * tolerated5xxPercentage: 1,\n * }\n * }\n * });\n * ```\n *\n * For all API configuration options, see [[`GuApiGatewayWithLambdaByPathProps`]].\n *\n * For details on configuring the individual Lambda functions, see [[`GuLambdaFunction`]].\n */\nexport class GuApiGatewayWithLambdaByPath extends Construct {\n public readonly api: RestApi;\n\n constructor(scope: GuStack, props: GuApiGatewayWithLambdaByPathProps) {\n super(scope, props.app); // The assumption is `app` is unique\n const apiGateway = new RestApi(scope, \"RestApi\", {\n // Override to avoid clashes as default is just api ID, which is often shared across stages.\n restApiName: `${scope.stack}-${scope.stage}-${props.app}`,\n ...props,\n });\n\n this.api = apiGateway;\n props.targets.map((target) => {\n const resource = apiGateway.root.resourceForPath(target.path);\n resource.addMethod(target.httpMethod, new LambdaIntegration(target.lambda), {\n apiKeyRequired: target.apiKeyRequired,\n });\n });\n if (!isNoMonitoring(props.monitoringConfiguration)) {\n new GuApiGateway5xxPercentageAlarm(scope, {\n app: props.app,\n apiGatewayInstance: apiGateway,\n snsTopicName: props.monitoringConfiguration.snsTopicName,\n ...props.monitoringConfiguration.http5xxAlarm,\n });\n }\n }\n}\n"]}
1
+ {"version":3,"file":"api-multiple-lambdas.js","sourceRoot":"","sources":["../../src/patterns/api-multiple-lambdas.ts"],"names":[],"mappings":";;;AACA,+DAAwE;AACxE,2CAAuC;AAEvC,oFAA6F;AAiE7F,SAAS,cAAc,CACrB,uBAAwD;IAExD,OAAsB,uBAAwB,CAAC,YAAY,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,MAAa,4BAA6B,SAAQ,sBAAS;IAGzD,YAAY,KAAc,EAAE,KAAwC;QAClE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,oCAAoC;QAC7D,MAAM,UAAU,GAAG,IAAI,wBAAO,CAAC,KAAK,EAAE,SAAS,EAAE;YAC/C,4FAA4F;YAC5F,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,EAAE;YACzD,GAAG,KAAK;SACT,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,GAAG,UAAU,CAAC;QACtB,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YAC3B,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9D,sGAAsG;YACtG,0DAA0D;YAC1D,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC;YAC1D,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,kCAAiB,CAAC,YAAY,CAAC,EAAE;gBACzE,cAAc,EAAE,MAAM,CAAC,cAAc;aACtC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,uBAAuB,CAAC,EAAE;YAClD,IAAI,mDAA8B,CAAC,KAAK,EAAE;gBACxC,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,kBAAkB,EAAE,UAAU;gBAC9B,YAAY,EAAE,KAAK,CAAC,uBAAuB,CAAC,YAAY;gBACxD,GAAG,KAAK,CAAC,uBAAuB,CAAC,YAAY;aAC9C,CAAC,CAAC;SACJ;IACH,CAAC;CACF;AA9BD,oEA8BC","sourcesContent":["import type { RestApiProps } from \"aws-cdk-lib/aws-apigateway\";\nimport { LambdaIntegration, RestApi } from \"aws-cdk-lib/aws-apigateway\";\nimport { Construct } from \"constructs\";\nimport type { Http5xxAlarmProps, NoMonitoring } from \"../constructs/cloudwatch\";\nimport { GuApiGateway5xxPercentageAlarm } from \"../constructs/cloudwatch/api-gateway-alarms\";\nimport type { AppIdentity, GuStack } from \"../constructs/core\";\nimport type { GuLambdaFunction } from \"../constructs/lambda\";\n\n/**\n * See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods\n */\nexport type HttpMethod = \"GET\" | \"HEAD\" | \"POST\" | \"PUT\" | \"DELETE\" | \"CONNECT\" | \"OPTIONS\" | \"TRACE\" | \"PATCH\";\n\n/**\n * API target props.\n */\nexport interface ApiTarget {\n /**\n * The path for the request (e.g. /test).\n */\n path: string;\n /**\n * The [[`HttpMethod`]] for the target (e.g. GET, POST, PUT).\n */\n httpMethod: HttpMethod;\n /**\n * The Lambda function responsible for handling the request.\n */\n lambda: GuLambdaFunction;\n /**\n * Whether an apiKey is required for this method.\n */\n apiKeyRequired?: true;\n}\n\n/**\n * Alarm props.\n */\nexport interface ApiGatewayAlarms {\n /**\n * (SNS) Topic name where alarm notifications will be sent.\n */\n snsTopicName: string;\n /**\n * Configuration the 5xx alarm.\n */\n http5xxAlarm: Http5xxAlarmProps;\n /**\n * Internal flag - users of this library should ignore this setting.\n */\n noMonitoring?: false;\n}\n\nexport interface GuApiGatewayWithLambdaByPathProps extends RestApiProps, AppIdentity {\n /**\n * A list of [[`ApiTarget`]]s to configure for the API Gateway instance.\n */\n targets: ApiTarget[];\n /**\n * Alarm configuration for your API. For more details, see [[`ApiGatewayAlarms`]].\n *\n * If your team do not use CloudWatch, it's possible to opt-out with the following configuration:\n * ```typescript\n * monitoringConfiguration: { noMonitoring: true }\n * ```\n */\n monitoringConfiguration: NoMonitoring | ApiGatewayAlarms;\n}\n\nfunction isNoMonitoring(\n monitoringConfiguration: NoMonitoring | ApiGatewayAlarms\n): monitoringConfiguration is NoMonitoring {\n return (<NoMonitoring>monitoringConfiguration).noMonitoring;\n}\n\n/**\n * A pattern to create an API Gateway instance which uses path-based routing to route requests\n * to two or more Lambda functions.\n *\n * This pattern should be used if you need to configure path-based routing to serve different\n * requests with different Lambdas. If you intend to serve all traffic via a single Lambda, use\n * the [[`GuApiLambda`]] pattern instead.\n *\n * Example usage:\n *\n * ```typescript\n * // Configure lambdas\n * const lambdaOne = new GuLambdaFunction(this, \"lambda-one\", {\n * app: \"example-lambda-one\",\n * runtime: Runtime.NODEJS_14_X,\n * handler: \"lambda-one.handler\",\n * fileName: \"lambda-one.zip\",\n * });\n * const lambdaTwo = new GuLambdaFunction(this, \"lambda-two\", {\n * app: \"example-lambda-two\",\n * runtime: Runtime.NODEJS_14_X,\n * handler: \"lambda-two.handler\",\n * fileName: \"lambda-two.zip\",\n * });\n *\n * // Wire up the API\n * new GuApiGatewayWithLambdaByPath(this, {\n * app: \"example-api-gateway-instance\",\n * targets: [\n * {\n * path: \"lambda-one\",\n * httpMethod: \"GET\",\n * lambda: lambdaOne,\n * },\n * {\n * path: \"lambda-two\",\n * httpMethod: \"GET\",\n * lambda: lambdaTwo,\n * },\n * ],\n * // Create an alarm\n * monitoringConfiguration: {\n * snsTopicName: \"my-topic-for-cloudwatch-alerts\",\n * http5xxAlarm: {\n * tolerated5xxPercentage: 1,\n * }\n * }\n * });\n * ```\n *\n * For all API configuration options, see [[`GuApiGatewayWithLambdaByPathProps`]].\n *\n * For details on configuring the individual Lambda functions, see [[`GuLambdaFunction`]].\n */\nexport class GuApiGatewayWithLambdaByPath extends Construct {\n public readonly api: RestApi;\n\n constructor(scope: GuStack, props: GuApiGatewayWithLambdaByPathProps) {\n super(scope, props.app); // The assumption is `app` is unique\n const apiGateway = new RestApi(scope, \"RestApi\", {\n // Override to avoid clashes as default is just api ID, which is often shared across stages.\n restApiName: `${scope.stack}-${scope.stage}-${props.app}`,\n ...props,\n });\n\n this.api = apiGateway;\n props.targets.map((target) => {\n const resource = apiGateway.root.resourceForPath(target.path);\n // If we have an alias, use this to ensure that all requests are routed to a published Lambda version.\n // Otherwise, use the latest unpublished version ($LATEST)\n const lambdaTarget = target.lambda.alias ?? target.lambda;\n resource.addMethod(target.httpMethod, new LambdaIntegration(lambdaTarget), {\n apiKeyRequired: target.apiKeyRequired,\n });\n });\n if (!isNoMonitoring(props.monitoringConfiguration)) {\n new GuApiGateway5xxPercentageAlarm(scope, {\n app: props.app,\n apiGatewayInstance: apiGateway,\n snsTopicName: props.monitoringConfiguration.snsTopicName,\n ...props.monitoringConfiguration.http5xxAlarm,\n });\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"scheduled-lambda.d.ts","sourceRoot":"","sources":["../../src/patterns/scheduled-lambda.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,KAAK,EAAE,sCAAsC,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACrG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,eAAe,EAAE,2BAA2B,CAAC;IAChG;;OAEG;IACH,KAAK,EAAE,KAAK,CAAC;QACX;;;;;WAKG;QACH,QAAQ,EAAE,QAAQ,CAAC;QACnB;;WAEG;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH;;;;OAIG;IACH,uBAAuB,EAAE,YAAY,GAAG,sCAAsC,CAAC;CAChF;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,gBAAgB;gBACzC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,sBAAsB;CAiBtE"}
1
+ {"version":3,"file":"scheduled-lambda.d.ts","sourceRoot":"","sources":["../../src/patterns/scheduled-lambda.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,KAAK,EAAE,sCAAsC,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACrG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,eAAe,EAAE,2BAA2B,CAAC;IAChG;;OAEG;IACH,KAAK,EAAE,KAAK,CAAC;QACX;;;;;WAKG;QACH,QAAQ,EAAE,QAAQ,CAAC;QACnB;;WAEG;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH;;;;OAIG;IACH,uBAAuB,EAAE,YAAY,GAAG,sCAAsC,CAAC;CAChF;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,gBAAgB;gBACzC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,sBAAsB;CAmBtE"}
@@ -17,10 +17,12 @@ class GuScheduledLambda extends lambda_1.GuLambdaFunction {
17
17
  };
18
18
  super(scope, id, lambdaProps);
19
19
  props.rules.forEach((rule, index) => {
20
- const target = new aws_events_targets_1.LambdaFunction(this);
20
+ // If we have an alias, use this to ensure that all invocations are handled by a published Lambda version.
21
+ // Otherwise, use the latest unpublished version ($LATEST)
22
+ const resourceToInvoke = this.alias ?? this;
21
23
  new aws_events_1.Rule(this, `${id}-${rule.schedule.expressionString}-${index}`, {
22
24
  schedule: rule.schedule,
23
- targets: [target],
25
+ targets: [new aws_events_targets_1.LambdaFunction(resourceToInvoke)],
24
26
  ...(rule.description && { description: rule.description }),
25
27
  enabled: true,
26
28
  });
@@ -1 +1 @@
1
- {"version":3,"file":"scheduled-lambda.js","sourceRoot":"","sources":["../../src/patterns/scheduled-lambda.ts"],"names":[],"mappings":";;;AAAA,uDAA8C;AAE9C,uEAAgE;AAGhE,iDAAwD;AA4BxD;;;;GAIG;AACH,MAAa,iBAAkB,SAAQ,yBAAgB;IACrD,YAAY,KAAc,EAAE,EAAU,EAAE,KAA6B;QACnE,MAAM,WAAW,GAAoB;YACnC,GAAG,KAAK;YACR,yBAAyB,EAAE,KAAK,CAAC,uBAAuB,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,uBAAuB;SAClH,CAAC;QACF,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC;QAE9B,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YAClC,MAAM,MAAM,GAAG,IAAI,mCAAc,CAAC,IAAI,CAAC,CAAC;YACxC,IAAI,iBAAI,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,IAAI,KAAK,EAAE,EAAE;gBACjE,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,OAAO,EAAE,CAAC,MAAM,CAAC;gBACjB,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC1D,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAlBD,8CAkBC","sourcesContent":["import { Rule } from \"aws-cdk-lib/aws-events\";\nimport type { Schedule } from \"aws-cdk-lib/aws-events\";\nimport { LambdaFunction } from \"aws-cdk-lib/aws-events-targets\";\nimport type { GuLambdaErrorPercentageMonitoringProps, NoMonitoring } from \"../constructs/cloudwatch\";\nimport type { GuStack } from \"../constructs/core\";\nimport { GuLambdaFunction } from \"../constructs/lambda\";\nimport type { GuFunctionProps } from \"../constructs/lambda\";\n\nexport interface GuScheduledLambdaProps extends Omit<GuFunctionProps, \"errorPercentageMonitoring\"> {\n /**\n * Schedule(s) for the lambda task.\n */\n rules: Array<{\n /**\n * E.g.:\n *\n * - `Schedule.expression(\"cron(0 8 ? * MON-FRI *)\")`\n * - `Schedule.rate(Duration.minutes(5))`\n */\n schedule: Schedule;\n /**\n * Optional description.\n */\n description?: string;\n }>;\n /**\n * Monitoring configuration for the lambda.\n *\n * Opting-out via the `NoMonitoring` type is supported but discouraged.\n */\n monitoringConfiguration: NoMonitoring | GuLambdaErrorPercentageMonitoringProps;\n}\n\n/**\n * Pattern which creates all of the resources needed to invoke a lambda function on a schedule.\n *\n * For all configuration options, see [[`GuScheduledLambdaProps`]].\n */\nexport class GuScheduledLambda extends GuLambdaFunction {\n constructor(scope: GuStack, id: string, props: GuScheduledLambdaProps) {\n const lambdaProps: GuFunctionProps = {\n ...props,\n errorPercentageMonitoring: props.monitoringConfiguration.noMonitoring ? undefined : props.monitoringConfiguration,\n };\n super(scope, id, lambdaProps);\n\n props.rules.forEach((rule, index) => {\n const target = new LambdaFunction(this);\n new Rule(this, `${id}-${rule.schedule.expressionString}-${index}`, {\n schedule: rule.schedule,\n targets: [target],\n ...(rule.description && { description: rule.description }),\n enabled: true,\n });\n });\n }\n}\n"]}
1
+ {"version":3,"file":"scheduled-lambda.js","sourceRoot":"","sources":["../../src/patterns/scheduled-lambda.ts"],"names":[],"mappings":";;;AAAA,uDAA8C;AAE9C,uEAAgE;AAGhE,iDAAwD;AA4BxD;;;;GAIG;AACH,MAAa,iBAAkB,SAAQ,yBAAgB;IACrD,YAAY,KAAc,EAAE,EAAU,EAAE,KAA6B;QACnE,MAAM,WAAW,GAAoB;YACnC,GAAG,KAAK;YACR,yBAAyB,EAAE,KAAK,CAAC,uBAAuB,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,uBAAuB;SAClH,CAAC;QACF,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC;QAE9B,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YAClC,0GAA0G;YAC1G,0DAA0D;YAC1D,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;YAC5C,IAAI,iBAAI,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,IAAI,KAAK,EAAE,EAAE;gBACjE,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,OAAO,EAAE,CAAC,IAAI,mCAAc,CAAC,gBAAgB,CAAC,CAAC;gBAC/C,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC1D,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AApBD,8CAoBC","sourcesContent":["import { Rule } from \"aws-cdk-lib/aws-events\";\nimport type { Schedule } from \"aws-cdk-lib/aws-events\";\nimport { LambdaFunction } from \"aws-cdk-lib/aws-events-targets\";\nimport type { GuLambdaErrorPercentageMonitoringProps, NoMonitoring } from \"../constructs/cloudwatch\";\nimport type { GuStack } from \"../constructs/core\";\nimport { GuLambdaFunction } from \"../constructs/lambda\";\nimport type { GuFunctionProps } from \"../constructs/lambda\";\n\nexport interface GuScheduledLambdaProps extends Omit<GuFunctionProps, \"errorPercentageMonitoring\"> {\n /**\n * Schedule(s) for the lambda task.\n */\n rules: Array<{\n /**\n * E.g.:\n *\n * - `Schedule.expression(\"cron(0 8 ? * MON-FRI *)\")`\n * - `Schedule.rate(Duration.minutes(5))`\n */\n schedule: Schedule;\n /**\n * Optional description.\n */\n description?: string;\n }>;\n /**\n * Monitoring configuration for the lambda.\n *\n * Opting-out via the `NoMonitoring` type is supported but discouraged.\n */\n monitoringConfiguration: NoMonitoring | GuLambdaErrorPercentageMonitoringProps;\n}\n\n/**\n * Pattern which creates all of the resources needed to invoke a lambda function on a schedule.\n *\n * For all configuration options, see [[`GuScheduledLambdaProps`]].\n */\nexport class GuScheduledLambda extends GuLambdaFunction {\n constructor(scope: GuStack, id: string, props: GuScheduledLambdaProps) {\n const lambdaProps: GuFunctionProps = {\n ...props,\n errorPercentageMonitoring: props.monitoringConfiguration.noMonitoring ? undefined : props.monitoringConfiguration,\n };\n super(scope, id, lambdaProps);\n\n props.rules.forEach((rule, index) => {\n // If we have an alias, use this to ensure that all invocations are handled by a published Lambda version.\n // Otherwise, use the latest unpublished version ($LATEST)\n const resourceToInvoke = this.alias ?? this;\n new Rule(this, `${id}-${rule.schedule.expressionString}-${index}`, {\n schedule: rule.schedule,\n targets: [new LambdaFunction(resourceToInvoke)],\n ...(rule.description && { description: rule.description }),\n enabled: true,\n });\n });\n }\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@guardian/cdk",
3
3
  "description": "Generic Guardian flavoured AWS CDK components",
4
- "version": "50.9.0",
4
+ "version": "50.10.1",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
7
7
  "files": [
@@ -38,7 +38,7 @@
38
38
  "@types/lodash.upperfirst": "^4.3.7",
39
39
  "@types/node": "20.3.2",
40
40
  "@types/yargs": "^17.0.19",
41
- "aws-cdk": "2.78.0",
41
+ "aws-cdk": "2.87.0",
42
42
  "cz-conventional-changelog": "^3.3.0",
43
43
  "eslint": "^8.43.0",
44
44
  "eslint-plugin-custom-rules": "file:tools/eslint",
@@ -54,11 +54,11 @@
54
54
  },
55
55
  "dependencies": {
56
56
  "@oclif/core": "2.8.10",
57
- "aws-cdk-lib": "2.78.0",
57
+ "aws-cdk-lib": "2.87.0",
58
58
  "aws-sdk": "^2.1408.0",
59
59
  "chalk": "^4.1.2",
60
60
  "codemaker": "^1.84.0",
61
- "constructs": "10.2.18",
61
+ "constructs": "10.2.69",
62
62
  "git-url-parse": "^13.1.0",
63
63
  "js-yaml": "^4.1.0",
64
64
  "lodash.camelcase": "^4.3.0",
@@ -68,9 +68,9 @@
68
68
  "yargs": "^17.6.2"
69
69
  },
70
70
  "peerDependencies": {
71
- "aws-cdk": "2.78.0",
72
- "aws-cdk-lib": "2.78.0",
73
- "constructs": "10.2.18"
71
+ "aws-cdk": "2.87.0",
72
+ "aws-cdk-lib": "2.87.0",
73
+ "constructs": "10.2.69"
74
74
  },
75
75
  "config": {
76
76
  "commitizen": {