@guardian/cdk 49.0.0-beta.1 → 49.1.0-beta.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.
- package/lib/aspects/cfn-parameter-reporter.d.ts +9 -0
- package/lib/aspects/cfn-parameter-reporter.d.ts.map +1 -0
- package/lib/aspects/cfn-parameter-reporter.js +21 -0
- package/lib/aspects/cfn-parameter-reporter.js.map +1 -0
- package/lib/bin/commands/new-project/index.d.ts +1 -1
- package/lib/bin/commands/new-project/index.d.ts.map +1 -1
- package/lib/constants/metadata-keys.d.ts +0 -1
- package/lib/constants/metadata-keys.d.ts.map +1 -1
- package/lib/constants/metadata-keys.js +0 -1
- package/lib/constants/metadata-keys.js.map +1 -1
- package/lib/constructs/acm/certificate.d.ts +1 -1
- package/lib/constructs/acm/certificate.d.ts.map +1 -1
- package/lib/constructs/autoscaling/user-data.d.ts +1 -1
- package/lib/constructs/autoscaling/user-data.d.ts.map +1 -1
- package/lib/constructs/autoscaling/user-data.js +8 -8
- package/lib/constructs/autoscaling/user-data.js.map +1 -1
- package/lib/constructs/core/parameters/base.d.ts +2 -2
- package/lib/constructs/core/parameters/base.d.ts.map +1 -1
- package/lib/constructs/core/stack.d.ts +7 -1
- package/lib/constructs/core/stack.d.ts.map +1 -1
- package/lib/constructs/core/stack.js +31 -23
- package/lib/constructs/core/stack.js.map +1 -1
- package/lib/constructs/dns/dns-records.js +1 -1
- package/lib/constructs/dns/dns-records.js.map +1 -1
- package/lib/constructs/ec2/vpc.d.ts +1 -1
- package/lib/constructs/ec2/vpc.d.ts.map +1 -1
- package/lib/constructs/ecs/ecs-task.d.ts +4 -4
- package/lib/constructs/ecs/ecs-task.d.ts.map +1 -1
- package/lib/constructs/iam/policies/base-policy.d.ts +3 -3
- package/lib/constructs/iam/policies/base-policy.d.ts.map +1 -1
- package/lib/constructs/iam/roles/instance-role.d.ts +1 -1
- package/lib/constructs/iam/roles/instance-role.d.ts.map +1 -1
- package/lib/constructs/iam/roles/roles.d.ts +1 -1
- package/lib/constructs/iam/roles/roles.d.ts.map +1 -1
- package/lib/constructs/kinesis/kinesis-stream.d.ts +1 -1
- package/lib/constructs/kinesis/kinesis-stream.d.ts.map +1 -1
- package/lib/constructs/s3/index.d.ts +90 -0
- package/lib/constructs/s3/index.d.ts.map +1 -1
- package/lib/constructs/s3/index.js +33 -1
- package/lib/constructs/s3/index.js.map +1 -1
- package/lib/constructs/vpc/vpc.d.ts +1 -1
- package/lib/constructs/vpc/vpc.d.ts.map +1 -1
- package/lib/constructs/vpc/vpc.js +1 -1
- package/lib/constructs/vpc/vpc.js.map +1 -1
- package/lib/experimental/constructs/error-budget-alarm.d.ts +47 -2
- package/lib/experimental/constructs/error-budget-alarm.d.ts.map +1 -1
- package/lib/experimental/constructs/error-budget-alarm.js +84 -42
- package/lib/experimental/constructs/error-budget-alarm.js.map +1 -1
- package/lib/experimental/constructs/index.d.ts +3 -0
- package/lib/experimental/constructs/index.d.ts.map +1 -0
- package/lib/{constructs/sns → experimental/constructs}/index.js +2 -1
- package/lib/experimental/constructs/index.js.map +1 -0
- package/lib/experimental/patterns/sns-lambda.d.ts.map +1 -1
- package/lib/experimental/patterns/sns-lambda.js +1 -2
- package/lib/experimental/patterns/sns-lambda.js.map +1 -1
- package/lib/experimental/riff-raff-yaml-file/deployments/s3.d.ts +4 -0
- package/lib/experimental/riff-raff-yaml-file/deployments/s3.d.ts.map +1 -0
- package/lib/experimental/riff-raff-yaml-file/deployments/s3.js +48 -0
- package/lib/experimental/riff-raff-yaml-file/deployments/s3.js.map +1 -0
- package/lib/experimental/riff-raff-yaml-file/index.d.ts +13 -3
- package/lib/experimental/riff-raff-yaml-file/index.d.ts.map +1 -1
- package/lib/experimental/riff-raff-yaml-file/index.js +71 -51
- package/lib/experimental/riff-raff-yaml-file/index.js.map +1 -1
- package/lib/experimental/riff-raff-yaml-file/types.d.ts +8 -8
- package/lib/experimental/riff-raff-yaml-file/types.d.ts.map +1 -1
- package/lib/experimental/riff-raff-yaml-file/types.js.map +1 -1
- package/lib/patterns/api-multiple-lambdas.d.ts +5 -1
- package/lib/patterns/api-multiple-lambdas.d.ts.map +1 -1
- package/lib/patterns/api-multiple-lambdas.js +3 -1
- package/lib/patterns/api-multiple-lambdas.js.map +1 -1
- package/lib/patterns/ec2-app/base.d.ts.map +1 -1
- package/lib/patterns/ec2-app/base.js +0 -5
- package/lib/patterns/ec2-app/base.js.map +1 -1
- package/lib/patterns/ec2-app/framework.d.ts +1 -1
- package/lib/patterns/ec2-app/framework.d.ts.map +1 -1
- package/lib/types/access.d.ts +1 -1
- package/lib/types/access.d.ts.map +1 -1
- package/lib/types/cli.d.ts +1 -1
- package/lib/types/cli.d.ts.map +1 -1
- package/lib/utils/lambda/event-source.d.ts +4 -4
- package/lib/utils/lambda/event-source.d.ts.map +1 -1
- package/lib/utils/lambda/event-source.js +4 -4
- package/lib/utils/lambda/event-source.js.map +1 -1
- package/lib/utils/mixin/types.d.ts +1 -1
- package/lib/utils/mixin/types.d.ts.map +1 -1
- package/package.json +21 -21
- package/lib/constructs/sns/index.d.ts +0 -2
- package/lib/constructs/sns/index.d.ts.map +0 -1
- package/lib/constructs/sns/index.js.map +0 -1
- package/lib/constructs/sns/sns-topic.d.ts +0 -15
- package/lib/constructs/sns/sns-topic.d.ts.map +0 -1
- package/lib/constructs/sns/sns-topic.js +0 -17
- package/lib/constructs/sns/sns-topic.js.map +0 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { Duration } from "aws-cdk-lib";
|
|
1
2
|
import type { BucketProps } from "aws-cdk-lib/aws-s3";
|
|
2
3
|
import { Bucket } from "aws-cdk-lib/aws-s3";
|
|
4
|
+
import type { IConstruct } from "constructs";
|
|
3
5
|
import type { AppIdentity, GuStack } from "../core";
|
|
4
6
|
export interface GuS3BucketProps extends Omit<BucketProps, "removalPolicy">, AppIdentity {
|
|
5
7
|
}
|
|
@@ -14,5 +16,93 @@ declare const GuS3Bucket_base: {
|
|
|
14
16
|
export declare class GuS3Bucket extends GuS3Bucket_base {
|
|
15
17
|
constructor(scope: GuStack, id: string, props: GuS3BucketProps);
|
|
16
18
|
}
|
|
19
|
+
interface GuS3OriginBucketDeploymentProps {
|
|
20
|
+
/**
|
|
21
|
+
* Customises the SSM Parameter path, making it stage agnostic.
|
|
22
|
+
* Useful when a single bucket is used across multiple stages.
|
|
23
|
+
*
|
|
24
|
+
* When `false` the path will be `/<STAGE>/<STACK>/<APP>/<APP>-origin-bucket`.
|
|
25
|
+
* When `true` the path will be `/<STACK>/<APP>/<APP>-origin-bucket`.
|
|
26
|
+
*
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
withoutStageAwareness: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Used to configure `bucketSsmKeyStageParam` in a generated `riff-raff.yaml` file.
|
|
32
|
+
*
|
|
33
|
+
* The SSM Parameter path, without a stage prefix.
|
|
34
|
+
*
|
|
35
|
+
* Not settable by user.
|
|
36
|
+
*
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
baseParameterName: string;
|
|
40
|
+
/**
|
|
41
|
+
* Used to configure `cacheControl` in a generated `riff-raff.yaml` file.
|
|
42
|
+
* Only needed if you're also using {@link GuRootExperimental}.
|
|
43
|
+
*
|
|
44
|
+
* Set the cache control header for the uploaded files.
|
|
45
|
+
*
|
|
46
|
+
* The key is a regular expression to match uploaded files.
|
|
47
|
+
* The value is the max-age to set in the `Cache-Control` header.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* To cache all files for one hour:
|
|
51
|
+
* ```ts
|
|
52
|
+
* { ".*", Duration.hours(1) }
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @default cache nothing
|
|
56
|
+
* @see https://riffraff.gutools.co.uk/docs/magenta-lib/types#awss3
|
|
57
|
+
*/
|
|
58
|
+
cacheControl: Record<string, Duration>;
|
|
59
|
+
/**
|
|
60
|
+
* Used to configure `surrogateControl` in a generated `riff-raff.yaml` file.
|
|
61
|
+
* Only needed if you're also using {@link GuRootExperimental}.
|
|
62
|
+
*
|
|
63
|
+
* Same as [[cacheControl]], but for setting the surrogate-control cache header, which is used by Fastly.
|
|
64
|
+
*
|
|
65
|
+
* @see https://riffraff.gutools.co.uk/docs/magenta-lib/types#awss3
|
|
66
|
+
*/
|
|
67
|
+
surrogateControl: Record<string, Duration>;
|
|
68
|
+
/**
|
|
69
|
+
* Used to configure `mimeTypes` in a generated `riff-raff.yaml` file.
|
|
70
|
+
* Only needed if you're also using {@link GuRootExperimental}.
|
|
71
|
+
*
|
|
72
|
+
* A map of file extension to MIME type.
|
|
73
|
+
*
|
|
74
|
+
* When a file is uploaded with a file extension that is in this map, the Content-Type header will be set to the MIME type provided.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* { "xpi", "application/x-xpinstall" }
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* @see https://riffraff.gutools.co.uk/docs/magenta-lib/types#awss3
|
|
82
|
+
*/
|
|
83
|
+
mimeTypes: Record<string, string>;
|
|
84
|
+
}
|
|
85
|
+
export interface GuS3OriginBucketProps extends GuS3BucketProps, Partial<Omit<GuS3OriginBucketDeploymentProps, "baseParameterName">> {
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* An S3 bucket for use as an origin for a static site.
|
|
89
|
+
* The bucket name will be stored in an SSM Parameter.
|
|
90
|
+
* Other infrastructure, or applications, that use this bucket should discover its name by the Parameter.
|
|
91
|
+
*/
|
|
92
|
+
export declare class GuS3OriginBucket extends GuS3Bucket implements IConstruct {
|
|
93
|
+
/**
|
|
94
|
+
* The name of the created SSM Parameter.
|
|
95
|
+
*/
|
|
96
|
+
readonly parameterName: string;
|
|
97
|
+
readonly app: string;
|
|
98
|
+
/**
|
|
99
|
+
* For internal use only, used to generate a `riff-raff.yaml` file.
|
|
100
|
+
*
|
|
101
|
+
* @see [[RiffRaffYamlFileExperimental]]
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
104
|
+
readonly _deploymentProps: Required<GuS3OriginBucketDeploymentProps>;
|
|
105
|
+
constructor(scope: GuStack, id: string, props: GuS3OriginBucketProps);
|
|
106
|
+
}
|
|
17
107
|
export {};
|
|
18
108
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/constructs/s3/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/constructs/s3/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAqB,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEpD,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,EAAE,WAAW;CAAG;;;;;;AAE3F;;GAEG;AACH,qBAAa,UAAW,SAAQ,eAA2B;gBAC7C,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe;CAQ/D;AAED,UAAU,+BAA+B;IACvC;;;;;;;;OAQG;IACH,qBAAqB,EAAE,OAAO,CAAC;IAE/B;;;;;;;;OAQG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAE1B;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEvC;;;;;;;OAOG;IACH,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;OAcG;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,qBACf,SAAQ,eAAe,EACrB,OAAO,CAAC,IAAI,CAAC,+BAA+B,EAAE,mBAAmB,CAAC,CAAC;CAAG;AAE1E;;;;GAIG;AAEH,qBAAa,gBAAiB,SAAQ,UAAW,YAAW,UAAU;IACpE;;OAEG;IACH,SAAgB,aAAa,EAAE,MAAM,CAAC;IAEtC,SAAgB,GAAG,EAAE,MAAM,CAAC;IAE5B;;;;;OAKG;IACH,SAAgB,gBAAgB,EAAE,QAAQ,CAAC,+BAA+B,CAAC,CAAC;gBAEhE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB;CA4BrE"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GuS3Bucket = void 0;
|
|
3
|
+
exports.GuS3OriginBucket = exports.GuS3Bucket = void 0;
|
|
4
4
|
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
5
5
|
const aws_s3_1 = require("aws-cdk-lib/aws-s3");
|
|
6
|
+
const aws_ssm_1 = require("aws-cdk-lib/aws-ssm");
|
|
6
7
|
const app_aware_construct_1 = require("../../utils/mixin/app-aware-construct");
|
|
7
8
|
/**
|
|
8
9
|
* A construct to create a bucket with a "retain" policy to prevent it from being deleted. It will be orphaned instead.
|
|
@@ -18,4 +19,35 @@ class GuS3Bucket extends (0, app_aware_construct_1.GuAppAwareConstruct)(aws_s3_1
|
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
21
|
exports.GuS3Bucket = GuS3Bucket;
|
|
22
|
+
/**
|
|
23
|
+
* An S3 bucket for use as an origin for a static site.
|
|
24
|
+
* The bucket name will be stored in an SSM Parameter.
|
|
25
|
+
* Other infrastructure, or applications, that use this bucket should discover its name by the Parameter.
|
|
26
|
+
*/
|
|
27
|
+
// implementing `IConstruct` is a no-op here as `Bucket` ultimately does so already. We explicitly do so to avoid a `SuspiciousTypeOfGuard` warning in `riff-raff-yaml-file/index.ts`.
|
|
28
|
+
class GuS3OriginBucket extends GuS3Bucket {
|
|
29
|
+
constructor(scope, id, props) {
|
|
30
|
+
const { stage, stack } = scope;
|
|
31
|
+
const { app, withoutStageAwareness = false, cacheControl = {}, surrogateControl = {}, mimeTypes = {} } = props;
|
|
32
|
+
super(scope, id, props);
|
|
33
|
+
this.app = app;
|
|
34
|
+
const stageAgnosticParameterParts = [stack, app, `${app}-origin-bucket`];
|
|
35
|
+
const parameterParts = withoutStageAwareness
|
|
36
|
+
? stageAgnosticParameterParts
|
|
37
|
+
: [stage, ...stageAgnosticParameterParts];
|
|
38
|
+
this.parameterName = `/${parameterParts.join("/")}`;
|
|
39
|
+
new aws_ssm_1.StringParameter(scope, `${id}-ssm-param`, {
|
|
40
|
+
parameterName: this.parameterName,
|
|
41
|
+
stringValue: this.bucketName,
|
|
42
|
+
});
|
|
43
|
+
this._deploymentProps = {
|
|
44
|
+
withoutStageAwareness,
|
|
45
|
+
cacheControl,
|
|
46
|
+
surrogateControl,
|
|
47
|
+
mimeTypes,
|
|
48
|
+
baseParameterName: `/${stageAgnosticParameterParts.join("/")}`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.GuS3OriginBucket = GuS3OriginBucket;
|
|
21
53
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/constructs/s3/index.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/constructs/s3/index.ts"],"names":[],"mappings":";;;AACA,6CAA4C;AAE5C,+CAA+D;AAC/D,iDAAsD;AAEtD,+EAA4E;AAK5E;;GAEG;AACH,MAAa,UAAW,SAAQ,IAAA,yCAAmB,EAAC,eAAM,CAAC;IACzD,YAAY,KAAc,EAAE,EAAU,EAAE,KAAsB;QAC5D,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,aAAa,EAAE,2BAAa,CAAC,MAAM;YACnC,gBAAgB,EAAE,KAAK;YACvB,iBAAiB,EAAE,0BAAiB,CAAC,SAAS;YAC9C,GAAG,KAAK;SACT,CAAC,CAAC;IACL,CAAC;CACF;AATD,gCASC;AA6ED;;;;GAIG;AACH,sLAAsL;AACtL,MAAa,gBAAiB,SAAQ,UAAU;IAgB9C,YAAY,KAAc,EAAE,EAAU,EAAE,KAA4B;QAClE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;QAC/B,MAAM,EAAE,GAAG,EAAE,qBAAqB,GAAG,KAAK,EAAE,YAAY,GAAG,EAAE,EAAE,gBAAgB,GAAG,EAAE,EAAE,SAAS,GAAG,EAAE,EAAE,GAAG,KAAK,CAAC;QAE/G,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAExB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QAEf,MAAM,2BAA2B,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,gBAAgB,CAAC,CAAC;QACzE,MAAM,cAAc,GAAG,qBAAqB;YAC1C,CAAC,CAAC,2BAA2B;YAC7B,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,2BAA2B,CAAC,CAAC;QAE5C,IAAI,CAAC,aAAa,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAEpD,IAAI,yBAAe,CAAC,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE;YAC5C,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,WAAW,EAAE,IAAI,CAAC,UAAU;SAC7B,CAAC,CAAC;QAEH,IAAI,CAAC,gBAAgB,GAAG;YACtB,qBAAqB;YACrB,YAAY;YACZ,gBAAgB;YAChB,SAAS;YACT,iBAAiB,EAAE,IAAI,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;SAC/D,CAAC;IACJ,CAAC;CACF;AA5CD,4CA4CC","sourcesContent":["import type { Duration } from \"aws-cdk-lib\";\nimport { RemovalPolicy } from \"aws-cdk-lib\";\nimport type { BucketProps } from \"aws-cdk-lib/aws-s3\";\nimport { BlockPublicAccess, Bucket } from \"aws-cdk-lib/aws-s3\";\nimport { StringParameter } from \"aws-cdk-lib/aws-ssm\";\nimport type { IConstruct } from \"constructs\";\nimport { GuAppAwareConstruct } from \"../../utils/mixin/app-aware-construct\";\nimport type { AppIdentity, GuStack } from \"../core\";\n\nexport interface GuS3BucketProps extends Omit<BucketProps, \"removalPolicy\">, AppIdentity {}\n\n/**\n * A construct to create a bucket with a \"retain\" policy to prevent it from being deleted. It will be orphaned instead.\n */\nexport class GuS3Bucket extends GuAppAwareConstruct(Bucket) {\n constructor(scope: GuStack, id: string, props: GuS3BucketProps) {\n super(scope, id, {\n removalPolicy: RemovalPolicy.RETAIN,\n publicReadAccess: false,\n blockPublicAccess: BlockPublicAccess.BLOCK_ALL,\n ...props,\n });\n }\n}\n\ninterface GuS3OriginBucketDeploymentProps {\n /**\n * Customises the SSM Parameter path, making it stage agnostic.\n * Useful when a single bucket is used across multiple stages.\n *\n * When `false` the path will be `/<STAGE>/<STACK>/<APP>/<APP>-origin-bucket`.\n * When `true` the path will be `/<STACK>/<APP>/<APP>-origin-bucket`.\n *\n * @default false\n */\n withoutStageAwareness: boolean;\n\n /**\n * Used to configure `bucketSsmKeyStageParam` in a generated `riff-raff.yaml` file.\n *\n * The SSM Parameter path, without a stage prefix.\n *\n * Not settable by user.\n *\n * @internal\n */\n baseParameterName: string;\n\n /**\n * Used to configure `cacheControl` in a generated `riff-raff.yaml` file.\n * Only needed if you're also using {@link GuRootExperimental}.\n *\n * Set the cache control header for the uploaded files.\n *\n * The key is a regular expression to match uploaded files.\n * The value is the max-age to set in the `Cache-Control` header.\n *\n * @example\n * To cache all files for one hour:\n * ```ts\n * { \".*\", Duration.hours(1) }\n * ```\n *\n * @default cache nothing\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types#awss3\n */\n cacheControl: Record<string, Duration>;\n\n /**\n * Used to configure `surrogateControl` in a generated `riff-raff.yaml` file.\n * Only needed if you're also using {@link GuRootExperimental}.\n *\n * Same as [[cacheControl]], but for setting the surrogate-control cache header, which is used by Fastly.\n *\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types#awss3\n */\n surrogateControl: Record<string, Duration>;\n\n /**\n * Used to configure `mimeTypes` in a generated `riff-raff.yaml` file.\n * Only needed if you're also using {@link GuRootExperimental}.\n *\n * A map of file extension to MIME type.\n *\n * When a file is uploaded with a file extension that is in this map, the Content-Type header will be set to the MIME type provided.\n *\n * @example\n * ```ts\n * { \"xpi\", \"application/x-xpinstall\" }\n * ```\n *\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types#awss3\n */\n mimeTypes: Record<string, string>;\n}\n\nexport interface GuS3OriginBucketProps\n extends GuS3BucketProps,\n Partial<Omit<GuS3OriginBucketDeploymentProps, \"baseParameterName\">> {}\n\n/**\n * An S3 bucket for use as an origin for a static site.\n * The bucket name will be stored in an SSM Parameter.\n * Other infrastructure, or applications, that use this bucket should discover its name by the Parameter.\n */\n// implementing `IConstruct` is a no-op here as `Bucket` ultimately does so already. We explicitly do so to avoid a `SuspiciousTypeOfGuard` warning in `riff-raff-yaml-file/index.ts`.\nexport class GuS3OriginBucket extends GuS3Bucket implements IConstruct {\n /**\n * The name of the created SSM Parameter.\n */\n public readonly parameterName: string;\n\n public readonly app: string;\n\n /**\n * For internal use only, used to generate a `riff-raff.yaml` file.\n *\n * @see [[RiffRaffYamlFileExperimental]]\n * @internal\n */\n public readonly _deploymentProps: Required<GuS3OriginBucketDeploymentProps>;\n\n constructor(scope: GuStack, id: string, props: GuS3OriginBucketProps) {\n const { stage, stack } = scope;\n const { app, withoutStageAwareness = false, cacheControl = {}, surrogateControl = {}, mimeTypes = {} } = props;\n\n super(scope, id, props);\n\n this.app = app;\n\n const stageAgnosticParameterParts = [stack, app, `${app}-origin-bucket`];\n const parameterParts = withoutStageAwareness\n ? stageAgnosticParameterParts\n : [stage, ...stageAgnosticParameterParts];\n\n this.parameterName = `/${parameterParts.join(\"/\")}`;\n\n new StringParameter(scope, `${id}-ssm-param`, {\n parameterName: this.parameterName,\n stringValue: this.bucketName,\n });\n\n this._deploymentProps = {\n withoutStageAwareness,\n cacheControl,\n surrogateControl,\n mimeTypes,\n baseParameterName: `/${stageAgnosticParameterParts.join(\"/\")}`,\n };\n }\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { VpcProps } from "aws-cdk-lib/aws-ec2";
|
|
2
2
|
import { Vpc } from "aws-cdk-lib/aws-ec2";
|
|
3
3
|
import type { GuStack } from "../core";
|
|
4
|
-
export
|
|
4
|
+
export type GuVpcProps = VpcProps;
|
|
5
5
|
/**
|
|
6
6
|
* Construct which creates a Virtual Private Cloud.
|
|
7
7
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vpc.d.ts","sourceRoot":"","sources":["../../../src/constructs/vpc/vpc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAA4C,GAAG,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,
|
|
1
|
+
{"version":3,"file":"vpc.d.ts","sourceRoot":"","sources":["../../../src/constructs/vpc/vpc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAA4C,GAAG,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBAAa,KAAM,SAAQ,GAAG;IAC5B;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,0BAA0B;gBAc7B,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,UAAU;CA4B3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vpc.js","sourceRoot":"","sources":["../../../src/constructs/vpc/vpc.ts"],"names":[],"mappings":";;;AAAA,6CAAoC;AAEpC,iDAAoF;AAKpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAa,KAAM,SAAQ,aAAG;IAC5B;;;;;;;OAOG;IACK,MAAM,CAAC,0BAA0B,CAAC,EAAE,OAAO,EAAE,IAAI,EAAW;QAClE,IAAI,mBAAK,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE;YAC/B,MAAM,IAAI,KAAK,CACb,8JAA8J,CAC/J,CAAC;SACH;QAED,IAAI,CAAC,UAAU,CAAC,8BAA8B,OAAO,mBAAmB,EAAE;YACxE,YAAY;YACZ,YAAY;YACZ,YAAY;SACb,CAAC,CAAC;IACL,CAAC;IAED,YAAY,KAAc,EAAE,EAAU,EAAE,KAAkB;QACxD,MAAM,eAAe,GAAa;YAChC,gBAAgB,EAAE;gBAChB,EAAE,EAAE;oBACF,OAAO,EAAE,sCAA4B,CAAC,EAAE;iBACzC;gBACD,QAAQ,EAAE;oBACR,OAAO,EAAE,sCAA4B,CAAC,QAAQ;iBAC/C;aACF;YAED,mBAAmB,EAAE;gBACnB;oBACE,IAAI,EAAE,SAAS;oBACf,UAAU,EAAE,oBAAU,CAAC,MAAM;iBAC9B;gBACD;oBACE,IAAI,EAAE,aAAa;oBACnB,UAAU,EAAE,oBAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"vpc.js","sourceRoot":"","sources":["../../../src/constructs/vpc/vpc.ts"],"names":[],"mappings":";;;AAAA,6CAAoC;AAEpC,iDAAoF;AAKpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAa,KAAM,SAAQ,aAAG;IAC5B;;;;;;;OAOG;IACK,MAAM,CAAC,0BAA0B,CAAC,EAAE,OAAO,EAAE,IAAI,EAAW;QAClE,IAAI,mBAAK,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE;YAC/B,MAAM,IAAI,KAAK,CACb,8JAA8J,CAC/J,CAAC;SACH;QAED,IAAI,CAAC,UAAU,CAAC,8BAA8B,OAAO,mBAAmB,EAAE;YACxE,YAAY;YACZ,YAAY;YACZ,YAAY;SACb,CAAC,CAAC;IACL,CAAC;IAED,YAAY,KAAc,EAAE,EAAU,EAAE,KAAkB;QACxD,MAAM,eAAe,GAAa;YAChC,gBAAgB,EAAE;gBAChB,EAAE,EAAE;oBACF,OAAO,EAAE,sCAA4B,CAAC,EAAE;iBACzC;gBACD,QAAQ,EAAE;oBACR,OAAO,EAAE,sCAA4B,CAAC,QAAQ;iBAC/C;aACF;YAED,mBAAmB,EAAE;gBACnB;oBACE,IAAI,EAAE,SAAS;oBACf,UAAU,EAAE,oBAAU,CAAC,MAAM;iBAC9B;gBACD;oBACE,IAAI,EAAE,aAAa;oBACnB,UAAU,EAAE,oBAAU,CAAC,mBAAmB;iBAC3C;aACF;SACF,CAAC;QAEF,8GAA8G;QAC9G,KAAK,CAAC,0BAA0B,CAAC,KAAK,CAAC,CAAC;QAExC,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,eAAe,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;CACF;AAnDD,sBAmDC","sourcesContent":["import { Token } from \"aws-cdk-lib\";\nimport type { VpcProps } from \"aws-cdk-lib/aws-ec2\";\nimport { GatewayVpcEndpointAwsService, SubnetType, Vpc } from \"aws-cdk-lib/aws-ec2\";\nimport type { GuStack } from \"../core\";\n\nexport type GuVpcProps = VpcProps;\n\n/**\n * Construct which creates a Virtual Private Cloud.\n *\n * NOTE: This construct requires an\n * [environment](https://docs.aws.amazon.com/cdk/latest/guide/environments.html)\n * to be set to function correctly. Without this, an environment-agnostic\n * template will be produced, which will only use two AZs even if the region\n * contains more than that. To set this, set the `env` prop when instantiating\n * your stack.\n *\n * NOTE: If using this construct outside eu-west-1, you'll need to commit the\n * `cdk.context.json` file that's created after synthesising locally.\n *\n * Be aware that account IDs are considered sensitive information and should NOT\n * be committed to public repos.\n *\n * The VPC is provisioned with a public and private subnet for each availability\n * zone, with IPs spread evenly across these. Instances in private subnets\n * cannot be accessed directly over the internet. You should locate services in\n * instances in the private subnets, and provide HTTP(S) as required via load\n * balancers living in the public subnets.\n *\n * A CIDR block is a combined IP and network mask that specifies the IP\n * addresses in your VPC. For testing purposes any (AWS supported) CIDR block\n * will do, but for production you should:\n *\n * - use a /21 network mask (providing up to 2048 IPs, which is plenty for most\n * accounts)\n * - ask Enterprise Tech for an IP address to go with this range (so that\n * peering with other company VPCs is possible without IP clashes)\n *\n * A managed NAT is created for each private subnet to allow access to the\n * internet.\n *\n * For recommendations on how best to configure your VPC see:\n * https://github.com/guardian/recommendations/blob/main/AWS.md#vpc\n *\n * For more information on VPCs and AWS see:\n * https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html.\n */\nexport class GuVpc extends Vpc {\n /**\n * Programmatically sets the CDK context with a list of AZs for eu-west-1.\n * This means consuming stacks do NOT have to commit a `cdk.context.json`\n * file when using this construct in eu-west-1.\n *\n * @throws {Error} if the account ID has not been explicitly set on the parent GuStack\n * @private\n */\n private static setAvailabilityZoneContext({ account, node }: GuStack) {\n if (Token.isUnresolved(account)) {\n throw new Error(\n `Account ID not set - the resulting VPC might not be shaped how you'd expect. See https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.StackProps.html#env`\n );\n }\n\n node.setContext(`availability-zones:account=${account}:region=eu-west-1`, [\n \"eu-west-1a\",\n \"eu-west-1b\",\n \"eu-west-1c\",\n ]);\n }\n\n constructor(scope: GuStack, id: string, props?: GuVpcProps) {\n const defaultVpcProps: VpcProps = {\n gatewayEndpoints: {\n s3: {\n service: GatewayVpcEndpointAwsService.S3,\n },\n dynamodb: {\n service: GatewayVpcEndpointAwsService.DYNAMODB,\n },\n },\n\n subnetConfiguration: [\n {\n name: \"ingress\",\n subnetType: SubnetType.PUBLIC,\n },\n {\n name: \"application\",\n subnetType: SubnetType.PRIVATE_WITH_EGRESS,\n },\n ],\n };\n\n // Set the context BEFORE the `super` call to avoid `Error: Cannot set context after children have been added`\n GuVpc.setAvailabilityZoneContext(scope);\n\n super(scope, id, { ...defaultVpcProps, ...props });\n }\n}\n"]}
|
|
@@ -1,12 +1,57 @@
|
|
|
1
1
|
import type { IMetric } from "aws-cdk-lib/aws-cloudwatch";
|
|
2
|
+
import { Construct } from "constructs";
|
|
2
3
|
import type { GuStack } from "../../constructs/core";
|
|
3
4
|
export interface ErrorBudgetAlarmProps {
|
|
4
|
-
|
|
5
|
+
/**
|
|
6
|
+
* The name of the SLO. Assumed to be unique per stack.
|
|
7
|
+
*/
|
|
8
|
+
sloName: string;
|
|
9
|
+
/**
|
|
10
|
+
* The percentange target for the SLO, expressed as a decimal floating point number. Must be between 0.95 and 0.995.
|
|
11
|
+
*/
|
|
5
12
|
sloTarget: number;
|
|
13
|
+
/**
|
|
14
|
+
* The metric representing the bad events. Can be any IMetric type, like Metric or MathExpression.
|
|
15
|
+
*/
|
|
6
16
|
badEvents: IMetric;
|
|
17
|
+
/**
|
|
18
|
+
* The metric representing the events to be considered. Can be any IMetric type, like Metric or MathExpression.
|
|
19
|
+
*/
|
|
7
20
|
validEvents: IMetric;
|
|
21
|
+
/**
|
|
22
|
+
* The sns topic name (not the full arn) used by the alarm to send email alerts.
|
|
23
|
+
*/
|
|
24
|
+
snsTopicNameForAlerts: string;
|
|
8
25
|
}
|
|
9
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Use this construct to create alarms that will notify you when you are at risk of missing your SLO targets.
|
|
28
|
+
*
|
|
29
|
+
* These alarms follow the recommendations in the [SRE Workbook](https://sre.google/workbook/alerting-on-slos/) to
|
|
30
|
+
* implement Multiwindow, Multi-Burn-Rate Alerts.
|
|
31
|
+
*
|
|
32
|
+
* The CloudWatch implementation of this strategy creates nine separate CloudWatch alarms. The main alarms that users
|
|
33
|
+
* need to care about are the three composite alarms. These track different burn rates of error budget consumption:
|
|
34
|
+
* fast (e.g. complete outages), medium (e.g. moderate error percentage over hours, rather than minutes) and slow (e.g.
|
|
35
|
+
* a small percentage of errors sustained over a much longer period). Multiple burn rates are used to ensure that
|
|
36
|
+
* we are able to pick up all scenarios which could threaten the SLO, without interrupting developers with an
|
|
37
|
+
* unnecessary level of urgency.
|
|
38
|
+
*
|
|
39
|
+
* Each composite alarm creates two child alarms; these are used to support multiple windows (or periods in CloudWatch
|
|
40
|
+
* terminology). A composite alarm is configured to send notifications if both of its child alarms are in an alarm state.
|
|
41
|
+
* The child alarms themselves have no actions/notifications configured and users should not need to interact with them
|
|
42
|
+
* directly. Multiple windows are helpful for accuracy and reset time. The long window helps us to avoid sending an
|
|
43
|
+
* alert in scenarios where no intervention is required, for example a very brief spike in errors that is resolved
|
|
44
|
+
* automatically (e.g. when AWS replaces a 'bad' EC2 instance). The short window helps to ensure that the alert is reset
|
|
45
|
+
* (or moved back into OK state, in CloudWatch terminology) promptly once a problem has been resolved.
|
|
46
|
+
*
|
|
47
|
+
* The composite alarms have an awareness of priority, meaning that low priority alarm notifications are suppressed if
|
|
48
|
+
* a higher priority alarm is already firing. That is, if you receive an alert about fast error budget consumption, you
|
|
49
|
+
* should not receive an alert from the medium or slow versions of the alarm.
|
|
50
|
+
*
|
|
51
|
+
* For how to instantiate an ErrorBudgetAlarm check the unit-test in error-budget-alarm.test.ts,
|
|
52
|
+
* and for a description of the props that need to be passed see [[ErrorBudgetAlarmProps]]
|
|
53
|
+
*/
|
|
54
|
+
export declare class GuErrorBudgetAlarmExperimental extends Construct {
|
|
10
55
|
constructor(scope: GuStack, props: ErrorBudgetAlarmProps);
|
|
11
56
|
}
|
|
12
57
|
//# sourceMappingURL=error-budget-alarm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-budget-alarm.d.ts","sourceRoot":"","sources":["../../../src/experimental/constructs/error-budget-alarm.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"error-budget-alarm.d.ts","sourceRoot":"","sources":["../../../src/experimental/constructs/error-budget-alarm.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAqB,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAa7E,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AA+BD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,8BAA+B,SAAQ,SAAS;gBAC/C,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,qBAAqB;CAsEzD"}
|
|
@@ -1,77 +1,110 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.GuErrorBudgetAlarmExperimental = void 0;
|
|
4
4
|
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
5
5
|
const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
|
|
6
6
|
const aws_cloudwatch_actions_1 = require("aws-cdk-lib/aws-cloudwatch-actions");
|
|
7
7
|
const aws_sns_1 = require("aws-cdk-lib/aws-sns");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
const constructs_1 = require("constructs");
|
|
9
|
+
/**
|
|
10
|
+
* Use this construct to create alarms that will notify you when you are at risk of missing your SLO targets.
|
|
11
|
+
*
|
|
12
|
+
* These alarms follow the recommendations in the [SRE Workbook](https://sre.google/workbook/alerting-on-slos/) to
|
|
13
|
+
* implement Multiwindow, Multi-Burn-Rate Alerts.
|
|
14
|
+
*
|
|
15
|
+
* The CloudWatch implementation of this strategy creates nine separate CloudWatch alarms. The main alarms that users
|
|
16
|
+
* need to care about are the three composite alarms. These track different burn rates of error budget consumption:
|
|
17
|
+
* fast (e.g. complete outages), medium (e.g. moderate error percentage over hours, rather than minutes) and slow (e.g.
|
|
18
|
+
* a small percentage of errors sustained over a much longer period). Multiple burn rates are used to ensure that
|
|
19
|
+
* we are able to pick up all scenarios which could threaten the SLO, without interrupting developers with an
|
|
20
|
+
* unnecessary level of urgency.
|
|
21
|
+
*
|
|
22
|
+
* Each composite alarm creates two child alarms; these are used to support multiple windows (or periods in CloudWatch
|
|
23
|
+
* terminology). A composite alarm is configured to send notifications if both of its child alarms are in an alarm state.
|
|
24
|
+
* The child alarms themselves have no actions/notifications configured and users should not need to interact with them
|
|
25
|
+
* directly. Multiple windows are helpful for accuracy and reset time. The long window helps us to avoid sending an
|
|
26
|
+
* alert in scenarios where no intervention is required, for example a very brief spike in errors that is resolved
|
|
27
|
+
* automatically (e.g. when AWS replaces a 'bad' EC2 instance). The short window helps to ensure that the alert is reset
|
|
28
|
+
* (or moved back into OK state, in CloudWatch terminology) promptly once a problem has been resolved.
|
|
29
|
+
*
|
|
30
|
+
* The composite alarms have an awareness of priority, meaning that low priority alarm notifications are suppressed if
|
|
31
|
+
* a higher priority alarm is already firing. That is, if you receive an alert about fast error budget consumption, you
|
|
32
|
+
* should not receive an alert from the medium or slow versions of the alarm.
|
|
33
|
+
*
|
|
34
|
+
* For how to instantiate an ErrorBudgetAlarm check the unit-test in error-budget-alarm.test.ts,
|
|
35
|
+
* and for a description of the props that need to be passed see [[ErrorBudgetAlarmProps]]
|
|
36
|
+
*/
|
|
37
|
+
class GuErrorBudgetAlarmExperimental extends constructs_1.Construct {
|
|
16
38
|
constructor(scope, props) {
|
|
39
|
+
const lowestTargetAllowed = 0.95;
|
|
40
|
+
const highestTargetAllowed = 0.9995;
|
|
41
|
+
if (!(props.sloTarget >= lowestTargetAllowed && props.sloTarget <= highestTargetAllowed)) {
|
|
42
|
+
throw new Error(`ErrorBudgetAlarm only works with SLO targets between ${lowestTargetAllowed} and ${highestTargetAllowed}`);
|
|
43
|
+
}
|
|
44
|
+
super(scope, props.sloName); // The assumption here is that `sloName` will be unique (per stack)
|
|
17
45
|
const errorBudget = 1 - props.sloTarget;
|
|
18
|
-
const snsTopic = aws_sns_1.Topic.fromTopicArn(scope,
|
|
46
|
+
const snsTopic = aws_sns_1.Topic.fromTopicArn(scope, `SnsSloAlarmsFor${props.sloName}`, `arn:aws:sns:${scope.region}:${scope.account}:${props.snsTopicNameForAlerts}`);
|
|
19
47
|
const fastBurnRate = {
|
|
20
|
-
speed:
|
|
21
|
-
burnRate:
|
|
22
|
-
|
|
23
|
-
|
|
48
|
+
speed: "Fast",
|
|
49
|
+
burnRate: 14.4,
|
|
50
|
+
longPeriod: aws_cdk_lib_1.Duration.hours(1),
|
|
51
|
+
shortPeriod: aws_cdk_lib_1.Duration.minutes(5),
|
|
24
52
|
};
|
|
25
53
|
const fastBurnAlarm = new CompositeBurnRateAlarm(scope, {
|
|
54
|
+
sloName: props.sloName,
|
|
26
55
|
badEvents: props.badEvents,
|
|
27
|
-
|
|
56
|
+
burnRateMonitoring: fastBurnRate,
|
|
28
57
|
errorBudget,
|
|
29
58
|
snsTopic,
|
|
30
59
|
validEvents: props.validEvents,
|
|
31
60
|
});
|
|
32
|
-
const
|
|
33
|
-
speed:
|
|
61
|
+
const mediumBurnRateMonitoring = {
|
|
62
|
+
speed: "Medium",
|
|
34
63
|
burnRate: 6,
|
|
35
|
-
|
|
36
|
-
|
|
64
|
+
longPeriod: aws_cdk_lib_1.Duration.hours(6),
|
|
65
|
+
shortPeriod: aws_cdk_lib_1.Duration.minutes(30),
|
|
37
66
|
};
|
|
38
|
-
const
|
|
67
|
+
const mediumBurnRateAlarm = new CompositeBurnRateAlarm(scope, {
|
|
68
|
+
sloName: props.sloName,
|
|
39
69
|
badEvents: props.badEvents,
|
|
40
|
-
|
|
70
|
+
burnRateMonitoring: mediumBurnRateMonitoring,
|
|
41
71
|
errorBudget,
|
|
42
72
|
snsTopic,
|
|
43
73
|
validEvents: props.validEvents,
|
|
74
|
+
suppressorAlarm: fastBurnAlarm,
|
|
44
75
|
});
|
|
45
|
-
applySuppression(moderateBurnAlarm, fastBurnAlarm, moderateBurnRate.shortWindow);
|
|
46
76
|
const slowBurnRate = {
|
|
47
|
-
speed:
|
|
77
|
+
speed: "Slow",
|
|
48
78
|
burnRate: 3,
|
|
49
|
-
|
|
50
|
-
|
|
79
|
+
longPeriod: aws_cdk_lib_1.Duration.days(1),
|
|
80
|
+
shortPeriod: aws_cdk_lib_1.Duration.hours(2),
|
|
51
81
|
};
|
|
52
|
-
|
|
82
|
+
new CompositeBurnRateAlarm(scope, {
|
|
83
|
+
sloName: props.sloName,
|
|
53
84
|
badEvents: props.badEvents,
|
|
54
|
-
|
|
85
|
+
burnRateMonitoring: slowBurnRate,
|
|
55
86
|
errorBudget,
|
|
87
|
+
// TODO - use a different topic for tickets or figure out how to route notifications vs tickets using a single topic
|
|
56
88
|
snsTopic,
|
|
57
89
|
validEvents: props.validEvents,
|
|
90
|
+
suppressorAlarm: mediumBurnRateAlarm,
|
|
58
91
|
});
|
|
59
|
-
applySuppression(slowBurnAlarm, moderateBurnAlarm, slowBurnRate.shortWindow);
|
|
60
92
|
}
|
|
61
93
|
}
|
|
62
|
-
exports.
|
|
63
|
-
class
|
|
94
|
+
exports.GuErrorBudgetAlarmExperimental = GuErrorBudgetAlarmExperimental;
|
|
95
|
+
class MonitorBurnRateForPeriod extends aws_cloudwatch_1.Alarm {
|
|
64
96
|
constructor(scope, props) {
|
|
65
97
|
const undesirableErrorBudgetConsumption = props.errorBudget * props.burnRateSpeed.burnRate;
|
|
66
|
-
super(scope,
|
|
98
|
+
super(scope, props.alarmName, {
|
|
99
|
+
alarmName: props.alarmName,
|
|
67
100
|
metric: new aws_cloudwatch_1.MathExpression({
|
|
68
|
-
expression:
|
|
69
|
-
label:
|
|
101
|
+
expression: "badEvents/validEvents",
|
|
102
|
+
label: "Observed failure rate",
|
|
70
103
|
usingMetrics: {
|
|
71
104
|
badEvents: props.badEvents,
|
|
72
105
|
validEvents: props.validEvents,
|
|
73
106
|
},
|
|
74
|
-
period: props.
|
|
107
|
+
period: props.period,
|
|
75
108
|
}),
|
|
76
109
|
evaluationPeriods: 1,
|
|
77
110
|
threshold: undesirableErrorBudgetConsumption,
|
|
@@ -82,25 +115,34 @@ class IndividualBurnRateAlarm extends aws_cloudwatch_1.Alarm {
|
|
|
82
115
|
}
|
|
83
116
|
class CompositeBurnRateAlarm extends aws_cloudwatch_1.CompositeAlarm {
|
|
84
117
|
constructor(scope, props) {
|
|
118
|
+
const alarmName = `${props.sloName}${props.burnRateMonitoring.speed}BurnCompositeAlarm`;
|
|
85
119
|
const sharedIndividualAlarmProps = {
|
|
86
120
|
badEvents: props.badEvents,
|
|
87
121
|
burnRateSpeed: {
|
|
88
|
-
speed: props.
|
|
89
|
-
burnRate: props.
|
|
122
|
+
speed: props.burnRateMonitoring.speed,
|
|
123
|
+
burnRate: props.burnRateMonitoring.burnRate,
|
|
90
124
|
},
|
|
91
125
|
errorBudget: props.errorBudget,
|
|
92
|
-
validEvents: props.validEvents
|
|
126
|
+
validEvents: props.validEvents,
|
|
93
127
|
};
|
|
94
|
-
super(scope,
|
|
95
|
-
alarmRule: aws_cloudwatch_1.AlarmRule.allOf(aws_cloudwatch_1.AlarmRule.fromAlarm(new
|
|
128
|
+
super(scope, alarmName, {
|
|
129
|
+
alarmRule: aws_cloudwatch_1.AlarmRule.allOf(aws_cloudwatch_1.AlarmRule.fromAlarm(new MonitorBurnRateForPeriod(scope, {
|
|
96
130
|
...sharedIndividualAlarmProps,
|
|
97
|
-
|
|
98
|
-
|
|
131
|
+
alarmName: `ChildAlarmLongPeriod${alarmName}`,
|
|
132
|
+
period: props.burnRateMonitoring.longPeriod,
|
|
133
|
+
}), aws_cloudwatch_1.AlarmState.ALARM), aws_cloudwatch_1.AlarmRule.fromAlarm(new MonitorBurnRateForPeriod(scope, {
|
|
99
134
|
...sharedIndividualAlarmProps,
|
|
100
|
-
|
|
135
|
+
alarmName: `ChildAlarmShortPeriod${alarmName}`,
|
|
136
|
+
period: props.burnRateMonitoring.shortPeriod,
|
|
101
137
|
}), aws_cloudwatch_1.AlarmState.ALARM)),
|
|
102
138
|
});
|
|
103
139
|
this.addAlarmAction(new aws_cloudwatch_actions_1.SnsAction(props.snsTopic));
|
|
140
|
+
if (props.suppressorAlarm) {
|
|
141
|
+
const cfnAlarm = this.node.defaultChild;
|
|
142
|
+
cfnAlarm.actionsSuppressor = props.suppressorAlarm.alarmArn;
|
|
143
|
+
cfnAlarm.actionsSuppressorWaitPeriod = 120;
|
|
144
|
+
cfnAlarm.actionsSuppressorExtensionPeriod = props.burnRateMonitoring.shortPeriod.toSeconds();
|
|
145
|
+
}
|
|
104
146
|
}
|
|
105
147
|
}
|
|
106
148
|
//# sourceMappingURL=error-budget-alarm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-budget-alarm.js","sourceRoot":"","sources":["../../../src/experimental/constructs/error-budget-alarm.ts"],"names":[],"mappings":"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","sourcesContent":["import { Duration } from \"aws-cdk-lib\";\nimport type { CfnCompositeAlarm,\n IMetric} from \"aws-cdk-lib/aws-cloudwatch\";\nimport {\n Alarm, AlarmRule, AlarmState,\n ComparisonOperator,\n CompositeAlarm,\n MathExpression,\n TreatMissingData\n} from \"aws-cdk-lib/aws-cloudwatch\";\nimport { SnsAction } from \"aws-cdk-lib/aws-cloudwatch-actions\";\nimport type { ITopic} from \"aws-cdk-lib/aws-sns\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport type { GuStack } from \"../../constructs/core\";\n\nexport interface ErrorBudgetAlarmProps {\n snsTopicNameForAlerts: string;\n sloTarget: number;\n badEvents: IMetric; // Should this be IMetric[]?\n validEvents: IMetric; // Should this be IMetric[]?\n // Could accept a MathExpression for more complicated cases?\n}\n\ninterface BurnRateSpeed {\n speed: 'Fast' | 'Moderate' | 'Slow';\n burnRate: number;\n}\n\ninterface BurnRate extends BurnRateSpeed {\n longWindow: Duration;\n shortWindow: Duration;\n}\n\ninterface IndividualBurnRateAlarmProps {\n burnRateSpeed: BurnRateSpeed;\n window: Duration;\n errorBudget: number;\n badEvents: IMetric;\n validEvents: IMetric;\n}\n\ninterface CompositeBurnRateAlarmProps {\n burnRate: BurnRate;\n errorBudget: number;\n badEvents: IMetric;\n validEvents: IMetric;\n snsTopic: ITopic;\n}\n\nfunction applySuppression(\n alarmToSuppress: CompositeAlarm,\n suppressingAlarm: CompositeAlarm,\n shortWindow: Duration,\n) {\n const cfnAlarm = alarmToSuppress.node.defaultChild as CfnCompositeAlarm;\n cfnAlarm.actionsSuppressor = suppressingAlarm.alarmArn;\n cfnAlarm.actionsSuppressorWaitPeriod = 120;\n cfnAlarm.actionsSuppressorExtensionPeriod = shortWindow.toSeconds();\n}\n\n// Do we need to extend construct here?\nexport class ErrorBudgetAlarmExperimental {\n\n constructor(scope: GuStack, props: ErrorBudgetAlarmProps) {\n\n const errorBudget = 1 - props.sloTarget;\n\n const snsTopic: ITopic = Topic.fromTopicArn(\n scope,\n 'SnsSloAlarms',\n `arn:aws:sns:${scope.region}:${scope.account}:${props.snsTopicNameForAlerts}`,\n );\n\n const fastBurnRate: BurnRate = {\n speed: 'Fast',\n burnRate: 15,\n longWindow: Duration.hours(1),\n shortWindow: Duration.minutes(5),\n };\n\n const fastBurnAlarm = new CompositeBurnRateAlarm(scope, {\n badEvents: props.badEvents,\n burnRate: fastBurnRate,\n errorBudget,\n snsTopic,\n validEvents: props.validEvents,\n });\n\n const moderateBurnRate: BurnRate = {\n speed: 'Moderate',\n burnRate: 6,\n longWindow: Duration.hours(6),\n shortWindow: Duration.minutes(30),\n };\n\n const moderateBurnAlarm = new CompositeBurnRateAlarm(scope, {\n badEvents: props.badEvents,\n burnRate: moderateBurnRate,\n errorBudget,\n snsTopic,\n validEvents: props.validEvents,\n });\n\n applySuppression(\n moderateBurnAlarm,\n fastBurnAlarm,\n moderateBurnRate.shortWindow,\n );\n\n const slowBurnRate: BurnRate = {\n speed: 'Slow',\n burnRate: 3,\n longWindow: Duration.days(1),\n shortWindow: Duration.hours(2),\n };\n\n const slowBurnAlarm = new CompositeBurnRateAlarm(scope, {\n badEvents: props.badEvents,\n burnRate: slowBurnRate,\n errorBudget,\n snsTopic, // TODO - use a different topic for tickets or figure out how to route notifications vs tickets using a single topic\n validEvents: props.validEvents,\n });\n\n applySuppression(\n slowBurnAlarm,\n moderateBurnAlarm,\n slowBurnRate.shortWindow,\n );\n\n }\n\n}\n\nclass IndividualBurnRateAlarm extends Alarm {\n constructor(scope: GuStack, props: IndividualBurnRateAlarmProps) {\n const undesirableErrorBudgetConsumption = props.errorBudget * props.burnRateSpeed.burnRate;\n super(\n scope,\n `${props.burnRateSpeed.speed}BurnOver${props.window.toHumanString()}`,\n {\n metric: new MathExpression({\n expression: `badEvents/validEvents`,\n label: 'Observed failure rate',\n usingMetrics: {\n badEvents: props.badEvents,\n validEvents: props.validEvents,\n },\n period: props.window,\n }),\n evaluationPeriods: 1,\n threshold: undesirableErrorBudgetConsumption,\n comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n },\n );\n }\n}\n\nclass CompositeBurnRateAlarm extends CompositeAlarm {\n constructor(scope: GuStack, props: CompositeBurnRateAlarmProps) {\n const sharedIndividualAlarmProps = {\n badEvents: props.badEvents,\n burnRateSpeed: {\n speed: props.burnRate.speed,\n burnRate: props.burnRate.burnRate,\n },\n errorBudget: props.errorBudget,\n validEvents: props.validEvents\n };\n super(scope,\n `${props.burnRate.speed}BurnCompositeAlarm`,\n {\n alarmRule: AlarmRule.allOf(\n AlarmRule.fromAlarm(\n new IndividualBurnRateAlarm(scope, {\n ...sharedIndividualAlarmProps,\n window: props.burnRate.longWindow,\n }),\n AlarmState.ALARM,\n ),\n AlarmRule.fromAlarm(\n new IndividualBurnRateAlarm(scope, {\n ...sharedIndividualAlarmProps,\n window: props.burnRate.shortWindow,\n }),\n AlarmState.ALARM,\n ),\n ),\n },\n );\n this.addAlarmAction(new SnsAction(props.snsTopic));\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"error-budget-alarm.js","sourceRoot":"","sources":["../../../src/experimental/constructs/error-budget-alarm.ts"],"names":[],"mappings":"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","sourcesContent":["import { Duration } from \"aws-cdk-lib\";\nimport type { CfnCompositeAlarm, IMetric } from \"aws-cdk-lib/aws-cloudwatch\";\nimport {\n Alarm,\n AlarmRule,\n AlarmState,\n ComparisonOperator,\n CompositeAlarm,\n MathExpression,\n TreatMissingData,\n} from \"aws-cdk-lib/aws-cloudwatch\";\nimport { SnsAction } from \"aws-cdk-lib/aws-cloudwatch-actions\";\nimport type { ITopic } from \"aws-cdk-lib/aws-sns\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport { Construct } from \"constructs\";\nimport type { GuStack } from \"../../constructs/core\";\n\nexport interface ErrorBudgetAlarmProps {\n /**\n * The name of the SLO. Assumed to be unique per stack.\n */\n sloName: string;\n /**\n * The percentange target for the SLO, expressed as a decimal floating point number. Must be between 0.95 and 0.995.\n */\n sloTarget: number;\n /**\n * The metric representing the bad events. Can be any IMetric type, like Metric or MathExpression.\n */\n badEvents: IMetric;\n /**\n * The metric representing the events to be considered. Can be any IMetric type, like Metric or MathExpression.\n */\n validEvents: IMetric;\n /**\n * The sns topic name (not the full arn) used by the alarm to send email alerts.\n */\n snsTopicNameForAlerts: string;\n}\n\ninterface BurnRate {\n speed: \"Fast\" | \"Medium\" | \"Slow\";\n burnRate: number;\n}\n\ninterface BurnRateMonitoring extends BurnRate {\n longPeriod: Duration;\n shortPeriod: Duration;\n}\n\ninterface MonitorBurnRateForPeriodProps {\n alarmName: string;\n burnRateSpeed: BurnRate;\n period: Duration;\n errorBudget: number;\n badEvents: IMetric;\n validEvents: IMetric;\n}\n\ninterface CompositeBurnRateAlarmProps {\n sloName: string;\n burnRateMonitoring: BurnRateMonitoring;\n errorBudget: number;\n badEvents: IMetric;\n validEvents: IMetric;\n snsTopic: ITopic;\n suppressorAlarm?: CompositeBurnRateAlarm;\n}\n\n/**\n * Use this construct to create alarms that will notify you when you are at risk of missing your SLO targets.\n *\n * These alarms follow the recommendations in the [SRE Workbook](https://sre.google/workbook/alerting-on-slos/) to\n * implement Multiwindow, Multi-Burn-Rate Alerts.\n *\n * The CloudWatch implementation of this strategy creates nine separate CloudWatch alarms. The main alarms that users\n * need to care about are the three composite alarms. These track different burn rates of error budget consumption:\n * fast (e.g. complete outages), medium (e.g. moderate error percentage over hours, rather than minutes) and slow (e.g.\n * a small percentage of errors sustained over a much longer period). Multiple burn rates are used to ensure that\n * we are able to pick up all scenarios which could threaten the SLO, without interrupting developers with an\n * unnecessary level of urgency.\n *\n * Each composite alarm creates two child alarms; these are used to support multiple windows (or periods in CloudWatch\n * terminology). A composite alarm is configured to send notifications if both of its child alarms are in an alarm state.\n * The child alarms themselves have no actions/notifications configured and users should not need to interact with them\n * directly. Multiple windows are helpful for accuracy and reset time. The long window helps us to avoid sending an\n * alert in scenarios where no intervention is required, for example a very brief spike in errors that is resolved\n * automatically (e.g. when AWS replaces a 'bad' EC2 instance). The short window helps to ensure that the alert is reset\n * (or moved back into OK state, in CloudWatch terminology) promptly once a problem has been resolved.\n *\n * The composite alarms have an awareness of priority, meaning that low priority alarm notifications are suppressed if\n * a higher priority alarm is already firing. That is, if you receive an alert about fast error budget consumption, you\n * should not receive an alert from the medium or slow versions of the alarm.\n *\n * For how to instantiate an ErrorBudgetAlarm check the unit-test in error-budget-alarm.test.ts,\n * and for a description of the props that need to be passed see [[ErrorBudgetAlarmProps]]\n */\nexport class GuErrorBudgetAlarmExperimental extends Construct {\n constructor(scope: GuStack, props: ErrorBudgetAlarmProps) {\n const lowestTargetAllowed = 0.95;\n const highestTargetAllowed = 0.9995;\n if (!(props.sloTarget >= lowestTargetAllowed && props.sloTarget <= highestTargetAllowed)) {\n throw new Error(\n `ErrorBudgetAlarm only works with SLO targets between ${lowestTargetAllowed} and ${highestTargetAllowed}`\n );\n }\n\n super(scope, props.sloName); // The assumption here is that `sloName` will be unique (per stack)\n\n const errorBudget = 1 - props.sloTarget;\n\n const snsTopic: ITopic = Topic.fromTopicArn(\n scope,\n `SnsSloAlarmsFor${props.sloName}`,\n `arn:aws:sns:${scope.region}:${scope.account}:${props.snsTopicNameForAlerts}`\n );\n\n const fastBurnRate: BurnRateMonitoring = {\n speed: \"Fast\",\n burnRate: 14.4,\n longPeriod: Duration.hours(1),\n shortPeriod: Duration.minutes(5),\n };\n\n const fastBurnAlarm = new CompositeBurnRateAlarm(scope, {\n sloName: props.sloName,\n badEvents: props.badEvents,\n burnRateMonitoring: fastBurnRate,\n errorBudget,\n snsTopic,\n validEvents: props.validEvents,\n });\n\n const mediumBurnRateMonitoring: BurnRateMonitoring = {\n speed: \"Medium\",\n burnRate: 6,\n longPeriod: Duration.hours(6),\n shortPeriod: Duration.minutes(30),\n };\n\n const mediumBurnRateAlarm = new CompositeBurnRateAlarm(scope, {\n sloName: props.sloName,\n badEvents: props.badEvents,\n burnRateMonitoring: mediumBurnRateMonitoring,\n errorBudget,\n snsTopic,\n validEvents: props.validEvents,\n suppressorAlarm: fastBurnAlarm,\n });\n\n const slowBurnRate: BurnRateMonitoring = {\n speed: \"Slow\",\n burnRate: 3,\n longPeriod: Duration.days(1),\n shortPeriod: Duration.hours(2),\n };\n\n new CompositeBurnRateAlarm(scope, {\n sloName: props.sloName,\n badEvents: props.badEvents,\n burnRateMonitoring: slowBurnRate,\n errorBudget,\n // TODO - use a different topic for tickets or figure out how to route notifications vs tickets using a single topic\n snsTopic,\n validEvents: props.validEvents,\n suppressorAlarm: mediumBurnRateAlarm,\n });\n }\n}\n\nclass MonitorBurnRateForPeriod extends Alarm {\n constructor(scope: GuStack, props: MonitorBurnRateForPeriodProps) {\n const undesirableErrorBudgetConsumption = props.errorBudget * props.burnRateSpeed.burnRate;\n super(scope, props.alarmName, {\n alarmName: props.alarmName,\n metric: new MathExpression({\n expression: \"badEvents/validEvents\",\n label: \"Observed failure rate\",\n usingMetrics: {\n badEvents: props.badEvents,\n validEvents: props.validEvents,\n },\n period: props.period,\n }),\n evaluationPeriods: 1,\n threshold: undesirableErrorBudgetConsumption,\n comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n });\n }\n}\n\nclass CompositeBurnRateAlarm extends CompositeAlarm {\n constructor(scope: GuStack, props: CompositeBurnRateAlarmProps) {\n const alarmName = `${props.sloName}${props.burnRateMonitoring.speed}BurnCompositeAlarm`;\n const sharedIndividualAlarmProps = {\n badEvents: props.badEvents,\n burnRateSpeed: {\n speed: props.burnRateMonitoring.speed,\n burnRate: props.burnRateMonitoring.burnRate,\n },\n errorBudget: props.errorBudget,\n validEvents: props.validEvents,\n };\n super(scope, alarmName, {\n alarmRule: AlarmRule.allOf(\n AlarmRule.fromAlarm(\n new MonitorBurnRateForPeriod(scope, {\n ...sharedIndividualAlarmProps,\n alarmName: `ChildAlarmLongPeriod${alarmName}`,\n period: props.burnRateMonitoring.longPeriod,\n }),\n AlarmState.ALARM\n ),\n AlarmRule.fromAlarm(\n new MonitorBurnRateForPeriod(scope, {\n ...sharedIndividualAlarmProps,\n alarmName: `ChildAlarmShortPeriod${alarmName}`,\n period: props.burnRateMonitoring.shortPeriod,\n }),\n AlarmState.ALARM\n )\n ),\n });\n this.addAlarmAction(new SnsAction(props.snsTopic));\n if (props.suppressorAlarm) {\n const cfnAlarm = this.node.defaultChild as CfnCompositeAlarm;\n cfnAlarm.actionsSuppressor = props.suppressorAlarm.alarmArn;\n cfnAlarm.actionsSuppressorWaitPeriod = 120;\n cfnAlarm.actionsSuppressorExtensionPeriod = props.burnRateMonitoring.shortPeriod.toSeconds();\n }\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/experimental/constructs/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,QAAQ,CAAC"}
|
|
@@ -14,5 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./
|
|
17
|
+
__exportStar(require("./error-budget-alarm"), exports);
|
|
18
|
+
__exportStar(require("./root"), exports);
|
|
18
19
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/experimental/constructs/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uDAAqC;AACrC,yCAAuB","sourcesContent":["export * from \"./error-budget-alarm\";\nexport * from \"./root\";\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;
|
|
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"}
|
|
@@ -6,7 +6,6 @@ const aws_lambda_event_sources_1 = require("aws-cdk-lib/aws-lambda-event-sources
|
|
|
6
6
|
const aws_sns_1 = require("aws-cdk-lib/aws-sns");
|
|
7
7
|
const core_1 = require("../../constructs/core");
|
|
8
8
|
const lambda_1 = require("../../constructs/lambda");
|
|
9
|
-
const sns_1 = require("../../constructs/sns");
|
|
10
9
|
/**
|
|
11
10
|
* Pattern which creates all of the resources needed to invoke a lambda function whenever a message
|
|
12
11
|
* is published onto an SNS topic.
|
|
@@ -30,7 +29,7 @@ class GuSnsLambdaExperimental extends lambda_1.GuLambdaFunction {
|
|
|
30
29
|
const { existingSnsTopic } = props;
|
|
31
30
|
this.snsTopic = existingSnsTopic
|
|
32
31
|
? aws_sns_1.Topic.fromTopicArn(scope, `${id}-SnsExistingIncomingEventsTopic`, `arn:aws:sns:${region}:${account}:${existingSnsTopic.externalTopicName}`)
|
|
33
|
-
: core_1.AppIdentity.taggedConstruct(props, new
|
|
32
|
+
: core_1.AppIdentity.taggedConstruct(props, new aws_sns_1.Topic(scope, "SnsIncomingEventsTopic"));
|
|
34
33
|
this.addEventSource(new aws_lambda_event_sources_1.SnsEventSource(this.snsTopic));
|
|
35
34
|
new aws_cdk_lib_1.CfnOutput(this, "TopicName", { value: this.snsTopic.topicName });
|
|
36
35
|
}
|
|
@@ -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;
|
|
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"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { GuS3OriginBucket } from "../../../constructs/s3";
|
|
2
|
+
import type { RiffRaffDeployment } from "../types";
|
|
3
|
+
export declare function uploadStaticFilesDeployment(stages: string[], originBucket: GuS3OriginBucket, { name: cfnDeployName }: RiffRaffDeployment): RiffRaffDeployment;
|
|
4
|
+
//# sourceMappingURL=s3.d.ts.map
|