@guardian/cdk 62.6.0 → 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.
Files changed (32) hide show
  1. package/lib/constructs/core/stack.d.ts +9 -0
  2. package/lib/constructs/core/stack.d.ts.map +1 -1
  3. package/lib/constructs/core/stack.js +5 -1
  4. package/lib/constructs/core/stack.js.map +1 -1
  5. package/lib/constructs/root.d.ts.map +1 -1
  6. package/lib/constructs/root.js +9 -1
  7. package/lib/constructs/root.js.map +1 -1
  8. package/lib/experimental/patterns/ec2-app.d.ts +13 -13
  9. package/lib/experimental/patterns/ec2-app.d.ts.map +1 -1
  10. package/lib/experimental/patterns/ec2-app.js +42 -38
  11. package/lib/experimental/patterns/ec2-app.js.map +1 -1
  12. package/lib/riff-raff-yaml-file/deployments/cloudformation.d.ts +2 -1
  13. package/lib/riff-raff-yaml-file/deployments/cloudformation.d.ts.map +1 -1
  14. package/lib/riff-raff-yaml-file/deployments/cloudformation.js +7 -12
  15. package/lib/riff-raff-yaml-file/deployments/cloudformation.js.map +1 -1
  16. package/lib/riff-raff-yaml-file/deployments/update-parameters.d.ts +3 -0
  17. package/lib/riff-raff-yaml-file/deployments/update-parameters.d.ts.map +1 -0
  18. package/lib/riff-raff-yaml-file/deployments/update-parameters.js +18 -0
  19. package/lib/riff-raff-yaml-file/deployments/update-parameters.js.map +1 -0
  20. package/lib/riff-raff-yaml-file/group-by.d.ts +6 -2
  21. package/lib/riff-raff-yaml-file/group-by.d.ts.map +1 -1
  22. package/lib/riff-raff-yaml-file/group-by.js +9 -13
  23. package/lib/riff-raff-yaml-file/group-by.js.map +1 -1
  24. package/lib/riff-raff-yaml-file/index.d.ts +9 -74
  25. package/lib/riff-raff-yaml-file/index.d.ts.map +1 -1
  26. package/lib/riff-raff-yaml-file/index.js +145 -172
  27. package/lib/riff-raff-yaml-file/index.js.map +1 -1
  28. package/lib/riff-raff-yaml-file/types.d.ts +8 -1
  29. package/lib/riff-raff-yaml-file/types.d.ts.map +1 -1
  30. package/lib/riff-raff-yaml-file/types.js +7 -0
  31. package/lib/riff-raff-yaml-file/types.js.map +1 -1
  32. package/package.json +1 -1
@@ -0,0 +1,3 @@
1
+ import type { RiffRaffDeployment, RiffRaffDeploymentParameters, RiffRaffDeployments } from "../types";
2
+ export declare function updateDeploymentParameters(allDeployments: RiffRaffDeployments, deploymentToUpdate: RiffRaffDeployment, additionalParametersToApply: RiffRaffDeploymentParameters): void;
3
+ //# sourceMappingURL=update-parameters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-parameters.d.ts","sourceRoot":"","sources":["../../../src/riff-raff-yaml-file/deployments/update-parameters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEtG,wBAAgB,0BAA0B,CACxC,cAAc,EAAE,mBAAmB,EACnC,kBAAkB,EAAE,kBAAkB,EACtC,2BAA2B,EAAE,4BAA4B,QAc1D"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateDeploymentParameters = void 0;
4
+ function updateDeploymentParameters(allDeployments, deploymentToUpdate, additionalParametersToApply) {
5
+ const currentDeployment = allDeployments.get(deploymentToUpdate.name);
6
+ if (!currentDeployment) {
7
+ throw new Error(`Unable to find deployment ${deploymentToUpdate.name}`);
8
+ }
9
+ allDeployments.set(deploymentToUpdate.name, {
10
+ ...currentDeployment,
11
+ parameters: {
12
+ ...currentDeployment.parameters,
13
+ ...additionalParametersToApply,
14
+ },
15
+ });
16
+ }
17
+ exports.updateDeploymentParameters = updateDeploymentParameters;
18
+ //# sourceMappingURL=update-parameters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-parameters.js","sourceRoot":"","sources":["../../../src/riff-raff-yaml-file/deployments/update-parameters.ts"],"names":[],"mappings":";;;AAEA,SAAgB,0BAA0B,CACxC,cAAmC,EACnC,kBAAsC,EACtC,2BAAyD;IAEzD,MAAM,iBAAiB,GAAG,cAAc,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACtE,IAAI,CAAC,iBAAiB,EAAE;QACtB,MAAM,IAAI,KAAK,CAAC,6BAA6B,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC;KACzE;IAED,cAAc,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,EAAE;QAC1C,GAAG,iBAAiB;QACpB,UAAU,EAAE;YACV,GAAG,iBAAiB,CAAC,UAAU;YAC/B,GAAG,2BAA2B;SAC/B;KACF,CAAC,CAAC;AACL,CAAC;AAjBD,gEAiBC","sourcesContent":["import type { RiffRaffDeployment, RiffRaffDeploymentParameters, RiffRaffDeployments } from \"../types\";\n\nexport function updateDeploymentParameters(\n allDeployments: RiffRaffDeployments,\n deploymentToUpdate: RiffRaffDeployment,\n additionalParametersToApply: RiffRaffDeploymentParameters,\n) {\n const currentDeployment = allDeployments.get(deploymentToUpdate.name);\n if (!currentDeployment) {\n throw new Error(`Unable to find deployment ${deploymentToUpdate.name}`);\n }\n\n allDeployments.set(deploymentToUpdate.name, {\n ...currentDeployment,\n parameters: {\n ...currentDeployment.parameters,\n ...additionalParametersToApply,\n },\n });\n}\n"]}
@@ -1,4 +1,8 @@
1
1
  import type { GuStack } from "../constructs/core";
2
- import type { GroupedCdkStacks } from "./types";
3
- export declare function groupByClassNameStackRegionStage(cdkStacks: GuStack[]): GroupedCdkStacks;
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,EAAa,gBAAgB,EAA8B,MAAM,SAAS,CAAC;AAkBvF,wBAAgB,gCAAgC,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAoBvF"}
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.groupByClassNameStackRegionStage = void 0;
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
- function groupByClassNameStackRegionStage(cdkStacks) {
18
- return Object.entries(groupByClassName(cdkStacks)).reduce((accClassName, [className, stacksGroupedByClassName]) => ({
19
- ...accClassName,
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.groupByClassNameStackRegionStage = groupByClassNameStackRegionStage;
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;AAGzC,SAAS,gBAAgB,CAAC,SAAoB;IAC5C,OAAO,IAAA,eAAO,EAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,eAAe,CAAC,SAAoB;IAC3C,OAAO,IAAA,eAAO,EAAC,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,eAAe,CAAC,SAAoB;IAC3C,OAAO,IAAA,eAAO,EAAC,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,aAAa,CAAC,SAAoB;IACzC,OAAO,IAAA,eAAO,EAAC,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;AACpD,CAAC;AAED,SAAgB,gCAAgC,CAAC,SAAoB;IACnE,OAAO,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CACvD,CAAC,YAAY,EAAE,CAAC,SAAS,EAAE,wBAAwB,CAAC,EAAE,EAAE,CAAC,CAAC;QACxD,GAAG,YAAY;QACf,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,wBAAwB,CAAC,CAAC,CAAC,MAAM,CAC3E,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,uBAAuB,CAAC,EAAE,EAAE,CAAC,CAAC;YACrD,GAAG,WAAW;YACd,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,uBAAuB,CAAC,CAAC,CAAC,MAAM,CACvE,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,qBAAqB,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC/C,GAAG,SAAS;gBACZ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC,qBAAqB,CAAC;aACjD,CAAC,EACF,EAAE,CACH;SACF,CAAC,EACF,EAAE,CACH;KACF,CAAC,EACF,EAAE,CACH,CAAC;AACJ,CAAC;AApBD,4EAoBC","sourcesContent":["import type { GuStack } from \"../constructs/core\";\nimport { groupBy } from \"../utils/array\";\nimport type { ClassName, GroupedCdkStacks, Region, StackTag, StageTag } from \"./types\";\n\nfunction groupByClassName(cdkStacks: GuStack[]): Record<ClassName, GuStack[]> {\n return groupBy(cdkStacks, (stack) => stack.constructor.name);\n}\n\nfunction groupByStackTag(cdkStacks: GuStack[]): Record<StackTag, GuStack[]> {\n return groupBy(cdkStacks, ({ stack }) => stack);\n}\n\nfunction groupByStageTag(cdkStacks: GuStack[]): Record<StageTag, GuStack[]> {\n return groupBy(cdkStacks, ({ stage }) => stage);\n}\n\nfunction groupByRegion(cdkStacks: GuStack[]): Record<Region, GuStack[]> {\n return groupBy(cdkStacks, ({ region }) => region);\n}\n\nexport function groupByClassNameStackRegionStage(cdkStacks: GuStack[]): GroupedCdkStacks {\n return Object.entries(groupByClassName(cdkStacks)).reduce(\n (accClassName, [className, stacksGroupedByClassName]) => ({\n ...accClassName,\n [className]: Object.entries(groupByStackTag(stacksGroupedByClassName)).reduce(\n (accStackTag, [stackTag, stacksGroupedByStackTag]) => ({\n ...accStackTag,\n [stackTag]: Object.entries(groupByRegion(stacksGroupedByStackTag)).reduce(\n (accRegion, [region, stacksGroupedByRegion]) => ({\n ...accRegion,\n [region]: groupByStageTag(stacksGroupedByRegion),\n }),\n {},\n ),\n }),\n {},\n ),\n }),\n {},\n );\n}\n"]}
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
- * The `riff-raff.yaml` file as an object.
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 riffRaffYaml: RiffRaffYaml;
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
- * The `riff-raff.yaml` file as a string.
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;AAgBvC,OAAO,KAAK,EAMV,YAAY,EAGb,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAY;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;;;;;;OAUG;IACH,SAAgB,YAAY,EAAE,YAAY,CAAC;IAE3C,OAAO,CAAC,iBAAiB;IASzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqDG;IACH,OAAO,CAAC,mBAAmB;IAiC3B,OAAO,CAAC,6BAA6B;IAQrC,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,sBAAsB;gBAKlB,GAAG,EAAE,GAAG;IAgGpB;;;OAGG;IACH,MAAM,IAAI,MAAM;IAiBhB;;;OAGG;IACH,KAAK,IAAI,IAAI;CAId"}
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");
@@ -15,7 +15,24 @@ const ec2_app_1 = require("../experimental/patterns/ec2-app");
15
15
  const autoscaling_2 = require("./deployments/autoscaling");
16
16
  const cloudformation_1 = require("./deployments/cloudformation");
17
17
  const lambda_2 = require("./deployments/lambda");
18
+ const update_parameters_1 = require("./deployments/update-parameters");
18
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
+ }
19
36
  /**
20
37
  * A class that creates a `riff-raff.yaml` file.
21
38
  *
@@ -60,183 +77,117 @@ const group_by_1 = require("./group-by");
60
77
  * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types
61
78
  */
62
79
  class RiffRaffYamlFile {
63
- isCdkStackPresent(expectedStack, expectedStage) {
64
- const matches = this.allCdkStacks.find((cdkStack) => {
65
- const { stack, stage } = cdkStack;
66
- return stack === expectedStack && stage === expectedStage;
67
- });
68
- return !!matches;
69
- }
70
- /**
71
- * Check there are the appropriate number of `GuStack`s.
72
- * Expect to find an instance for each combination of `stack`, and `stage`.
73
- *
74
- * If not valid, a message is logged describing what is missing to aid debugging.
75
- *
76
- * Given the following:
77
- *
78
- * ```ts
79
- * const app = new App();
80
- *
81
- * class MyApplicationStack extends GuStack { }
82
- *
83
- * new MyApplicationStack(app, "App-CODE-deploy", {
84
- * env: {
85
- * region: "eu-west-1",
86
- * },
87
- * stack: "deploy",
88
- * stage: "CODE"
89
- * });
90
- *
91
- * new MyApplicationStack(app, "App-PROD-media-service", {
92
- * env: {
93
- * region: "eu-west-1",
94
- * },
95
- * stack: "media-service",
96
- * stage: "PROD",
97
- * });
98
- *
99
- * new MyApplicationStack(app, "App-PROD-deploy", {
100
- * env: {
101
- * region: "eu-west-1",
102
- * },
103
- * stack: "deploy",
104
- * stage: "PROD"
105
- * });
106
- * ```
107
- *
108
- * This will log a message like this, where ❌ denotes something missing,
109
- * specifically there is no `CODE` template for `media-service`.
110
- *
111
- * ```log
112
- * Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)
113
- *
114
- * ┌───────────────┬──────┬──────┐
115
- * │ (index) │ CODE │ PROD │
116
- * ├───────────────┼──────┼──────┤
117
- * │ deploy │ '✅' │ '✅' │
118
- * │ media-service │ '❌' │ '✅' │
119
- * └───────────────┴──────┴──────┘
120
- * ```
121
- *
122
- * @private
123
- */
124
- validateStacksInApp() {
125
- const { allStackTags, allStageTags } = this;
126
- const checks = allStackTags.reduce((accStackTag, stackTag) => {
127
- return {
128
- ...accStackTag,
129
- [stackTag]: allStageTags.reduce((accStageTag, stageTag) => {
130
- return {
131
- ...accStageTag,
132
- [stageTag]: this.isCdkStackPresent(stackTag, stageTag) ? "✅" : "❌",
133
- };
134
- }, {}),
135
- };
136
- }, {});
137
- const missingDefinitions = Object.values(checks).flatMap((groupedByStackTag) => {
138
- return Object.values(groupedByStackTag).filter((_) => _ === "❌");
139
- });
140
- if (missingDefinitions.length > 0) {
141
- const message = `Unable to produce a working riff-raff.yaml file; missing ${missingDefinitions.length} definitions`;
142
- console.log(`${message} (details below)`);
143
- console.table(checks);
144
- throw new Error(message);
145
- }
146
- }
147
- validateAllRegionsAreResolved() {
148
- const unresolved = this.allRegions.filter((region) => aws_cdk_lib_1.Token.isUnresolved(region));
149
- if (unresolved.length !== 0) {
150
- throw new Error(`Unable to produce a working riff-raff.yaml file; all stacks must have an explicit region set`);
151
- }
152
- }
153
- getLambdas(cdkStack) {
154
- return cdkStack.node.findAll().filter((_) => _ instanceof lambda_1.GuLambdaFunction);
155
- }
156
- getAutoScalingGroups(cdkStack) {
157
- return cdkStack.node.findAll().filter((_) => _ instanceof autoscaling_1.GuAutoScalingGroup);
158
- }
159
- getGuStackDependencies(cdkStack) {
160
- return cdkStack.dependencies.filter((_) => _ instanceof core_1.GuStack);
161
- }
162
80
  // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree
163
81
  constructor(app) {
164
- this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof core_1.GuStack);
165
- const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));
166
- this.allStageTags = Array.from(allowedStages);
167
- this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));
168
- this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));
169
- this.validateStacksInApp();
170
- 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);
171
85
  this.outdir = app.outdir;
172
- const deployments = new Map();
173
- const groupedStacks = (0, group_by_1.groupByClassNameStackRegionStage)(this.allCdkStacks);
174
- Object.values(groupedStacks).forEach((stackTagGroup) => {
175
- Object.values(stackTagGroup).forEach((regionGroup) => {
176
- Object.values(regionGroup).forEach((stageGroup) => {
177
- const stacks = Object.values(stageGroup).flat();
178
- // The items in `stacks` only differ by stage, so we can just use the first item in the list.
179
- const [stack] = stacks;
180
- if (!stack) {
181
- throw new Error("Unable to produce a working riff-raff.yaml file; there are no stacks!");
182
- }
183
- const lambdas = this.getLambdas(stack);
184
- const autoscalingGroups = this.getAutoScalingGroups(stack);
185
- const artifactUploads = [
186
- lambdas.filter((_) => !_.withoutArtifactUpload).map(lambda_2.uploadLambdaArtifact),
187
- autoscalingGroups.map(autoscaling_2.uploadAutoscalingArtifact),
188
- ].flat();
189
- artifactUploads.forEach(({ name, props }) => deployments.set(name, props));
190
- const parentStacks = this.getGuStackDependencies(stack).map((x) => (0, cloudformation_1.cloudFormationDeployment)([x], [], this.outdir));
191
- const cfnDeployment = (0, cloudformation_1.cloudFormationDeployment)(stacks, [...artifactUploads, ...parentStacks], this.outdir);
192
- deployments.set(cfnDeployment.name, cfnDeployment.props);
193
- const lambdasWithoutAnAlias = lambdas.filter((lambda) => lambda.alias === undefined);
194
- // If the Lambda has an alias it is using versioning. When using versioning, there is no need for Riff-Raff
195
- // to modify the unpublished version of the function
196
- lambdasWithoutAnAlias.forEach((lambda) => {
197
- const lambdaDeployment = (0, lambda_2.updateLambdaDeployment)(lambda, cfnDeployment);
198
- deployments.set(lambdaDeployment.name, lambdaDeployment.props);
199
- });
200
- /*
201
- Instances in an ASG with an `AutoScalingRollingUpdate` update policy are rotated via CloudFormation.
202
- Therefore, they do not need to also perform an `autoscaling` deployment via Riff-Raff.
203
- */
204
- const legacyAutoscalingGroups = autoscalingGroups.filter((asg) => {
205
- const { cfnOptions } = asg.node.defaultChild;
206
- const { updatePolicy } = cfnOptions;
207
- return updatePolicy?.autoScalingRollingUpdate === undefined;
208
- });
209
- legacyAutoscalingGroups.forEach((asg) => {
210
- const asgDeployment = (0, autoscaling_2.autoscalingDeployment)(asg, cfnDeployment);
211
- deployments.set(asgDeployment.name, asgDeployment.props);
212
- });
213
- const amiParametersToTags = (0, cloudformation_1.getAmiParameters)(autoscalingGroups);
214
- const minInServiceParamMap = ec2_app_1.GuHorizontallyScalingDeploymentPropertiesExperimental.getInstance(stack).asgToParamMap;
215
- const minInServiceAsgs = autoscalingGroups.filter((asg) => minInServiceParamMap.has(asg.node.id));
216
- const minInstancesInServiceParameters = (0, cloudformation_1.getMinInstancesInServiceParameters)(minInServiceAsgs);
217
- deployments.set(cfnDeployment.name, {
218
- ...cfnDeployment.props,
219
- parameters: {
220
- ...cfnDeployment.props.parameters,
221
- // only add the `amiParametersToTags` property if there are some
222
- ...(autoscalingGroups.length > 0 && { amiParametersToTags }),
223
- // only add the `minInstancesInServiceParameters` property if there are some
224
- ...(minInServiceAsgs.length > 0 && { minInstancesInServiceParameters }),
225
- },
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
+ }
106
+ });
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!");
111
+ }
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);
128
+ });
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
+ }
226
171
  });
227
172
  });
228
173
  });
174
+ configuration.set(riffRaffProjectName, { allowedStages, deployments });
229
175
  });
230
- this.riffRaffYaml = {
231
- allowedStages,
232
- deployments,
233
- };
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;
234
183
  }
235
184
  /**
236
- * The `riff-raff.yaml` file as a string.
185
+ * A `riff-raff.yaml` file as a string.
237
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.
238
189
  */
239
- toYAML() {
190
+ toYAML(riffRaffProjectName = types_1.UnknownRiffRaffProjectName) {
240
191
  // Add support for ES6 Set and Map. See https://github.com/nodeca/js-yaml/issues/436.
241
192
  const replacer = (_key, value) => {
242
193
  if (value instanceof Set) {
@@ -249,16 +200,38 @@ class RiffRaffYamlFile {
249
200
  }
250
201
  return value;
251
202
  };
252
- return (0, js_yaml_1.dump)(this.riffRaffYaml, { replacer });
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 });
253
208
  }
254
209
  /**
255
- * Write the `riff-raff.yaml` file to disk.
256
- * 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`.
257
211
  */
258
212
  synth() {
259
- const outPath = path_1.default.join(this.outdir, "riff-raff.yaml");
260
- (0, fs_1.writeFileSync)(outPath, this.toYAML());
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
+ });
261
223
  }
262
224
  }
263
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;
264
237
  //# sourceMappingURL=index.js.map