@guardian/cdk 62.6.1 → 63.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/constructs/core/stack.d.ts +9 -0
- package/lib/constructs/core/stack.d.ts.map +1 -1
- package/lib/constructs/core/stack.js +5 -1
- package/lib/constructs/core/stack.js.map +1 -1
- package/lib/riff-raff-yaml-file/group-by.d.ts +6 -2
- package/lib/riff-raff-yaml-file/group-by.d.ts.map +1 -1
- package/lib/riff-raff-yaml-file/group-by.js +9 -13
- package/lib/riff-raff-yaml-file/group-by.js.map +1 -1
- package/lib/riff-raff-yaml-file/index.d.ts +9 -74
- package/lib/riff-raff-yaml-file/index.d.ts.map +1 -1
- package/lib/riff-raff-yaml-file/index.js +142 -185
- package/lib/riff-raff-yaml-file/index.js.map +1 -1
- package/lib/riff-raff-yaml-file/types.d.ts +7 -1
- package/lib/riff-raff-yaml-file/types.d.ts.map +1 -1
- package/lib/riff-raff-yaml-file/types.js +7 -0
- package/lib/riff-raff-yaml-file/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -18,6 +18,14 @@ export interface GuStackProps extends Omit<StackProps, "stackName"> {
|
|
|
18
18
|
* Optional name of the app. If defined, all resources will have an App tag.
|
|
19
19
|
*/
|
|
20
20
|
app?: string;
|
|
21
|
+
/**
|
|
22
|
+
* The name of the Riff-Raff project used to deploy these resources.
|
|
23
|
+
* Used as the value of the `gu:riff-raff-project` tag on all resources.
|
|
24
|
+
* If using {@link GuRoot} or {@link RiffRaffYamlFile}, this value is also used in the location of the generated `riff-raff.yaml`.
|
|
25
|
+
*
|
|
26
|
+
* @see https://github.com/guardian/riffraff-platform
|
|
27
|
+
*/
|
|
28
|
+
riffRaffProjectName?: string;
|
|
21
29
|
/**
|
|
22
30
|
* The AWS CloudFormation stack name (as shown in the AWS CloudFormation UI).
|
|
23
31
|
* @defaultValue the `GU_CFN_STACK_NAME` environment variable
|
|
@@ -66,6 +74,7 @@ export declare class GuStack extends Stack implements StackStageIdentity {
|
|
|
66
74
|
readonly stack: string;
|
|
67
75
|
readonly stage: string;
|
|
68
76
|
readonly app: string | undefined;
|
|
77
|
+
readonly riffRaffProjectName: string | undefined;
|
|
69
78
|
/**
|
|
70
79
|
* The repository name, if it can be determined from the context or the git remote origin url.
|
|
71
80
|
* If it cannot be determined from either of these sources, it will be `undefined`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../../src/constructs/core/stack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAc,UAAU,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAwB,YAAY,EAA0B,KAAK,EAAQ,MAAM,aAAa,CAAC;AACtG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAO7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC;IACjE;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,OAAQ,SAAQ,KAAM,YAAW,kBAAkB;IAC9D,SAAgB,KAAK,EAAE,MAAM,CAAC;IAC9B,SAAgB,KAAK,EAAE,MAAM,CAAC;IAC9B,SAAgB,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../../src/constructs/core/stack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAc,UAAU,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAwB,YAAY,EAA0B,KAAK,EAAQ,MAAM,aAAa,CAAC;AACtG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAO7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC;IACjE;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,OAAQ,SAAQ,KAAM,YAAW,kBAAkB;IAC9D,SAAgB,KAAK,EAAE,MAAM,CAAC;IAC9B,SAAgB,KAAK,EAAE,MAAM,CAAC;IAC9B,SAAgB,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,SAAgB,mBAAmB,EAAE,MAAM,GAAG,SAAS,CAAC;IAExD;;;OAGG;IACH,SAAgB,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAEnD;;;;;;;;;OASG;IACH,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,GAAE,OAAc,GAAG,IAAI;IAM5F;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAK7C;gBAGW,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY;IAmDvD;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IAa3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqDG;IACI,iBAAiB,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,iBAAiB,GAAG,IAAI;CAQhG"}
|
|
@@ -67,7 +67,7 @@ class GuStack extends aws_cdk_lib_1.Stack {
|
|
|
67
67
|
}
|
|
68
68
|
// eslint-disable-next-line custom-rules/valid-constructors -- GuStack is the exception as it must take an App
|
|
69
69
|
constructor(scope, id, props) {
|
|
70
|
-
const { cloudFormationStackName = process.env.GU_CFN_STACK_NAME, stack, stage, app, withoutTags } = props;
|
|
70
|
+
const { cloudFormationStackName = process.env.GU_CFN_STACK_NAME, stack, stage, app, riffRaffProjectName, withoutTags, } = props;
|
|
71
71
|
super(scope, id, {
|
|
72
72
|
...props,
|
|
73
73
|
stackName: cloudFormationStackName,
|
|
@@ -78,6 +78,7 @@ class GuStack extends aws_cdk_lib_1.Stack {
|
|
|
78
78
|
this.stack = stack;
|
|
79
79
|
this.stage = stage.toUpperCase();
|
|
80
80
|
this.app = app;
|
|
81
|
+
this.riffRaffProjectName = riffRaffProjectName;
|
|
81
82
|
this.repositoryName = this.tryGetRepositoryTag();
|
|
82
83
|
if (!withoutTags) {
|
|
83
84
|
this.addTag(constants_1.TrackingTag.Key, constants_1.TrackingTag.Value);
|
|
@@ -86,6 +87,9 @@ class GuStack extends aws_cdk_lib_1.Stack {
|
|
|
86
87
|
if (this.app) {
|
|
87
88
|
this.addTag("App", this.app);
|
|
88
89
|
}
|
|
90
|
+
if (this.riffRaffProjectName) {
|
|
91
|
+
this.addTag("gu:riff-raff-project", this.riffRaffProjectName);
|
|
92
|
+
}
|
|
89
93
|
if (this.repositoryName) {
|
|
90
94
|
this.addTag(constants_1.MetadataKeys.REPOSITORY_NAME, this.repositoryName);
|
|
91
95
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stack.js","sourceRoot":"","sources":["../../../src/constructs/core/stack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { App, CfnElement, StackProps } from \"aws-cdk-lib\";\nimport { Annotations, Aspects, CfnParameter, LegacyStackSynthesizer, Stack, Tags } from \"aws-cdk-lib\";\nimport type { IConstruct } from \"constructs\";\nimport gitUrlParse from \"git-url-parse\";\nimport { CfnIncludeReporter } from \"../../aspects/cfn-include-reporter\";\nimport { CfnParameterReporter } from \"../../aspects/cfn-parameter-reporter\";\nimport { Metadata } from \"../../aspects/metadata\";\nimport { ContextKeys, MetadataKeys, TrackingTag } from \"../../constants\";\nimport { gitRemoteOriginUrl } from \"../../utils/git\";\nimport type { StackStageIdentity } from \"./identity\";\nimport type { GuStaticLogicalId } from \"./migrating\";\n\nexport interface GuStackProps extends Omit<StackProps, \"stackName\"> {\n /**\n * The Guardian stack being used (as defined in your riff-raff.yaml).\n * This will be applied as a tag to all of your resources.\n */\n stack: string;\n\n /**\n * The stage being used (as defined in your riff-raff.yaml).\n * This will be applied as a tag to all of your resources.\n */\n stage: string;\n\n /**\n * Optional name of the app. If defined, all resources will have an App tag.\n */\n app?: string;\n\n /**\n * The AWS CloudFormation stack name (as shown in the AWS CloudFormation UI).\n * @defaultValue the `GU_CFN_STACK_NAME` environment variable\n */\n cloudFormationStackName?: string;\n /**\n * Set this to true to stop the GuStack from tagging all of your AWS resources.\n * This should only be turned on as part of an initial migration from CloudFormation.\n */\n withoutTags?: boolean;\n\n /**\n * Set to disable CDK metadata. Only for internal use (for disabling for some\n * snapshot tests). We rely on tracking data to prioritise future work so\n * please do not override this.\n */\n withoutMetadata?: boolean;\n}\n\n/**\n * GuStack provides the `stack` and `stage` parameters to a template.\n * It also takes the `app` in the constructor.\n *\n * GuStack will add the Stack, Stage and App tags to all resources.\n *\n * GuStack also adds the tag `X-Gu-CDK-Version`.\n * This tag allows us to measure adoption of this library.\n * It's value is the version of guardian/cdk being used, as defined in `package.json`.\n * As a result, the change sets between version numbers will be fairly noisy,\n * as all resources receive a tag update.\n * It is recommended to upgrade the version of @guardian/cdk being used in two steps:\n * 1. Bump the library, apply the tag updates\n * 2. Make any other stack changes\n *\n * Typical usage is to extend GuStack:\n *\n * ```typescript\n * class MyStack extends GuStack {\n * constructor(scope: App, id: string, props: GuStackProps) {\n * super(scope, id, props)\n * }\n *\n * // add resources here\n * }\n * ```\n */\nexport class GuStack extends Stack implements StackStageIdentity {\n public readonly stack: string;\n public readonly stage: string;\n public readonly app: string | undefined;\n\n /**\n * The repository name, if it can be determined from the context or the git remote origin url.\n * If it cannot be determined from either of these sources, it will be `undefined`.\n */\n public readonly repositoryName: string | undefined;\n\n /**\n * A helper function to add a tag to all resources in a stack.\n *\n * Note: tags will be listed in alphabetical order during synthesis.\n *\n * @param key the tag name\n * @param value the value of the tag\n * @param applyToLaunchedInstances whether or not to apply the tag to instances launched in an ASG.\n * @protected\n */\n protected addTag(key: string, value: string, applyToLaunchedInstances: boolean = true): void {\n // TODO add validation for `key` and `value`\n // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html\n Tags.of(this).add(key, value, { applyToLaunchedInstances });\n }\n\n /**\n * Returns all the parameters on this stack.\n *\n * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html\n */\n get parameters(): Record<string, CfnParameter> {\n return this.node\n .findAll()\n .filter((construct) => construct instanceof CfnParameter)\n .reduce((acc, param) => ({ ...acc, [param.node.id]: param as CfnParameter }), {});\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- GuStack is the exception as it must take an App\n constructor(scope: App, id: string, props: GuStackProps) {\n const { cloudFormationStackName = process.env.GU_CFN_STACK_NAME, stack, stage, app, withoutTags } = props;\n\n super(scope, id, {\n ...props,\n stackName: cloudFormationStackName,\n\n // TODO Use `DefaultStackSynthesizer` or create own synthesizer?\n // see https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html#bootstrapping-custom-synth\n synthesizer: new LegacyStackSynthesizer(),\n });\n\n this.stack = stack;\n this.stage = stage.toUpperCase();\n this.app = app;\n this.repositoryName = this.tryGetRepositoryTag();\n\n if (!withoutTags) {\n this.addTag(TrackingTag.Key, TrackingTag.Value);\n\n this.addTag(\"Stack\", this.stack);\n this.addTag(\"Stage\", this.stage);\n if (this.app) {\n this.addTag(\"App\", this.app);\n }\n\n if (this.repositoryName) {\n this.addTag(MetadataKeys.REPOSITORY_NAME, this.repositoryName);\n }\n }\n\n if (!props.withoutMetadata) {\n Aspects.of(this).add(new Metadata(this));\n }\n\n Aspects.of(this).add(new CfnIncludeReporter());\n Aspects.of(this).add(new CfnParameterReporter());\n }\n\n /**\n * Returns the repository name.\n * The value is retrieved in the following order:\n * 1. From the context\n * 2. From git config\n *\n * @private\n */\n private tryGetRepositoryTag(): string | undefined {\n try {\n const urlFromContext = this.node.tryGetContext(ContextKeys.REPOSITORY_URL) as string | undefined;\n const repositoryUrl: string = urlFromContext ?? gitRemoteOriginUrl();\n return gitUrlParse(repositoryUrl).full_name;\n } catch {\n console.info(\n `Unable to find git repository name. Set the ${ContextKeys.REPOSITORY_URL} context value or configure a git remote`,\n );\n return undefined;\n }\n }\n\n /**\n * Override the auto-generated logical ID for a resource, in the generated CloudFormation template, with a static one.\n *\n * Of particular use when migrating a JSON/YAML CloudFormation template into GuCDK.\n * It's generally advised to retain the logical ID for stateful resources, such as databases or buckets.\n *\n * Let's say we have a YAML template:\n *\n * ```yaml\n * AWSTemplateFormatVersion: '2010-09-09'\n * Resources:\n * UsesTable:\n * Type: AWS::DynamoDB::Table\n * Properties:\n * TableName: !Sub 'users-${stage}'\n * ```\n *\n * When moving to GuCDK we'll have this:\n *\n * class MyStack extends GuStack {\n * constructor(app: App, id: string, props: GuStackProps) {\n * super(app, id, props);\n *\n * const { stage } = this;\n *\n * new Table(this, \"UsersTable\", {\n * name: `users-${stage}`\n * });\n * }\n * }\n *\n * During synthesis, CDK auto-generates logical IDs, so we'll have a stack with a DynamoDB table named 'UsersTable<SOME GUID>', NOT `UsersTable`.\n * That is, the `UsersTable` table will be deleted.\n *\n * In order to retain the original ID from the YAML template, we will do:\n *\n * class MyStack extends GuStack {\n * constructor(app: App, id: string, props: GuStackProps) {\n * super(app, id, props);\n *\n * const { stage } = this;\n *\n * const table = new Table(this, \"UsersTable\", {\n * name: `users-${stage}`\n * });\n *\n * this.overrideLogicalId(table, { logicalId: \"UsersTable\", reason: \"Retaining a stateful resource from the YAML template\" });\n * }\n * }\n *\n * @param construct The (stateful) resource to retain the logical ID of.\n * @param logicalId The logical ID of the resource (as defined in the JSON/YAML template.\n * @param reason A small explanation to keep the logical ID. Mainly used to help future developers.\n */\n public overrideLogicalId(construct: IConstruct, { logicalId, reason }: GuStaticLogicalId): void {\n const {\n node: { id, defaultChild },\n } = construct;\n\n (defaultChild as CfnElement).overrideLogicalId(logicalId);\n Annotations.of(construct).addInfo(`Setting logical ID for ${id} to ${logicalId}. Reason: ${reason}`);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stack.js","sourceRoot":"","sources":["../../../src/constructs/core/stack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { App, CfnElement, StackProps } from \"aws-cdk-lib\";\nimport { Annotations, Aspects, CfnParameter, LegacyStackSynthesizer, Stack, Tags } from \"aws-cdk-lib\";\nimport type { IConstruct } from \"constructs\";\nimport gitUrlParse from \"git-url-parse\";\nimport { CfnIncludeReporter } from \"../../aspects/cfn-include-reporter\";\nimport { CfnParameterReporter } from \"../../aspects/cfn-parameter-reporter\";\nimport { Metadata } from \"../../aspects/metadata\";\nimport { ContextKeys, MetadataKeys, TrackingTag } from \"../../constants\";\nimport { gitRemoteOriginUrl } from \"../../utils/git\";\nimport type { StackStageIdentity } from \"./identity\";\nimport type { GuStaticLogicalId } from \"./migrating\";\n\nexport interface GuStackProps extends Omit<StackProps, \"stackName\"> {\n /**\n * The Guardian stack being used (as defined in your riff-raff.yaml).\n * This will be applied as a tag to all of your resources.\n */\n stack: string;\n\n /**\n * The stage being used (as defined in your riff-raff.yaml).\n * This will be applied as a tag to all of your resources.\n */\n stage: string;\n\n /**\n * Optional name of the app. If defined, all resources will have an App tag.\n */\n app?: string;\n\n /**\n * The name of the Riff-Raff project used to deploy these resources.\n * Used as the value of the `gu:riff-raff-project` tag on all resources.\n * If using {@link GuRoot} or {@link RiffRaffYamlFile}, this value is also used in the location of the generated `riff-raff.yaml`.\n *\n * @see https://github.com/guardian/riffraff-platform\n */\n riffRaffProjectName?: string;\n\n /**\n * The AWS CloudFormation stack name (as shown in the AWS CloudFormation UI).\n * @defaultValue the `GU_CFN_STACK_NAME` environment variable\n */\n cloudFormationStackName?: string;\n /**\n * Set this to true to stop the GuStack from tagging all of your AWS resources.\n * This should only be turned on as part of an initial migration from CloudFormation.\n */\n withoutTags?: boolean;\n\n /**\n * Set to disable CDK metadata. Only for internal use (for disabling for some\n * snapshot tests). We rely on tracking data to prioritise future work so\n * please do not override this.\n */\n withoutMetadata?: boolean;\n}\n\n/**\n * GuStack provides the `stack` and `stage` parameters to a template.\n * It also takes the `app` in the constructor.\n *\n * GuStack will add the Stack, Stage and App tags to all resources.\n *\n * GuStack also adds the tag `X-Gu-CDK-Version`.\n * This tag allows us to measure adoption of this library.\n * It's value is the version of guardian/cdk being used, as defined in `package.json`.\n * As a result, the change sets between version numbers will be fairly noisy,\n * as all resources receive a tag update.\n * It is recommended to upgrade the version of @guardian/cdk being used in two steps:\n * 1. Bump the library, apply the tag updates\n * 2. Make any other stack changes\n *\n * Typical usage is to extend GuStack:\n *\n * ```typescript\n * class MyStack extends GuStack {\n * constructor(scope: App, id: string, props: GuStackProps) {\n * super(scope, id, props)\n * }\n *\n * // add resources here\n * }\n * ```\n */\nexport class GuStack extends Stack implements StackStageIdentity {\n public readonly stack: string;\n public readonly stage: string;\n public readonly app: string | undefined;\n public readonly riffRaffProjectName: string | undefined;\n\n /**\n * The repository name, if it can be determined from the context or the git remote origin url.\n * If it cannot be determined from either of these sources, it will be `undefined`.\n */\n public readonly repositoryName: string | undefined;\n\n /**\n * A helper function to add a tag to all resources in a stack.\n *\n * Note: tags will be listed in alphabetical order during synthesis.\n *\n * @param key the tag name\n * @param value the value of the tag\n * @param applyToLaunchedInstances whether or not to apply the tag to instances launched in an ASG.\n * @protected\n */\n protected addTag(key: string, value: string, applyToLaunchedInstances: boolean = true): void {\n // TODO add validation for `key` and `value`\n // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html\n Tags.of(this).add(key, value, { applyToLaunchedInstances });\n }\n\n /**\n * Returns all the parameters on this stack.\n *\n * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html\n */\n get parameters(): Record<string, CfnParameter> {\n return this.node\n .findAll()\n .filter((construct) => construct instanceof CfnParameter)\n .reduce((acc, param) => ({ ...acc, [param.node.id]: param as CfnParameter }), {});\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- GuStack is the exception as it must take an App\n constructor(scope: App, id: string, props: GuStackProps) {\n const {\n cloudFormationStackName = process.env.GU_CFN_STACK_NAME,\n stack,\n stage,\n app,\n riffRaffProjectName,\n withoutTags,\n } = props;\n\n super(scope, id, {\n ...props,\n stackName: cloudFormationStackName,\n\n // TODO Use `DefaultStackSynthesizer` or create own synthesizer?\n // see https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html#bootstrapping-custom-synth\n synthesizer: new LegacyStackSynthesizer(),\n });\n\n this.stack = stack;\n this.stage = stage.toUpperCase();\n this.app = app;\n this.riffRaffProjectName = riffRaffProjectName;\n this.repositoryName = this.tryGetRepositoryTag();\n\n if (!withoutTags) {\n this.addTag(TrackingTag.Key, TrackingTag.Value);\n\n this.addTag(\"Stack\", this.stack);\n this.addTag(\"Stage\", this.stage);\n if (this.app) {\n this.addTag(\"App\", this.app);\n }\n\n if (this.riffRaffProjectName) {\n this.addTag(\"gu:riff-raff-project\", this.riffRaffProjectName);\n }\n\n if (this.repositoryName) {\n this.addTag(MetadataKeys.REPOSITORY_NAME, this.repositoryName);\n }\n }\n\n if (!props.withoutMetadata) {\n Aspects.of(this).add(new Metadata(this));\n }\n\n Aspects.of(this).add(new CfnIncludeReporter());\n Aspects.of(this).add(new CfnParameterReporter());\n }\n\n /**\n * Returns the repository name.\n * The value is retrieved in the following order:\n * 1. From the context\n * 2. From git config\n *\n * @private\n */\n private tryGetRepositoryTag(): string | undefined {\n try {\n const urlFromContext = this.node.tryGetContext(ContextKeys.REPOSITORY_URL) as string | undefined;\n const repositoryUrl: string = urlFromContext ?? gitRemoteOriginUrl();\n return gitUrlParse(repositoryUrl).full_name;\n } catch {\n console.info(\n `Unable to find git repository name. Set the ${ContextKeys.REPOSITORY_URL} context value or configure a git remote`,\n );\n return undefined;\n }\n }\n\n /**\n * Override the auto-generated logical ID for a resource, in the generated CloudFormation template, with a static one.\n *\n * Of particular use when migrating a JSON/YAML CloudFormation template into GuCDK.\n * It's generally advised to retain the logical ID for stateful resources, such as databases or buckets.\n *\n * Let's say we have a YAML template:\n *\n * ```yaml\n * AWSTemplateFormatVersion: '2010-09-09'\n * Resources:\n * UsesTable:\n * Type: AWS::DynamoDB::Table\n * Properties:\n * TableName: !Sub 'users-${stage}'\n * ```\n *\n * When moving to GuCDK we'll have this:\n *\n * class MyStack extends GuStack {\n * constructor(app: App, id: string, props: GuStackProps) {\n * super(app, id, props);\n *\n * const { stage } = this;\n *\n * new Table(this, \"UsersTable\", {\n * name: `users-${stage}`\n * });\n * }\n * }\n *\n * During synthesis, CDK auto-generates logical IDs, so we'll have a stack with a DynamoDB table named 'UsersTable<SOME GUID>', NOT `UsersTable`.\n * That is, the `UsersTable` table will be deleted.\n *\n * In order to retain the original ID from the YAML template, we will do:\n *\n * class MyStack extends GuStack {\n * constructor(app: App, id: string, props: GuStackProps) {\n * super(app, id, props);\n *\n * const { stage } = this;\n *\n * const table = new Table(this, \"UsersTable\", {\n * name: `users-${stage}`\n * });\n *\n * this.overrideLogicalId(table, { logicalId: \"UsersTable\", reason: \"Retaining a stateful resource from the YAML template\" });\n * }\n * }\n *\n * @param construct The (stateful) resource to retain the logical ID of.\n * @param logicalId The logical ID of the resource (as defined in the JSON/YAML template.\n * @param reason A small explanation to keep the logical ID. Mainly used to help future developers.\n */\n public overrideLogicalId(construct: IConstruct, { logicalId, reason }: GuStaticLogicalId): void {\n const {\n node: { id, defaultChild },\n } = construct;\n\n (defaultChild as CfnElement).overrideLogicalId(logicalId);\n Annotations.of(construct).addInfo(`Setting logical ID for ${id} to ${logicalId}. Reason: ${reason}`);\n }\n}\n"]}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { GuStack } from "../constructs/core";
|
|
2
|
-
import type {
|
|
3
|
-
export declare function
|
|
2
|
+
import type { ClassName, Region, RiffRaffProjectName, StackTag, StageTag } from "./types";
|
|
3
|
+
export declare function groupByClassName(cdkStacks: GuStack[]): Record<ClassName, GuStack[]>;
|
|
4
|
+
export declare function groupByStackTag(cdkStacks: GuStack[]): Record<StackTag, GuStack[]>;
|
|
5
|
+
export declare function groupByStageTag(cdkStacks: GuStack[]): Record<StageTag, GuStack[]>;
|
|
6
|
+
export declare function groupByRegion(cdkStacks: GuStack[]): Record<Region, GuStack[]>;
|
|
7
|
+
export declare function groupByRiffRaffProjectName(cdkStacks: GuStack[]): Record<RiffRaffProjectName, GuStack[]>;
|
|
4
8
|
//# sourceMappingURL=group-by.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group-by.d.ts","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/group-by.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"group-by.d.ts","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/group-by.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,mBAAmB,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAG1F,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAEnF;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAEjF;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAEjF;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAE7E;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,mBAAmB,EAAE,OAAO,EAAE,CAAC,CAEvG"}
|
|
@@ -1,30 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.groupByRiffRaffProjectName = exports.groupByRegion = exports.groupByStageTag = exports.groupByStackTag = exports.groupByClassName = void 0;
|
|
4
4
|
const array_1 = require("../utils/array");
|
|
5
|
+
const types_1 = require("./types");
|
|
5
6
|
function groupByClassName(cdkStacks) {
|
|
6
7
|
return (0, array_1.groupBy)(cdkStacks, (stack) => stack.constructor.name);
|
|
7
8
|
}
|
|
9
|
+
exports.groupByClassName = groupByClassName;
|
|
8
10
|
function groupByStackTag(cdkStacks) {
|
|
9
11
|
return (0, array_1.groupBy)(cdkStacks, ({ stack }) => stack);
|
|
10
12
|
}
|
|
13
|
+
exports.groupByStackTag = groupByStackTag;
|
|
11
14
|
function groupByStageTag(cdkStacks) {
|
|
12
15
|
return (0, array_1.groupBy)(cdkStacks, ({ stage }) => stage);
|
|
13
16
|
}
|
|
17
|
+
exports.groupByStageTag = groupByStageTag;
|
|
14
18
|
function groupByRegion(cdkStacks) {
|
|
15
19
|
return (0, array_1.groupBy)(cdkStacks, ({ region }) => region);
|
|
16
20
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
[className]: Object.entries(groupByStackTag(stacksGroupedByClassName)).reduce((accStackTag, [stackTag, stacksGroupedByStackTag]) => ({
|
|
21
|
-
...accStackTag,
|
|
22
|
-
[stackTag]: Object.entries(groupByRegion(stacksGroupedByStackTag)).reduce((accRegion, [region, stacksGroupedByRegion]) => ({
|
|
23
|
-
...accRegion,
|
|
24
|
-
[region]: groupByStageTag(stacksGroupedByRegion),
|
|
25
|
-
}), {}),
|
|
26
|
-
}), {}),
|
|
27
|
-
}), {});
|
|
21
|
+
exports.groupByRegion = groupByRegion;
|
|
22
|
+
function groupByRiffRaffProjectName(cdkStacks) {
|
|
23
|
+
return (0, array_1.groupBy)(cdkStacks, (_) => _.riffRaffProjectName ?? types_1.UnknownRiffRaffProjectName);
|
|
28
24
|
}
|
|
29
|
-
exports.
|
|
25
|
+
exports.groupByRiffRaffProjectName = groupByRiffRaffProjectName;
|
|
30
26
|
//# sourceMappingURL=group-by.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group-by.js","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/group-by.ts"],"names":[],"mappings":";;;AACA,0CAAyC;
|
|
1
|
+
{"version":3,"file":"group-by.js","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/group-by.ts"],"names":[],"mappings":";;;AACA,0CAAyC;AAEzC,mCAAqD;AAErD,SAAgB,gBAAgB,CAAC,SAAoB;IACnD,OAAO,IAAA,eAAO,EAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AAC/D,CAAC;AAFD,4CAEC;AAED,SAAgB,eAAe,CAAC,SAAoB;IAClD,OAAO,IAAA,eAAO,EAAC,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC;AAFD,0CAEC;AAED,SAAgB,eAAe,CAAC,SAAoB;IAClD,OAAO,IAAA,eAAO,EAAC,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC;AAFD,0CAEC;AAED,SAAgB,aAAa,CAAC,SAAoB;IAChD,OAAO,IAAA,eAAO,EAAC,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;AACpD,CAAC;AAFD,sCAEC;AAED,SAAgB,0BAA0B,CAAC,SAAoB;IAC7D,OAAO,IAAA,eAAO,EAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,mBAAmB,IAAI,kCAA0B,CAAC,CAAC;AACxF,CAAC;AAFD,gEAEC","sourcesContent":["import type { GuStack } from \"../constructs/core\";\nimport { groupBy } from \"../utils/array\";\nimport type { ClassName, Region, RiffRaffProjectName, StackTag, StageTag } from \"./types\";\nimport { UnknownRiffRaffProjectName } from \"./types\";\n\nexport function groupByClassName(cdkStacks: GuStack[]): Record<ClassName, GuStack[]> {\n return groupBy(cdkStacks, (stack) => stack.constructor.name);\n}\n\nexport function groupByStackTag(cdkStacks: GuStack[]): Record<StackTag, GuStack[]> {\n return groupBy(cdkStacks, ({ stack }) => stack);\n}\n\nexport function groupByStageTag(cdkStacks: GuStack[]): Record<StageTag, GuStack[]> {\n return groupBy(cdkStacks, ({ stage }) => stage);\n}\n\nexport function groupByRegion(cdkStacks: GuStack[]): Record<Region, GuStack[]> {\n return groupBy(cdkStacks, ({ region }) => region);\n}\n\nexport function groupByRiffRaffProjectName(cdkStacks: GuStack[]): Record<RiffRaffProjectName, GuStack[]> {\n return groupBy(cdkStacks, (_) => _.riffRaffProjectName ?? UnknownRiffRaffProjectName);\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { App } from "aws-cdk-lib";
|
|
2
|
-
import type { RiffRaffYaml } from "./types";
|
|
2
|
+
import type { RiffRaffProjectName, RiffRaffYaml } from "./types";
|
|
3
3
|
/**
|
|
4
4
|
* A class that creates a `riff-raff.yaml` file.
|
|
5
5
|
*
|
|
@@ -44,93 +44,28 @@ import type { RiffRaffYaml } from "./types";
|
|
|
44
44
|
* @see https://riffraff.gutools.co.uk/docs/magenta-lib/types
|
|
45
45
|
*/
|
|
46
46
|
export declare class RiffRaffYamlFile {
|
|
47
|
-
private readonly allCdkStacks;
|
|
48
|
-
private readonly allStackTags;
|
|
49
|
-
private readonly allStageTags;
|
|
50
|
-
private readonly allRegions;
|
|
51
47
|
private readonly outdir;
|
|
52
48
|
/**
|
|
53
|
-
*
|
|
49
|
+
* A mapping between a Riff-Raff project and `riff-raff.yaml` content as an object.
|
|
54
50
|
*
|
|
55
51
|
* It is useful for specifying additional deployment types that GuCDK does not support.
|
|
56
52
|
* Consider raising an issue or pull request if you think it should be supported.
|
|
57
53
|
*
|
|
58
|
-
* In most cases, you shouldn't need to access this.
|
|
59
|
-
* No validation is performed on the parameters you provide, so you might get deployment errors.
|
|
60
|
-
*
|
|
61
54
|
* @see https://riffraff.gutools.co.uk/docs/magenta-lib/types
|
|
62
55
|
*/
|
|
63
|
-
readonly
|
|
64
|
-
private isCdkStackPresent;
|
|
65
|
-
/**
|
|
66
|
-
* Check there are the appropriate number of `GuStack`s.
|
|
67
|
-
* Expect to find an instance for each combination of `stack`, and `stage`.
|
|
68
|
-
*
|
|
69
|
-
* If not valid, a message is logged describing what is missing to aid debugging.
|
|
70
|
-
*
|
|
71
|
-
* Given the following:
|
|
72
|
-
*
|
|
73
|
-
* ```ts
|
|
74
|
-
* const app = new App();
|
|
75
|
-
*
|
|
76
|
-
* class MyApplicationStack extends GuStack { }
|
|
77
|
-
*
|
|
78
|
-
* new MyApplicationStack(app, "App-CODE-deploy", {
|
|
79
|
-
* env: {
|
|
80
|
-
* region: "eu-west-1",
|
|
81
|
-
* },
|
|
82
|
-
* stack: "deploy",
|
|
83
|
-
* stage: "CODE"
|
|
84
|
-
* });
|
|
85
|
-
*
|
|
86
|
-
* new MyApplicationStack(app, "App-PROD-media-service", {
|
|
87
|
-
* env: {
|
|
88
|
-
* region: "eu-west-1",
|
|
89
|
-
* },
|
|
90
|
-
* stack: "media-service",
|
|
91
|
-
* stage: "PROD",
|
|
92
|
-
* });
|
|
93
|
-
*
|
|
94
|
-
* new MyApplicationStack(app, "App-PROD-deploy", {
|
|
95
|
-
* env: {
|
|
96
|
-
* region: "eu-west-1",
|
|
97
|
-
* },
|
|
98
|
-
* stack: "deploy",
|
|
99
|
-
* stage: "PROD"
|
|
100
|
-
* });
|
|
101
|
-
* ```
|
|
102
|
-
*
|
|
103
|
-
* This will log a message like this, where ❌ denotes something missing,
|
|
104
|
-
* specifically there is no `CODE` template for `media-service`.
|
|
105
|
-
*
|
|
106
|
-
* ```log
|
|
107
|
-
* Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)
|
|
108
|
-
*
|
|
109
|
-
* ┌───────────────┬──────┬──────┐
|
|
110
|
-
* │ (index) │ CODE │ PROD │
|
|
111
|
-
* ├───────────────┼──────┼──────┤
|
|
112
|
-
* │ deploy │ '✅' │ '✅' │
|
|
113
|
-
* │ media-service │ '❌' │ '✅' │
|
|
114
|
-
* └───────────────┴──────┴──────┘
|
|
115
|
-
* ```
|
|
116
|
-
*
|
|
117
|
-
* @private
|
|
118
|
-
*/
|
|
119
|
-
private validateStacksInApp;
|
|
120
|
-
private validateAllRegionsAreResolved;
|
|
121
|
-
private getLambdas;
|
|
122
|
-
private getAutoScalingGroups;
|
|
123
|
-
private getGuStackDependencies;
|
|
56
|
+
readonly configuration: Map<RiffRaffProjectName, RiffRaffYaml>;
|
|
124
57
|
constructor(app: App);
|
|
125
58
|
/**
|
|
126
|
-
*
|
|
59
|
+
* A `riff-raff.yaml` file as a string.
|
|
127
60
|
* Useful for testing.
|
|
61
|
+
*
|
|
62
|
+
* @param riffRaffProjectName which project to convert to YAML. Defaults to {@link UnknownRiffRaffProjectName} - any {@link GuStack} without an explicit `riffRaffProjectName` property.
|
|
128
63
|
*/
|
|
129
|
-
toYAML(): string;
|
|
64
|
+
toYAML(riffRaffProjectName?: RiffRaffProjectName): string;
|
|
130
65
|
/**
|
|
131
|
-
* Write the `riff-raff.yaml` file to disk
|
|
132
|
-
* It'll be located with the CFN JSON templates generated by `cdk synth`.
|
|
66
|
+
* Write the `riff-raff.yaml` file(s) to disk, located in the same directory as the CFN JSON templates generated by `cdk synth`.
|
|
133
67
|
*/
|
|
134
68
|
synth(): void;
|
|
135
69
|
}
|
|
70
|
+
export declare function validateRiffRaffYamlDirectory(basePath: string, riffRaffProjectName: RiffRaffProjectName): string;
|
|
136
71
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAuBvC,OAAO,KAAK,EAMV,mBAAmB,EACnB,YAAY,EAGb,MAAM,SAAS,CAAC;AA+BjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;;;OAOG;IACH,SAAgB,aAAa,EAAE,GAAG,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;gBAG1D,GAAG,EAAE,GAAG;IA6IpB;;;;;OAKG;IACH,MAAM,CAAC,mBAAmB,GAAE,mBAAgD,GAAG,MAAM;IAuBrF;;OAEG;IACH,KAAK,IAAI,IAAI;CAed;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,GAAG,MAAM,CAahH"}
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.RiffRaffYamlFile = void 0;
|
|
6
|
+
exports.validateRiffRaffYamlDirectory = exports.RiffRaffYamlFile = void 0;
|
|
7
7
|
const fs_1 = require("fs");
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
@@ -17,6 +17,22 @@ const cloudformation_1 = require("./deployments/cloudformation");
|
|
|
17
17
|
const lambda_2 = require("./deployments/lambda");
|
|
18
18
|
const update_parameters_1 = require("./deployments/update-parameters");
|
|
19
19
|
const group_by_1 = require("./group-by");
|
|
20
|
+
const types_1 = require("./types");
|
|
21
|
+
function validateAllRegionsAreResolved(regions) {
|
|
22
|
+
const unresolved = regions.filter((region) => aws_cdk_lib_1.Token.isUnresolved(region));
|
|
23
|
+
if (unresolved.length !== 0) {
|
|
24
|
+
throw new Error(`Unable to produce a working riff-raff.yaml file; all stacks must have an explicit region set`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function getLambdas(cdkStack) {
|
|
28
|
+
return cdkStack.node.findAll().filter((_) => _ instanceof lambda_1.GuLambdaFunction);
|
|
29
|
+
}
|
|
30
|
+
function getAutoScalingGroups(cdkStack) {
|
|
31
|
+
return cdkStack.node.findAll().filter((_) => _ instanceof autoscaling_1.GuAutoScalingGroup);
|
|
32
|
+
}
|
|
33
|
+
function getGuStackDependencies(cdkStack) {
|
|
34
|
+
return cdkStack.dependencies.filter((_) => _ instanceof core_1.GuStack);
|
|
35
|
+
}
|
|
20
36
|
/**
|
|
21
37
|
* A class that creates a `riff-raff.yaml` file.
|
|
22
38
|
*
|
|
@@ -61,198 +77,117 @@ const group_by_1 = require("./group-by");
|
|
|
61
77
|
* @see https://riffraff.gutools.co.uk/docs/magenta-lib/types
|
|
62
78
|
*/
|
|
63
79
|
class RiffRaffYamlFile {
|
|
64
|
-
isCdkStackPresent(expectedStack, expectedStage) {
|
|
65
|
-
const matches = this.allCdkStacks.find((cdkStack) => {
|
|
66
|
-
const { stack, stage } = cdkStack;
|
|
67
|
-
return stack === expectedStack && stage === expectedStage;
|
|
68
|
-
});
|
|
69
|
-
return !!matches;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Check there are the appropriate number of `GuStack`s.
|
|
73
|
-
* Expect to find an instance for each combination of `stack`, and `stage`.
|
|
74
|
-
*
|
|
75
|
-
* If not valid, a message is logged describing what is missing to aid debugging.
|
|
76
|
-
*
|
|
77
|
-
* Given the following:
|
|
78
|
-
*
|
|
79
|
-
* ```ts
|
|
80
|
-
* const app = new App();
|
|
81
|
-
*
|
|
82
|
-
* class MyApplicationStack extends GuStack { }
|
|
83
|
-
*
|
|
84
|
-
* new MyApplicationStack(app, "App-CODE-deploy", {
|
|
85
|
-
* env: {
|
|
86
|
-
* region: "eu-west-1",
|
|
87
|
-
* },
|
|
88
|
-
* stack: "deploy",
|
|
89
|
-
* stage: "CODE"
|
|
90
|
-
* });
|
|
91
|
-
*
|
|
92
|
-
* new MyApplicationStack(app, "App-PROD-media-service", {
|
|
93
|
-
* env: {
|
|
94
|
-
* region: "eu-west-1",
|
|
95
|
-
* },
|
|
96
|
-
* stack: "media-service",
|
|
97
|
-
* stage: "PROD",
|
|
98
|
-
* });
|
|
99
|
-
*
|
|
100
|
-
* new MyApplicationStack(app, "App-PROD-deploy", {
|
|
101
|
-
* env: {
|
|
102
|
-
* region: "eu-west-1",
|
|
103
|
-
* },
|
|
104
|
-
* stack: "deploy",
|
|
105
|
-
* stage: "PROD"
|
|
106
|
-
* });
|
|
107
|
-
* ```
|
|
108
|
-
*
|
|
109
|
-
* This will log a message like this, where ❌ denotes something missing,
|
|
110
|
-
* specifically there is no `CODE` template for `media-service`.
|
|
111
|
-
*
|
|
112
|
-
* ```log
|
|
113
|
-
* Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)
|
|
114
|
-
*
|
|
115
|
-
* ┌───────────────┬──────┬──────┐
|
|
116
|
-
* │ (index) │ CODE │ PROD │
|
|
117
|
-
* ├───────────────┼──────┼──────┤
|
|
118
|
-
* │ deploy │ '✅' │ '✅' │
|
|
119
|
-
* │ media-service │ '❌' │ '✅' │
|
|
120
|
-
* └───────────────┴──────┴──────┘
|
|
121
|
-
* ```
|
|
122
|
-
*
|
|
123
|
-
* @private
|
|
124
|
-
*/
|
|
125
|
-
validateStacksInApp() {
|
|
126
|
-
const { allStackTags, allStageTags } = this;
|
|
127
|
-
const checks = allStackTags.reduce((accStackTag, stackTag) => {
|
|
128
|
-
return {
|
|
129
|
-
...accStackTag,
|
|
130
|
-
[stackTag]: allStageTags.reduce((accStageTag, stageTag) => {
|
|
131
|
-
return {
|
|
132
|
-
...accStageTag,
|
|
133
|
-
[stageTag]: this.isCdkStackPresent(stackTag, stageTag) ? "✅" : "❌",
|
|
134
|
-
};
|
|
135
|
-
}, {}),
|
|
136
|
-
};
|
|
137
|
-
}, {});
|
|
138
|
-
const missingDefinitions = Object.values(checks).flatMap((groupedByStackTag) => {
|
|
139
|
-
return Object.values(groupedByStackTag).filter((_) => _ === "❌");
|
|
140
|
-
});
|
|
141
|
-
if (missingDefinitions.length > 0) {
|
|
142
|
-
const message = `Unable to produce a working riff-raff.yaml file; missing ${missingDefinitions.length} definitions`;
|
|
143
|
-
console.log(`${message} (details below)`);
|
|
144
|
-
console.table(checks);
|
|
145
|
-
throw new Error(message);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
validateAllRegionsAreResolved() {
|
|
149
|
-
const unresolved = this.allRegions.filter((region) => aws_cdk_lib_1.Token.isUnresolved(region));
|
|
150
|
-
if (unresolved.length !== 0) {
|
|
151
|
-
throw new Error(`Unable to produce a working riff-raff.yaml file; all stacks must have an explicit region set`);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
getLambdas(cdkStack) {
|
|
155
|
-
return cdkStack.node.findAll().filter((_) => _ instanceof lambda_1.GuLambdaFunction);
|
|
156
|
-
}
|
|
157
|
-
getAutoScalingGroups(cdkStack) {
|
|
158
|
-
return cdkStack.node.findAll().filter((_) => _ instanceof autoscaling_1.GuAutoScalingGroup);
|
|
159
|
-
}
|
|
160
|
-
getGuStackDependencies(cdkStack) {
|
|
161
|
-
return cdkStack.dependencies.filter((_) => _ instanceof core_1.GuStack);
|
|
162
|
-
}
|
|
163
80
|
// eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree
|
|
164
81
|
constructor(app) {
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));
|
|
169
|
-
this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));
|
|
170
|
-
this.validateStacksInApp();
|
|
171
|
-
this.validateAllRegionsAreResolved();
|
|
82
|
+
const allCdkStacks = app.node.findAll().filter((_) => _ instanceof core_1.GuStack);
|
|
83
|
+
const allRegions = Array.from(new Set(allCdkStacks.map((_) => _.region)));
|
|
84
|
+
validateAllRegionsAreResolved(allRegions);
|
|
172
85
|
this.outdir = app.outdir;
|
|
173
|
-
const
|
|
174
|
-
const
|
|
175
|
-
Object.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
deployments.set(cfnDeployment.name, cfnDeployment.props);
|
|
194
|
-
const lambdasWithoutAnAlias = lambdas.filter((lambda) => lambda.alias === undefined);
|
|
195
|
-
// If the Lambda has an alias it is using versioning. When using versioning, there is no need for Riff-Raff
|
|
196
|
-
// to modify the unpublished version of the function
|
|
197
|
-
lambdasWithoutAnAlias.forEach((lambda) => {
|
|
198
|
-
const lambdaDeployment = (0, lambda_2.updateLambdaDeployment)(lambda, cfnDeployment);
|
|
199
|
-
deployments.set(lambdaDeployment.name, lambdaDeployment.props);
|
|
200
|
-
});
|
|
201
|
-
/*
|
|
202
|
-
Instances in an ASG with an `AutoScalingRollingUpdate` update policy are rotated via CloudFormation.
|
|
203
|
-
Therefore, they do not need to also perform an `autoscaling` deployment via Riff-Raff.
|
|
204
|
-
*/
|
|
205
|
-
const legacyAutoscalingGroups = autoscalingGroups.filter((asg) => {
|
|
206
|
-
const { cfnOptions } = asg.node.defaultChild;
|
|
207
|
-
const { updatePolicy } = cfnOptions;
|
|
208
|
-
return updatePolicy?.autoScalingRollingUpdate === undefined;
|
|
209
|
-
});
|
|
210
|
-
legacyAutoscalingGroups.forEach((asg) => {
|
|
211
|
-
const asgDeployment = (0, autoscaling_2.autoscalingDeployment)(asg, cfnDeployment);
|
|
212
|
-
deployments.set(asgDeployment.name, asgDeployment.props);
|
|
213
|
-
});
|
|
214
|
-
// only add the `amiParametersToTags` property if there are some ASGs in the stack
|
|
215
|
-
if (autoscalingGroups.length > 0) {
|
|
216
|
-
(0, update_parameters_1.updateDeploymentParameters)(deployments, cfnDeployment, {
|
|
217
|
-
amiParametersToTags: (0, cloudformation_1.getAmiParameters)(autoscalingGroups),
|
|
86
|
+
const configuration = new Map();
|
|
87
|
+
const missingStacks = [];
|
|
88
|
+
Object.entries((0, group_by_1.groupByRiffRaffProjectName)(allCdkStacks)).forEach(([riffRaffProjectName, stacksGroupedByRiffRaffProject]) => {
|
|
89
|
+
const allowedStages = new Set(stacksGroupedByRiffRaffProject.map((_) => _.stage));
|
|
90
|
+
const requiredStages = Array.from(allowedStages);
|
|
91
|
+
const deployments = new Map();
|
|
92
|
+
Object.entries((0, group_by_1.groupByClassName)(stacksGroupedByRiffRaffProject)).forEach(([className, stacksGroupedByClassName]) => {
|
|
93
|
+
Object.entries((0, group_by_1.groupByStackTag)(stacksGroupedByClassName)).forEach(([stackTag, stacksGroupedByStackTag]) => {
|
|
94
|
+
Object.entries((0, group_by_1.groupByRegion)(stacksGroupedByStackTag)).forEach(([region, stacksGroupedByRegion]) => {
|
|
95
|
+
const stacks = Object.values((0, group_by_1.groupByStageTag)(stacksGroupedByRegion)).flat();
|
|
96
|
+
requiredStages.forEach((requiredStage) => {
|
|
97
|
+
if (!stacks.find(({ stage }) => stage === requiredStage)) {
|
|
98
|
+
missingStacks.push({
|
|
99
|
+
riffRaffProjectName,
|
|
100
|
+
className,
|
|
101
|
+
region,
|
|
102
|
+
stack: stackTag,
|
|
103
|
+
stage: requiredStage,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
218
106
|
});
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
This is driven by the presence of conditionally added CFN Parameters.
|
|
224
|
-
To support the possibility of there being a scaling policy in PROD but not CODE, look at all the CFN Parameters in `stacks`.
|
|
225
|
-
*/
|
|
226
|
-
const minInstancesInServiceParameters = stacks
|
|
227
|
-
.flatMap((stack) => Object.values(stack.parameters))
|
|
228
|
-
.filter((_) => _ instanceof ec2_app_1.GuAsgMinInstancesInServiceParameterExperimental)
|
|
229
|
-
.reduce((acc, item) => {
|
|
230
|
-
if (!acc.has(item.node.id)) {
|
|
231
|
-
acc.set(item.node.id, item);
|
|
107
|
+
// The items in `stacks` only differ by stage, so we can just use the first item in the list.
|
|
108
|
+
const [stack] = stacks;
|
|
109
|
+
if (!stack) {
|
|
110
|
+
throw new Error("Unable to produce a working riff-raff.yaml file; there are no stacks!");
|
|
232
111
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
(
|
|
240
|
-
|
|
112
|
+
const lambdas = getLambdas(stack);
|
|
113
|
+
const autoscalingGroups = getAutoScalingGroups(stack);
|
|
114
|
+
const artifactUploads = [
|
|
115
|
+
lambdas.filter((_) => !_.withoutArtifactUpload).map(lambda_2.uploadLambdaArtifact),
|
|
116
|
+
autoscalingGroups.map(autoscaling_2.uploadAutoscalingArtifact),
|
|
117
|
+
].flat();
|
|
118
|
+
artifactUploads.forEach(({ name, props }) => deployments.set(name, props));
|
|
119
|
+
const parentStacks = getGuStackDependencies(stack).map((x) => (0, cloudformation_1.cloudFormationDeployment)([x], [], this.outdir));
|
|
120
|
+
const cfnDeployment = (0, cloudformation_1.cloudFormationDeployment)(stacks, [...artifactUploads, ...parentStacks], this.outdir);
|
|
121
|
+
deployments.set(cfnDeployment.name, cfnDeployment.props);
|
|
122
|
+
const lambdasWithoutAnAlias = lambdas.filter((lambda) => lambda.alias === undefined);
|
|
123
|
+
// If the Lambda has an alias it is using versioning. When using versioning, there is no need for Riff-Raff
|
|
124
|
+
// to modify the unpublished version of the function
|
|
125
|
+
lambdasWithoutAnAlias.forEach((lambda) => {
|
|
126
|
+
const lambdaDeployment = (0, lambda_2.updateLambdaDeployment)(lambda, cfnDeployment);
|
|
127
|
+
deployments.set(lambdaDeployment.name, lambdaDeployment.props);
|
|
241
128
|
});
|
|
242
|
-
|
|
129
|
+
/*
|
|
130
|
+
Instances in an ASG with an `AutoScalingRollingUpdate` update policy are rotated via CloudFormation.
|
|
131
|
+
Therefore, they do not need to also perform an `autoscaling` deployment via Riff-Raff.
|
|
132
|
+
*/
|
|
133
|
+
const legacyAutoscalingGroups = autoscalingGroups.filter((asg) => {
|
|
134
|
+
const { cfnOptions } = asg.node.defaultChild;
|
|
135
|
+
const { updatePolicy } = cfnOptions;
|
|
136
|
+
return updatePolicy?.autoScalingRollingUpdate === undefined;
|
|
137
|
+
});
|
|
138
|
+
legacyAutoscalingGroups.forEach((asg) => {
|
|
139
|
+
const asgDeployment = (0, autoscaling_2.autoscalingDeployment)(asg, cfnDeployment);
|
|
140
|
+
deployments.set(asgDeployment.name, asgDeployment.props);
|
|
141
|
+
});
|
|
142
|
+
// only add the `amiParametersToTags` property if there are some ASGs in the stack
|
|
143
|
+
if (autoscalingGroups.length > 0) {
|
|
144
|
+
(0, update_parameters_1.updateDeploymentParameters)(deployments, cfnDeployment, {
|
|
145
|
+
amiParametersToTags: (0, cloudformation_1.getAmiParameters)(autoscalingGroups),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/*
|
|
149
|
+
At this point, `stacks` is a collection of similar `GuStack`s that differ only by their `stage`.
|
|
150
|
+
We're about to add `minInstancesInServiceParameters` to assist Riff-Raff when deploying ASGs with scaling policies.
|
|
151
|
+
This is driven by the presence of conditionally added CFN Parameters.
|
|
152
|
+
To support the possibility of there being a scaling policy in PROD but not CODE, look at all the CFN Parameters in `stacks`.
|
|
153
|
+
*/
|
|
154
|
+
const minInstancesInServiceParameters = stacks
|
|
155
|
+
.flatMap((stack) => Object.values(stack.parameters))
|
|
156
|
+
.filter((_) => _ instanceof ec2_app_1.GuAsgMinInstancesInServiceParameterExperimental)
|
|
157
|
+
.reduce((acc, item) => {
|
|
158
|
+
if (!acc.has(item.node.id)) {
|
|
159
|
+
acc.set(item.node.id, item);
|
|
160
|
+
}
|
|
161
|
+
return acc;
|
|
162
|
+
}, new Map());
|
|
163
|
+
/**
|
|
164
|
+
* Only add the `minInstancesInServiceParameters` property if there are some ASGs affected by {@link GuHorizontallyScalingDeploymentPropertiesExperimental}.
|
|
165
|
+
*/
|
|
166
|
+
if (minInstancesInServiceParameters.size > 0) {
|
|
167
|
+
(0, update_parameters_1.updateDeploymentParameters)(deployments, cfnDeployment, {
|
|
168
|
+
minInstancesInServiceParameters: (0, cloudformation_1.getMinInstancesInServiceParameters)(minInstancesInServiceParameters),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
});
|
|
243
172
|
});
|
|
244
173
|
});
|
|
174
|
+
configuration.set(riffRaffProjectName, { allowedStages, deployments });
|
|
245
175
|
});
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
176
|
+
if (missingStacks.length > 0) {
|
|
177
|
+
const message = `Unable to produce a working riff-raff.yaml file; missing ${missingStacks.length} definitions`;
|
|
178
|
+
console.log(`${message} (details below)`);
|
|
179
|
+
console.table(missingStacks);
|
|
180
|
+
throw new Error(message);
|
|
181
|
+
}
|
|
182
|
+
this.configuration = configuration;
|
|
250
183
|
}
|
|
251
184
|
/**
|
|
252
|
-
*
|
|
185
|
+
* A `riff-raff.yaml` file as a string.
|
|
253
186
|
* Useful for testing.
|
|
187
|
+
*
|
|
188
|
+
* @param riffRaffProjectName which project to convert to YAML. Defaults to {@link UnknownRiffRaffProjectName} - any {@link GuStack} without an explicit `riffRaffProjectName` property.
|
|
254
189
|
*/
|
|
255
|
-
toYAML() {
|
|
190
|
+
toYAML(riffRaffProjectName = types_1.UnknownRiffRaffProjectName) {
|
|
256
191
|
// Add support for ES6 Set and Map. See https://github.com/nodeca/js-yaml/issues/436.
|
|
257
192
|
const replacer = (_key, value) => {
|
|
258
193
|
if (value instanceof Set) {
|
|
@@ -265,16 +200,38 @@ class RiffRaffYamlFile {
|
|
|
265
200
|
}
|
|
266
201
|
return value;
|
|
267
202
|
};
|
|
268
|
-
|
|
203
|
+
const content = this.configuration.get(riffRaffProjectName);
|
|
204
|
+
if (!content) {
|
|
205
|
+
throw new Error(`No Riff-Raff project found with name: ${riffRaffProjectName}`);
|
|
206
|
+
}
|
|
207
|
+
return (0, js_yaml_1.dump)(content, { replacer });
|
|
269
208
|
}
|
|
270
209
|
/**
|
|
271
|
-
* Write the `riff-raff.yaml` file to disk
|
|
272
|
-
* It'll be located with the CFN JSON templates generated by `cdk synth`.
|
|
210
|
+
* Write the `riff-raff.yaml` file(s) to disk, located in the same directory as the CFN JSON templates generated by `cdk synth`.
|
|
273
211
|
*/
|
|
274
212
|
synth() {
|
|
275
|
-
|
|
276
|
-
|
|
213
|
+
this.configuration.forEach((_, riffRaffProjectName) => {
|
|
214
|
+
const targetDirectory = riffRaffProjectName === types_1.UnknownRiffRaffProjectName
|
|
215
|
+
? this.outdir
|
|
216
|
+
: validateRiffRaffYamlDirectory(this.outdir, riffRaffProjectName);
|
|
217
|
+
if (!(0, fs_1.existsSync)(targetDirectory)) {
|
|
218
|
+
(0, fs_1.mkdirSync)(targetDirectory, { recursive: true });
|
|
219
|
+
}
|
|
220
|
+
const outPath = path_1.default.join(targetDirectory, "riff-raff.yaml");
|
|
221
|
+
(0, fs_1.writeFileSync)(outPath, this.toYAML(riffRaffProjectName));
|
|
222
|
+
});
|
|
277
223
|
}
|
|
278
224
|
}
|
|
279
225
|
exports.RiffRaffYamlFile = RiffRaffYamlFile;
|
|
226
|
+
function validateRiffRaffYamlDirectory(basePath, riffRaffProjectName) {
|
|
227
|
+
const resolvedBase = path_1.default.resolve(basePath);
|
|
228
|
+
const resolvedPath = path_1.default.resolve(basePath, riffRaffProjectName);
|
|
229
|
+
const relativePath = path_1.default.relative(resolvedBase, resolvedPath);
|
|
230
|
+
const isOutside = relativePath === ".." || relativePath.startsWith(`..${path_1.default.sep}`) || path_1.default.isAbsolute(relativePath);
|
|
231
|
+
if (isOutside) {
|
|
232
|
+
throw new Error(`Directory traversal detected: '${riffRaffProjectName}' would create a directory outside of ${basePath} (riffRaffProjectName=${riffRaffProjectName}, resolvedPath='${resolvedPath}', resolvedBase='${resolvedBase}')`);
|
|
233
|
+
}
|
|
234
|
+
return resolvedPath;
|
|
235
|
+
}
|
|
236
|
+
exports.validateRiffRaffYamlDirectory = validateRiffRaffYamlDirectory;
|
|
280
237
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/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 type { CfnAutoScalingGroup } from \"aws-cdk-lib/aws-autoscaling\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../constructs/autoscaling\";\nimport { GuStack } from \"../constructs/core\";\nimport { GuLambdaFunction } from \"../constructs/lambda\";\nimport { GuAsgMinInstancesInServiceParameterExperimental } from \"../experimental/patterns/ec2-app\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport {\n cloudFormationDeployment,\n getAmiParameters,\n getMinInstancesInServiceParameters,\n} from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { updateDeploymentParameters } from \"./deployments/update-parameters\";\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 RiffRaffYamlFile {\n private readonly allCdkStacks: GuStack[];\n private readonly allStackTags: StackTag[];\n private readonly allStageTags: StageTag[];\n private readonly allRegions: Region[];\n private readonly outdir: string;\n\n /**\n * The `riff-raff.yaml` file as an object.\n *\n * It is useful for specifying additional deployment types that GuCDK does not support.\n * Consider raising an issue or pull request if you think it should be supported.\n *\n * In most cases, you shouldn't need to access this.\n * No validation is performed on the parameters you provide, so you might get deployment errors.\n *\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\n public readonly riffRaffYaml: RiffRaffYaml;\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 private getGuStackDependencies(cdkStack: GuStack): GuStack[] {\n return cdkStack.dependencies.filter((_) => _ instanceof GuStack) as GuStack[];\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 // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n const [stack] = stacks;\n\n if (!stack) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\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 parentStacks: RiffRaffDeployment[] = this.getGuStackDependencies(stack).map((x) =>\n cloudFormationDeployment([x], [], this.outdir),\n );\n\n const cfnDeployment = cloudFormationDeployment(stacks, [...artifactUploads, ...parentStacks], 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 /*\n Instances in an ASG with an `AutoScalingRollingUpdate` update policy are rotated via CloudFormation.\n Therefore, they do not need to also perform an `autoscaling` deployment via Riff-Raff.\n */\n const legacyAutoscalingGroups = autoscalingGroups.filter((asg) => {\n const { cfnOptions } = asg.node.defaultChild as CfnAutoScalingGroup;\n const { updatePolicy } = cfnOptions;\n return updatePolicy?.autoScalingRollingUpdate === undefined;\n });\n\n legacyAutoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n });\n\n // only add the `amiParametersToTags` property if there are some ASGs in the stack\n if (autoscalingGroups.length > 0) {\n updateDeploymentParameters(deployments, cfnDeployment, {\n amiParametersToTags: getAmiParameters(autoscalingGroups),\n });\n }\n\n /*\n At this point, `stacks` is a collection of similar `GuStack`s that differ only by their `stage`.\n We're about to add `minInstancesInServiceParameters` to assist Riff-Raff when deploying ASGs with scaling policies.\n This is driven by the presence of conditionally added CFN Parameters.\n To support the possibility of there being a scaling policy in PROD but not CODE, look at all the CFN Parameters in `stacks`.\n */\n const minInstancesInServiceParameters: Map<string, GuAsgMinInstancesInServiceParameterExperimental> = stacks\n .flatMap((stack) => Object.values(stack.parameters))\n .filter(\n (_): _ is GuAsgMinInstancesInServiceParameterExperimental =>\n _ instanceof GuAsgMinInstancesInServiceParameterExperimental,\n )\n .reduce((acc, item) => {\n if (!acc.has(item.node.id)) {\n acc.set(item.node.id, item);\n }\n return acc;\n }, new Map<string, GuAsgMinInstancesInServiceParameterExperimental>());\n\n /**\n * Only add the `minInstancesInServiceParameters` property if there are some ASGs affected by {@link GuHorizontallyScalingDeploymentPropertiesExperimental}.\n */\n if (minInstancesInServiceParameters.size > 0) {\n updateDeploymentParameters(deployments, cfnDeployment, {\n minInstancesInServiceParameters: getMinInstancesInServiceParameters(minInstancesInServiceParameters),\n });\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/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport type { CfnAutoScalingGroup } from \"aws-cdk-lib/aws-autoscaling\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../constructs/autoscaling\";\nimport { GuStack } from \"../constructs/core\";\nimport { GuLambdaFunction } from \"../constructs/lambda\";\nimport { GuAsgMinInstancesInServiceParameterExperimental } from \"../experimental/patterns/ec2-app\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport {\n cloudFormationDeployment,\n getAmiParameters,\n getMinInstancesInServiceParameters,\n} from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { updateDeploymentParameters } from \"./deployments/update-parameters\";\nimport {\n groupByClassName,\n groupByRegion,\n groupByRiffRaffProjectName,\n groupByStackTag,\n groupByStageTag,\n} from \"./group-by\";\nimport type {\n ClassName,\n Region,\n RiffRaffDeployment,\n RiffRaffDeploymentName,\n RiffRaffDeploymentProps,\n RiffRaffProjectName,\n RiffRaffYaml,\n StackTag,\n StageTag,\n} from \"./types\";\nimport { UnknownRiffRaffProjectName } from \"./types\";\n\nfunction validateAllRegionsAreResolved(regions: Region[]): void {\n const unresolved = regions.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\nfunction getLambdas(cdkStack: GuStack): GuLambdaFunction[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuLambdaFunction) as GuLambdaFunction[];\n}\n\nfunction getAutoScalingGroups(cdkStack: GuStack): GuAutoScalingGroup[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuAutoScalingGroup) as GuAutoScalingGroup[];\n}\n\nfunction getGuStackDependencies(cdkStack: GuStack): GuStack[] {\n return cdkStack.dependencies.filter((_) => _ instanceof GuStack) as GuStack[];\n}\n\ninterface MissingStack {\n riffRaffProjectName: RiffRaffProjectName;\n className: ClassName;\n stack: StackTag;\n stage: StageTag;\n region: Region;\n}\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 RiffRaffYamlFile {\n private readonly outdir: string;\n\n /**\n * A mapping between a Riff-Raff project and `riff-raff.yaml` content as an object.\n *\n * It is useful for specifying additional deployment types that GuCDK does not support.\n * Consider raising an issue or pull request if you think it should be supported.\n *\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\n public readonly configuration: Map<RiffRaffProjectName, RiffRaffYaml>;\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 const allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allRegions = Array.from(new Set(allCdkStacks.map((_) => _.region)));\n\n validateAllRegionsAreResolved(allRegions);\n\n this.outdir = app.outdir;\n const configuration = new Map<RiffRaffProjectName, RiffRaffYaml>();\n const missingStacks: MissingStack[] = [];\n\n Object.entries(groupByRiffRaffProjectName(allCdkStacks)).forEach(\n ([riffRaffProjectName, stacksGroupedByRiffRaffProject]) => {\n const allowedStages = new Set(stacksGroupedByRiffRaffProject.map((_) => _.stage));\n const requiredStages = Array.from(allowedStages);\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n Object.entries(groupByClassName(stacksGroupedByRiffRaffProject)).forEach(\n ([className, stacksGroupedByClassName]) => {\n Object.entries(groupByStackTag(stacksGroupedByClassName)).forEach(([stackTag, stacksGroupedByStackTag]) => {\n Object.entries(groupByRegion(stacksGroupedByStackTag)).forEach(([region, stacksGroupedByRegion]) => {\n const stacks: GuStack[] = Object.values(groupByStageTag(stacksGroupedByRegion)).flat();\n\n requiredStages.forEach((requiredStage) => {\n if (!stacks.find(({ stage }) => stage === requiredStage)) {\n missingStacks.push({\n riffRaffProjectName,\n className,\n region,\n stack: stackTag,\n stage: requiredStage,\n });\n }\n });\n\n // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n const [stack] = stacks;\n\n if (!stack) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n const lambdas = getLambdas(stack);\n const autoscalingGroups = 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 parentStacks: RiffRaffDeployment[] = getGuStackDependencies(stack).map((x) =>\n cloudFormationDeployment([x], [], this.outdir),\n );\n\n const cfnDeployment = cloudFormationDeployment(\n stacks,\n [...artifactUploads, ...parentStacks],\n this.outdir,\n );\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 /*\n Instances in an ASG with an `AutoScalingRollingUpdate` update policy are rotated via CloudFormation.\n Therefore, they do not need to also perform an `autoscaling` deployment via Riff-Raff.\n */\n const legacyAutoscalingGroups = autoscalingGroups.filter((asg) => {\n const { cfnOptions } = asg.node.defaultChild as CfnAutoScalingGroup;\n const { updatePolicy } = cfnOptions;\n return updatePolicy?.autoScalingRollingUpdate === undefined;\n });\n\n legacyAutoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n });\n\n // only add the `amiParametersToTags` property if there are some ASGs in the stack\n if (autoscalingGroups.length > 0) {\n updateDeploymentParameters(deployments, cfnDeployment, {\n amiParametersToTags: getAmiParameters(autoscalingGroups),\n });\n }\n\n /*\n At this point, `stacks` is a collection of similar `GuStack`s that differ only by their `stage`.\n We're about to add `minInstancesInServiceParameters` to assist Riff-Raff when deploying ASGs with scaling policies.\n This is driven by the presence of conditionally added CFN Parameters.\n To support the possibility of there being a scaling policy in PROD but not CODE, look at all the CFN Parameters in `stacks`.\n */\n const minInstancesInServiceParameters: Map<string, GuAsgMinInstancesInServiceParameterExperimental> =\n stacks\n .flatMap((stack) => Object.values(stack.parameters))\n .filter(\n (_): _ is GuAsgMinInstancesInServiceParameterExperimental =>\n _ instanceof GuAsgMinInstancesInServiceParameterExperimental,\n )\n .reduce((acc, item) => {\n if (!acc.has(item.node.id)) {\n acc.set(item.node.id, item);\n }\n return acc;\n }, new Map<string, GuAsgMinInstancesInServiceParameterExperimental>());\n\n /**\n * Only add the `minInstancesInServiceParameters` property if there are some ASGs affected by {@link GuHorizontallyScalingDeploymentPropertiesExperimental}.\n */\n if (minInstancesInServiceParameters.size > 0) {\n updateDeploymentParameters(deployments, cfnDeployment, {\n minInstancesInServiceParameters: getMinInstancesInServiceParameters(\n minInstancesInServiceParameters,\n ),\n });\n }\n });\n });\n },\n );\n\n configuration.set(riffRaffProjectName, { allowedStages, deployments });\n },\n );\n\n if (missingStacks.length > 0) {\n const message = `Unable to produce a working riff-raff.yaml file; missing ${missingStacks.length} definitions`;\n console.log(`${message} (details below)`);\n console.table(missingStacks);\n\n throw new Error(message);\n }\n\n this.configuration = configuration;\n }\n\n /**\n * A `riff-raff.yaml` file as a string.\n * Useful for testing.\n *\n * @param riffRaffProjectName which project to convert to YAML. Defaults to {@link UnknownRiffRaffProjectName} - any {@link GuStack} without an explicit `riffRaffProjectName` property.\n */\n toYAML(riffRaffProjectName: RiffRaffProjectName = UnknownRiffRaffProjectName): 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 const content = this.configuration.get(riffRaffProjectName);\n\n if (!content) {\n throw new Error(`No Riff-Raff project found with name: ${riffRaffProjectName}`);\n }\n\n return dump(content, { replacer });\n }\n\n /**\n * Write the `riff-raff.yaml` file(s) to disk, located in the same directory as the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n this.configuration.forEach((_, riffRaffProjectName) => {\n const targetDirectory =\n riffRaffProjectName === UnknownRiffRaffProjectName\n ? this.outdir\n : validateRiffRaffYamlDirectory(this.outdir, riffRaffProjectName);\n\n if (!existsSync(targetDirectory)) {\n mkdirSync(targetDirectory, { recursive: true });\n }\n\n const outPath = path.join(targetDirectory, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML(riffRaffProjectName));\n });\n }\n}\n\nexport function validateRiffRaffYamlDirectory(basePath: string, riffRaffProjectName: RiffRaffProjectName): string {\n const resolvedBase = path.resolve(basePath);\n const resolvedPath = path.resolve(basePath, riffRaffProjectName);\n const relativePath = path.relative(resolvedBase, resolvedPath);\n const isOutside = relativePath === \"..\" || relativePath.startsWith(`..${path.sep}`) || path.isAbsolute(relativePath);\n\n if (isOutside) {\n throw new Error(\n `Directory traversal detected: '${riffRaffProjectName}' would create a directory outside of ${basePath} (riffRaffProjectName=${riffRaffProjectName}, resolvedPath='${resolvedPath}', resolvedBase='${resolvedBase}')`,\n );\n }\n\n return resolvedPath;\n}\n"]}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import type { GuStack } from "../constructs/core";
|
|
2
|
+
export type RiffRaffProjectName = string;
|
|
2
3
|
export type ClassName = string;
|
|
3
4
|
export type StackTag = string;
|
|
4
5
|
export type StageTag = string;
|
|
5
6
|
export type Region = string;
|
|
6
7
|
export type CdkStacksDifferingOnlyByStage = GuStack[];
|
|
8
|
+
/**
|
|
9
|
+
* The default value used to group {@link GuStack} when generating a `riff-raff.yaml` file.
|
|
10
|
+
* This value will be used when the {@link GuStack} does not have a `riffRaffProjectName` property set.
|
|
11
|
+
* Should only be externally used if adding a custom deployment to the `riff-raff.yaml` file.
|
|
12
|
+
*/
|
|
13
|
+
export declare const UnknownRiffRaffProjectName: RiffRaffProjectName;
|
|
7
14
|
export interface RiffRaffYaml {
|
|
8
15
|
allowedStages: Set<StageTag>;
|
|
9
16
|
deployments: Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>;
|
|
@@ -24,6 +31,5 @@ export interface RiffRaffDeployment {
|
|
|
24
31
|
name: RiffRaffDeploymentName;
|
|
25
32
|
props: RiffRaffDeploymentProps;
|
|
26
33
|
}
|
|
27
|
-
export type GroupedCdkStacks = Record<ClassName, Record<StackTag, Record<Region, Record<StageTag, CdkStacksDifferingOnlyByStage>>>>;
|
|
28
34
|
export type RiffRaffDeployments = Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>;
|
|
29
35
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAC/B,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAC9B,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAC9B,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAC5B,MAAM,MAAM,6BAA6B,GAAG,OAAO,EAAE,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,WAAW,EAAE,GAAG,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;CACnE;AAED,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE5C,MAAM,MAAM,4BAA4B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEtG,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,4BAA4B,CAAC;IACzC,YAAY,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,sBAAsB,CAAC;IAC7B,KAAK,EAAE,uBAAuB,CAAC;CAChC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC;AACzC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAC/B,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAC9B,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAC9B,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAC5B,MAAM,MAAM,6BAA6B,GAAG,OAAO,EAAE,CAAC;AAEtD;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,mBAAuE,CAAC;AAEjH,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,WAAW,EAAE,GAAG,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;CACnE;AAED,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE5C,MAAM,MAAM,4BAA4B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEtG,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,4BAA4B,CAAC;IACzC,YAAY,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,sBAAsB,CAAC;IAC7B,KAAK,EAAE,uBAAuB,CAAC;CAChC;AAED,MAAM,MAAM,mBAAmB,GAAG,GAAG,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC"}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnknownRiffRaffProjectName = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The default value used to group {@link GuStack} when generating a `riff-raff.yaml` file.
|
|
6
|
+
* This value will be used when the {@link GuStack} does not have a `riffRaffProjectName` property set.
|
|
7
|
+
* Should only be externally used if adding a custom deployment to the `riff-raff.yaml` file.
|
|
8
|
+
*/
|
|
9
|
+
exports.UnknownRiffRaffProjectName = "gu:cdk:constants:unknown-riff-raff-project-name";
|
|
3
10
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/types.ts"],"names":[],"mappings":"","sourcesContent":["// type aliases to, hopefully, improve readability\nimport type { GuStack } from \"../constructs/core\";\n\nexport type ClassName = string;\nexport type StackTag = string;\nexport type StageTag = string;\nexport type Region = string;\nexport type CdkStacksDifferingOnlyByStage = GuStack[];\n\nexport interface RiffRaffYaml {\n allowedStages: Set<StageTag>;\n deployments: Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>;\n}\n\nexport type RiffRaffDeploymentName = string;\n\nexport type RiffRaffDeploymentParameters = Record<string, string | boolean | Record<string, unknown>>;\n\nexport interface RiffRaffDeploymentProps {\n type: string;\n regions: Set<Region>;\n stacks: Set<StackTag>;\n app: string;\n contentDirectory: string;\n parameters: RiffRaffDeploymentParameters;\n dependencies?: RiffRaffDeploymentName[];\n actions?: string[];\n}\n\nexport interface RiffRaffDeployment {\n name: RiffRaffDeploymentName;\n props: RiffRaffDeploymentProps;\n}\n\
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/types.ts"],"names":[],"mappings":";;;AAUA;;;;GAIG;AACU,QAAA,0BAA0B,GAAwB,iDAAiD,CAAC","sourcesContent":["// type aliases to, hopefully, improve readability\nimport type { GuStack } from \"../constructs/core\";\n\nexport type RiffRaffProjectName = string;\nexport type ClassName = string;\nexport type StackTag = string;\nexport type StageTag = string;\nexport type Region = string;\nexport type CdkStacksDifferingOnlyByStage = GuStack[];\n\n/**\n * The default value used to group {@link GuStack} when generating a `riff-raff.yaml` file.\n * This value will be used when the {@link GuStack} does not have a `riffRaffProjectName` property set.\n * Should only be externally used if adding a custom deployment to the `riff-raff.yaml` file.\n */\nexport const UnknownRiffRaffProjectName: RiffRaffProjectName = \"gu:cdk:constants:unknown-riff-raff-project-name\";\n\nexport interface RiffRaffYaml {\n allowedStages: Set<StageTag>;\n deployments: Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>;\n}\n\nexport type RiffRaffDeploymentName = string;\n\nexport type RiffRaffDeploymentParameters = Record<string, string | boolean | Record<string, unknown>>;\n\nexport interface RiffRaffDeploymentProps {\n type: string;\n regions: Set<Region>;\n stacks: Set<StackTag>;\n app: string;\n contentDirectory: string;\n parameters: RiffRaffDeploymentParameters;\n dependencies?: RiffRaffDeploymentName[];\n actions?: string[];\n}\n\nexport interface RiffRaffDeployment {\n name: RiffRaffDeploymentName;\n props: RiffRaffDeploymentProps;\n}\n\nexport type RiffRaffDeployments = Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>;\n"]}
|