@guardian/cdk 49.1.0-beta.1 → 49.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/lib/constructs/autoscaling/user-data.js +1 -1
  2. package/lib/constructs/autoscaling/user-data.js.map +1 -1
  3. package/lib/constructs/iam/policies/index.d.ts +0 -1
  4. package/lib/constructs/iam/policies/index.d.ts.map +1 -1
  5. package/lib/constructs/iam/policies/index.js +0 -1
  6. package/lib/constructs/iam/policies/index.js.map +1 -1
  7. package/lib/constructs/iam/roles/instance-role.d.ts.map +1 -1
  8. package/lib/constructs/iam/roles/instance-role.js +2 -1
  9. package/lib/constructs/iam/roles/instance-role.js.map +1 -1
  10. package/lib/constructs/s3/index.d.ts +0 -90
  11. package/lib/constructs/s3/index.d.ts.map +1 -1
  12. package/lib/constructs/s3/index.js +1 -33
  13. package/lib/constructs/s3/index.js.map +1 -1
  14. package/lib/experimental/riff-raff-yaml-file/deployments/cloudformation.d.ts +1 -1
  15. package/lib/experimental/riff-raff-yaml-file/deployments/cloudformation.d.ts.map +1 -1
  16. package/lib/experimental/riff-raff-yaml-file/deployments/cloudformation.js +17 -11
  17. package/lib/experimental/riff-raff-yaml-file/deployments/cloudformation.js.map +1 -1
  18. package/lib/experimental/riff-raff-yaml-file/index.d.ts +10 -22
  19. package/lib/experimental/riff-raff-yaml-file/index.d.ts.map +1 -1
  20. package/lib/experimental/riff-raff-yaml-file/index.js +22 -62
  21. package/lib/experimental/riff-raff-yaml-file/index.js.map +1 -1
  22. package/lib/experimental/riff-raff-yaml-file/types.d.ts +1 -1
  23. package/lib/experimental/riff-raff-yaml-file/types.d.ts.map +1 -1
  24. package/lib/experimental/riff-raff-yaml-file/types.js.map +1 -1
  25. package/package.json +21 -21
  26. package/lib/constructs/iam/policies/ssm.d.ts +0 -8
  27. package/lib/constructs/iam/policies/ssm.d.ts.map +0 -1
  28. package/lib/constructs/iam/policies/ssm.js +0 -37
  29. package/lib/constructs/iam/policies/ssm.js.map +0 -1
  30. package/lib/experimental/riff-raff-yaml-file/deployments/s3.d.ts +0 -4
  31. package/lib/experimental/riff-raff-yaml-file/deployments/s3.d.ts.map +0 -1
  32. package/lib/experimental/riff-raff-yaml-file/deployments/s3.js +0 -48
  33. package/lib/experimental/riff-raff-yaml-file/deployments/s3.js.map +0 -1
@@ -18,7 +18,7 @@ class GuUserData {
18
18
  }
19
19
  downloadDistributable(scope, app, props) {
20
20
  const bucketKey = types_1.GuDistributable.getObjectKey(scope, app, props);
21
- const bucket = aws_s3_1.Bucket.fromBucketAttributes(scope, "DistributionBucket", {
21
+ const bucket = aws_s3_1.Bucket.fromBucketAttributes(scope, `DistributionBucket-${app.app}`, {
22
22
  bucketName: core_1.GuDistributionBucketParameter.getInstance(scope).valueAsString,
23
23
  });
24
24
  this.addS3DownloadCommand({
@@ -1 +1 @@
1
- {"version":3,"file":"user-data.js","sourceRoot":"","sources":["../../../src/constructs/autoscaling/user-data.ts"],"names":[],"mappings":";;;AAAA,iDAA+C;AAE/C,+CAA4C;AAC5C,uCAA8C;AAG9C,kCAAwD;AASxD;;;;;;GAMG;AACH,MAAa,UAAU;IAGrB,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAEO,qBAAqB,CAAC,KAAc,EAAE,GAAgB,EAAE,KAA4B;QAC1F,MAAM,SAAS,GAAG,uBAAe,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAElE,MAAM,MAAM,GAAG,eAAM,CAAC,oBAAoB,CAAC,KAAK,EAAE,oBAAoB,EAAE;YACtE,UAAU,EAAE,oCAA6B,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,aAAa;SAC3E,CAAC,CAAC;QAEH,IAAI,CAAC,oBAAoB,CAAC;YACxB,MAAM;YACN,SAAS;YACT,SAAS,EAAE,IAAI,GAAG,CAAC,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE;SAC3C,CAAC,CAAC;IACL,CAAC;IAEO,qBAAqB,CAAC,KAAc,EAAE,GAAW,EAAE,KAAoC;QAC7F,MAAM,MAAM,GAAG,eAAM,CAAC,oBAAoB,CAAC,KAAK,EAAE,GAAG,GAAG,qBAAqB,EAAE;YAC7E,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,aAAa;SACvC,CAAC,CAAC;QAEH,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;YAChC,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAEnD,6EAA6E;YAC7E,IAAI,CAAC,QAAQ,EAAE;gBACb,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;aACvE;YAED,IAAI,CAAC,oBAAoB,CAAC;gBACxB,MAAM;gBACN,SAAS;gBACT,SAAS,EAAE,QAAQ,GAAG,IAAI,QAAQ,EAAE;aACrC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,YAAY,KAAc,EAAE,KAA6B;QACvD,IAAI,CAAC,SAAS,GAAG,kBAAQ,CAAC,QAAQ,EAAE,CAAC;QAErC,IAAI,KAAK,CAAC,aAAa,EAAE;YACvB,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;SACnE;QAED,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;QAC9D,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC;IAC3D,CAAC;IAED,WAAW,CAAC,GAAG,QAAkB;QAC/B,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,QAAQ,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oBAAoB,CAAC,MAAyB;QAC5C,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AA9DD,gCA8DC","sourcesContent":["import { UserData } from \"aws-cdk-lib/aws-ec2\";\nimport type { S3DownloadOptions } from \"aws-cdk-lib/aws-ec2\";\nimport { Bucket } from \"aws-cdk-lib/aws-s3\";\nimport { GuDistributable } from \"../../types\";\nimport type { GuDistributableForEc2 } from \"../../types\";\nimport type { GuPrivateS3ConfigurationProps } from \"../../utils/ec2\";\nimport { GuDistributionBucketParameter } from \"../core\";\nimport type { AppIdentity, GuStack } from \"../core\";\n\nexport type GuUserDataPropsWithApp = GuUserDataProps & AppIdentity;\nexport interface GuUserDataProps {\n distributable: GuDistributableForEc2;\n configuration?: GuPrivateS3ConfigurationProps;\n}\n\n/**\n * An abstraction over UserData to simplify its creation.\n * Especially useful for simple user data where we:\n * - (optional) download config\n * - download distributable\n * - execute distributable\n */\nexport class GuUserData {\n private readonly _userData: UserData;\n\n get userData(): UserData {\n return this._userData;\n }\n\n private downloadDistributable(scope: GuStack, app: AppIdentity, props: GuDistributableForEc2) {\n const bucketKey = GuDistributable.getObjectKey(scope, app, props);\n\n const bucket = Bucket.fromBucketAttributes(scope, \"DistributionBucket\", {\n bucketName: GuDistributionBucketParameter.getInstance(scope).valueAsString,\n });\n\n this.addS3DownloadCommand({\n bucket,\n bucketKey,\n localFile: `/${app.app}/${props.fileName}`,\n });\n }\n\n private downloadConfiguration(scope: GuStack, app: string, props: GuPrivateS3ConfigurationProps) {\n const bucket = Bucket.fromBucketAttributes(scope, `${app}ConfigurationBucket`, {\n bucketName: props.bucket.valueAsString,\n });\n\n props.files.forEach((bucketKey) => {\n const fileName = bucketKey.split(\"/\").slice(-1)[0];\n\n // `fileName` is typed as `string | undefined`. Throw if `fileName` is falsy.\n if (!fileName) {\n throw new Error(\"Failed to create configuration section in UserData\");\n }\n\n this.addS3DownloadCommand({\n bucket,\n bucketKey,\n localFile: `/etc/${app}/${fileName}`,\n });\n });\n }\n\n constructor(scope: GuStack, props: GuUserDataPropsWithApp) {\n this._userData = UserData.forLinux();\n\n if (props.configuration) {\n this.downloadConfiguration(scope, props.app, props.configuration);\n }\n\n this.downloadDistributable(scope, props, props.distributable);\n this.addCommands(props.distributable.executionStatement);\n }\n\n addCommands(...commands: string[]): GuUserData {\n this._userData.addCommands(...commands);\n return this;\n }\n\n addS3DownloadCommand(params: S3DownloadOptions): GuUserData {\n this._userData.addS3DownloadCommand(params);\n return this;\n }\n}\n"]}
1
+ {"version":3,"file":"user-data.js","sourceRoot":"","sources":["../../../src/constructs/autoscaling/user-data.ts"],"names":[],"mappings":";;;AAAA,iDAA+C;AAE/C,+CAA4C;AAC5C,uCAA8C;AAG9C,kCAAwD;AASxD;;;;;;GAMG;AACH,MAAa,UAAU;IAGrB,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAEO,qBAAqB,CAAC,KAAc,EAAE,GAAgB,EAAE,KAA4B;QAC1F,MAAM,SAAS,GAAG,uBAAe,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAElE,MAAM,MAAM,GAAG,eAAM,CAAC,oBAAoB,CAAC,KAAK,EAAE,sBAAsB,GAAG,CAAC,GAAG,EAAE,EAAE;YACjF,UAAU,EAAE,oCAA6B,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,aAAa;SAC3E,CAAC,CAAC;QAEH,IAAI,CAAC,oBAAoB,CAAC;YACxB,MAAM;YACN,SAAS;YACT,SAAS,EAAE,IAAI,GAAG,CAAC,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE;SAC3C,CAAC,CAAC;IACL,CAAC;IAEO,qBAAqB,CAAC,KAAc,EAAE,GAAW,EAAE,KAAoC;QAC7F,MAAM,MAAM,GAAG,eAAM,CAAC,oBAAoB,CAAC,KAAK,EAAE,GAAG,GAAG,qBAAqB,EAAE;YAC7E,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,aAAa;SACvC,CAAC,CAAC;QAEH,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;YAChC,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAEnD,6EAA6E;YAC7E,IAAI,CAAC,QAAQ,EAAE;gBACb,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;aACvE;YAED,IAAI,CAAC,oBAAoB,CAAC;gBACxB,MAAM;gBACN,SAAS;gBACT,SAAS,EAAE,QAAQ,GAAG,IAAI,QAAQ,EAAE;aACrC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,YAAY,KAAc,EAAE,KAA6B;QACvD,IAAI,CAAC,SAAS,GAAG,kBAAQ,CAAC,QAAQ,EAAE,CAAC;QAErC,IAAI,KAAK,CAAC,aAAa,EAAE;YACvB,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;SACnE;QAED,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;QAC9D,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC;IAC3D,CAAC;IAED,WAAW,CAAC,GAAG,QAAkB;QAC/B,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,QAAQ,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oBAAoB,CAAC,MAAyB;QAC5C,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AA9DD,gCA8DC","sourcesContent":["import { UserData } from \"aws-cdk-lib/aws-ec2\";\nimport type { S3DownloadOptions } from \"aws-cdk-lib/aws-ec2\";\nimport { Bucket } from \"aws-cdk-lib/aws-s3\";\nimport { GuDistributable } from \"../../types\";\nimport type { GuDistributableForEc2 } from \"../../types\";\nimport type { GuPrivateS3ConfigurationProps } from \"../../utils/ec2\";\nimport { GuDistributionBucketParameter } from \"../core\";\nimport type { AppIdentity, GuStack } from \"../core\";\n\nexport type GuUserDataPropsWithApp = GuUserDataProps & AppIdentity;\nexport interface GuUserDataProps {\n distributable: GuDistributableForEc2;\n configuration?: GuPrivateS3ConfigurationProps;\n}\n\n/**\n * An abstraction over UserData to simplify its creation.\n * Especially useful for simple user data where we:\n * - (optional) download config\n * - download distributable\n * - execute distributable\n */\nexport class GuUserData {\n private readonly _userData: UserData;\n\n get userData(): UserData {\n return this._userData;\n }\n\n private downloadDistributable(scope: GuStack, app: AppIdentity, props: GuDistributableForEc2) {\n const bucketKey = GuDistributable.getObjectKey(scope, app, props);\n\n const bucket = Bucket.fromBucketAttributes(scope, `DistributionBucket-${app.app}`, {\n bucketName: GuDistributionBucketParameter.getInstance(scope).valueAsString,\n });\n\n this.addS3DownloadCommand({\n bucket,\n bucketKey,\n localFile: `/${app.app}/${props.fileName}`,\n });\n }\n\n private downloadConfiguration(scope: GuStack, app: string, props: GuPrivateS3ConfigurationProps) {\n const bucket = Bucket.fromBucketAttributes(scope, `${app}ConfigurationBucket`, {\n bucketName: props.bucket.valueAsString,\n });\n\n props.files.forEach((bucketKey) => {\n const fileName = bucketKey.split(\"/\").slice(-1)[0];\n\n // `fileName` is typed as `string | undefined`. Throw if `fileName` is falsy.\n if (!fileName) {\n throw new Error(\"Failed to create configuration section in UserData\");\n }\n\n this.addS3DownloadCommand({\n bucket,\n bucketKey,\n localFile: `/etc/${app}/${fileName}`,\n });\n });\n }\n\n constructor(scope: GuStack, props: GuUserDataPropsWithApp) {\n this._userData = UserData.forLinux();\n\n if (props.configuration) {\n this.downloadConfiguration(scope, props.app, props.configuration);\n }\n\n this.downloadDistributable(scope, props, props.distributable);\n this.addCommands(props.distributable.executionStatement);\n }\n\n addCommands(...commands: string[]): GuUserData {\n this._userData.addCommands(...commands);\n return this;\n }\n\n addS3DownloadCommand(params: S3DownloadOptions): GuUserData {\n this._userData.addS3DownloadCommand(params);\n return this;\n }\n}\n"]}
@@ -9,5 +9,4 @@ export * from "./parameter-store-read";
9
9
  export * from "./s3-get-object";
10
10
  export * from "./s3-put-object";
11
11
  export * from "./ses";
12
- export * from "./ssm";
13
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,OAAO,CAAC"}
@@ -25,5 +25,4 @@ __exportStar(require("./parameter-store-read"), exports);
25
25
  __exportStar(require("./s3-get-object"), exports);
26
26
  __exportStar(require("./s3-put-object"), exports);
27
27
  __exportStar(require("./ses"), exports);
28
- __exportStar(require("./ssm"), exports);
29
28
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,gDAA8B;AAC9B,gDAA8B;AAC9B,+CAA6B;AAC7B,iDAA+B;AAC/B,6CAA2B;AAC3B,iDAA+B;AAC/B,yDAAuC;AACvC,kDAAgC;AAChC,kDAAgC;AAChC,wCAAsB;AACtB,wCAAsB","sourcesContent":["export * from \"./anghammarad\";\nexport * from \"./assume-role\";\nexport * from \"./base-policy\";\nexport * from \"./cloudwatch\";\nexport * from \"./describe-ec2\";\nexport * from \"./dynamodb\";\nexport * from \"./log-shipping\";\nexport * from \"./parameter-store-read\";\nexport * from \"./s3-get-object\";\nexport * from \"./s3-put-object\";\nexport * from \"./ses\";\nexport * from \"./ssm\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,gDAA8B;AAC9B,gDAA8B;AAC9B,+CAA6B;AAC7B,iDAA+B;AAC/B,6CAA2B;AAC3B,iDAA+B;AAC/B,yDAAuC;AACvC,kDAAgC;AAChC,kDAAgC;AAChC,wCAAsB","sourcesContent":["export * from \"./anghammarad\";\nexport * from \"./assume-role\";\nexport * from \"./base-policy\";\nexport * from \"./cloudwatch\";\nexport * from \"./describe-ec2\";\nexport * from \"./dynamodb\";\nexport * from \"./log-shipping\";\nexport * from \"./parameter-store-read\";\nexport * from \"./s3-get-object\";\nexport * from \"./s3-put-object\";\nexport * from \"./ses\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"instance-role.d.ts","sourceRoot":"","sources":["../../../../src/constructs/iam/roles/instance-role.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAQvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B,kBAAkB,CAAC,EAAE,QAAQ,EAAE,CAAC;CACjC;AAED,MAAM,MAAM,0BAA0B,GAAG,mBAAmB,GAAG,WAAW,CAAC;;;;;;AAE3E;;;;;;;;;;;;;;GAcG;AACH,qBAAa,cAAe,SAAQ,mBAA2B;gBACjD,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,0BAA0B;CAsB9D"}
1
+ {"version":3,"file":"instance-role.d.ts","sourceRoot":"","sources":["../../../../src/constructs/iam/roles/instance-role.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAOvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B,kBAAkB,CAAC,EAAE,QAAQ,EAAE,CAAC;CACjC;AAED,MAAM,MAAM,0BAA0B,GAAG,mBAAmB,GAAG,WAAW,CAAC;;;;;;AAE3E;;;;;;;;;;;;;;GAcG;AACH,qBAAa,cAAe,SAAQ,mBAA2B;gBACjD,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,0BAA0B;CAwB9D"}
@@ -28,7 +28,6 @@ class GuInstanceRole extends (0, app_aware_construct_1.GuAppAwareConstruct)(role
28
28
  ...props,
29
29
  });
30
30
  const sharedPolicies = [
31
- policies_1.GuSSMRunCommandPolicy.getInstance(scope),
32
31
  policies_1.GuDescribeEC2Policy.getInstance(scope),
33
32
  ...(props.withoutLogShipping ? [] : [policies_1.GuLogShippingPolicy.getInstance(scope)]),
34
33
  ];
@@ -38,7 +37,9 @@ class GuInstanceRole extends (0, app_aware_construct_1.GuAppAwareConstruct)(role
38
37
  new policies_1.GuParameterStoreReadPolicy(scope, props),
39
38
  ...(props.additionalPolicies ? props.additionalPolicies : []),
40
39
  ];
40
+ const managedPolicies = [aws_iam_1.ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore")];
41
41
  policies.forEach((p) => p.attachToRole(this));
42
+ managedPolicies.forEach((p) => this.addManagedPolicy(p));
42
43
  }
43
44
  }
44
45
  exports.GuInstanceRole = GuInstanceRole;
@@ -1 +1 @@
1
- {"version":3,"file":"instance-role.js","sourceRoot":"","sources":["../../../../src/constructs/iam/roles/instance-role.ts"],"names":[],"mappings":";;;AAAA,iDAAuD;AACvD,kFAA+E;AAE/E,0CAMqB;AAErB,mCAAiC;AAgBjC;;;;;;;;;;;;;;GAcG;AACH,MAAa,cAAe,SAAQ,IAAA,yCAAmB,EAAC,cAAM,CAAC;IAC7D,YAAY,KAAc,EAAE,KAAiC;QAC3D,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE;YAC3B,IAAI,EAAE,GAAG;YACT,SAAS,EAAE,IAAI,0BAAgB,CAAC,mBAAmB,CAAC;YACpD,GAAG,KAAK;SACT,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG;YACrB,gCAAqB,CAAC,WAAW,CAAC,KAAK,CAAC;YACxC,8BAAmB,CAAC,WAAW,CAAC,KAAK,CAAC;YACtC,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,8BAAmB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;SAC9E,CAAC;QAEF,MAAM,QAAQ,GAAG;YACf,GAAG,cAAc;YACjB,IAAI,mCAAwB,CAAC,KAAK,EAAE,KAAK,CAAC;YAC1C,IAAI,qCAA0B,CAAC,KAAK,EAAE,KAAK,CAAC;YAC5C,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9D,CAAC;QAEF,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;CACF;AAvBD,wCAuBC","sourcesContent":["import { ServicePrincipal } from \"aws-cdk-lib/aws-iam\";\nimport { GuAppAwareConstruct } from \"../../../utils/mixin/app-aware-construct\";\nimport type { AppIdentity, GuStack } from \"../../core\";\nimport {\n GuDescribeEC2Policy,\n GuGetDistributablePolicy,\n GuLogShippingPolicy,\n GuParameterStoreReadPolicy,\n GuSSMRunCommandPolicy,\n} from \"../policies\";\nimport type { GuPolicy } from \"../policies\";\nimport { GuRole } from \"./roles\";\n\nexport interface GuInstanceRoleProps {\n /**\n * By default, instances are given permissions to write to Kinesis. Set to\n * 'true' to prevent this. Note, disabling will prevent not just application\n * logs being shipped but also anything else - for example, automatic log\n * shipping of Cloud Init and other logs by the cdk-base role in your AMI.\n */\n withoutLogShipping?: boolean;\n\n additionalPolicies?: GuPolicy[];\n}\n\nexport type GuInstanceRolePropsWithApp = GuInstanceRoleProps & AppIdentity;\n\n/**\n * Creates an IAM role with common policies that are needed by most Guardian applications.\n *\n * More specifically:\n * 1. Allows for `ssh` access to an EC2 instance via [ssm-scala](https://github.com/guardian/ssm-scala) (instead of standard `ssh`).\n * 2. Allows EC2 instances to communicate with Wazuh, for security monitoring.\n * 3. Allows EC2 instances to download an artifact from AWS S3, for application deployment.\n * 4. Allows EC2 instances to download private configuration from AWS Parameter Store. See [[`GuParameterStoreReadPolicy`]]\n * for specific details.\n * 5. Allows EC2 instances to write logs into our central ELK stack via Kinesis.\n *\n * If additional IAM permissions are required, create custom policies and pass them in via the `additionalPolicies` prop.\n *\n * If log shipping is not required, opt out by setting the `withoutLogShipping` prop to `true`.\n */\nexport class GuInstanceRole extends GuAppAwareConstruct(GuRole) {\n constructor(scope: GuStack, props: GuInstanceRolePropsWithApp) {\n super(scope, \"InstanceRole\", {\n path: \"/\",\n assumedBy: new ServicePrincipal(\"ec2.amazonaws.com\"),\n ...props,\n });\n\n const sharedPolicies = [\n GuSSMRunCommandPolicy.getInstance(scope),\n GuDescribeEC2Policy.getInstance(scope),\n ...(props.withoutLogShipping ? [] : [GuLogShippingPolicy.getInstance(scope)]),\n ];\n\n const policies = [\n ...sharedPolicies,\n new GuGetDistributablePolicy(scope, props),\n new GuParameterStoreReadPolicy(scope, props),\n ...(props.additionalPolicies ? props.additionalPolicies : []),\n ];\n\n policies.forEach((p) => p.attachToRole(this));\n }\n}\n"]}
1
+ {"version":3,"file":"instance-role.js","sourceRoot":"","sources":["../../../../src/constructs/iam/roles/instance-role.ts"],"names":[],"mappings":";;;AAAA,iDAAsE;AACtE,kFAA+E;AAE/E,0CAKqB;AAErB,mCAAiC;AAgBjC;;;;;;;;;;;;;;GAcG;AACH,MAAa,cAAe,SAAQ,IAAA,yCAAmB,EAAC,cAAM,CAAC;IAC7D,YAAY,KAAc,EAAE,KAAiC;QAC3D,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE;YAC3B,IAAI,EAAE,GAAG;YACT,SAAS,EAAE,IAAI,0BAAgB,CAAC,mBAAmB,CAAC;YACpD,GAAG,KAAK;SACT,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG;YACrB,8BAAmB,CAAC,WAAW,CAAC,KAAK,CAAC;YACtC,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,8BAAmB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;SAC9E,CAAC;QAEF,MAAM,QAAQ,GAAG;YACf,GAAG,cAAc;YACjB,IAAI,mCAAwB,CAAC,KAAK,EAAE,KAAK,CAAC;YAC1C,IAAI,qCAA0B,CAAC,KAAK,EAAE,KAAK,CAAC;YAC5C,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9D,CAAC;QAEF,MAAM,eAAe,GAAG,CAAC,uBAAa,CAAC,wBAAwB,CAAC,8BAA8B,CAAC,CAAC,CAAC;QAEjG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9C,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF;AAzBD,wCAyBC","sourcesContent":["import { ManagedPolicy, ServicePrincipal } from \"aws-cdk-lib/aws-iam\";\nimport { GuAppAwareConstruct } from \"../../../utils/mixin/app-aware-construct\";\nimport type { AppIdentity, GuStack } from \"../../core\";\nimport {\n GuDescribeEC2Policy,\n GuGetDistributablePolicy,\n GuLogShippingPolicy,\n GuParameterStoreReadPolicy,\n} from \"../policies\";\nimport type { GuPolicy } from \"../policies\";\nimport { GuRole } from \"./roles\";\n\nexport interface GuInstanceRoleProps {\n /**\n * By default, instances are given permissions to write to Kinesis. Set to\n * 'true' to prevent this. Note, disabling will prevent not just application\n * logs being shipped but also anything else - for example, automatic log\n * shipping of Cloud Init and other logs by the cdk-base role in your AMI.\n */\n withoutLogShipping?: boolean;\n\n additionalPolicies?: GuPolicy[];\n}\n\nexport type GuInstanceRolePropsWithApp = GuInstanceRoleProps & AppIdentity;\n\n/**\n * Creates an IAM role with common policies that are needed by most Guardian applications.\n *\n * More specifically:\n * 1. Allows for `ssh` access to an EC2 instance via [ssm-scala](https://github.com/guardian/ssm-scala) (instead of standard `ssh`).\n * 2. Allows EC2 instances to communicate with Wazuh, for security monitoring.\n * 3. Allows EC2 instances to download an artifact from AWS S3, for application deployment.\n * 4. Allows EC2 instances to download private configuration from AWS Parameter Store. See [[`GuParameterStoreReadPolicy`]]\n * for specific details.\n * 5. Allows EC2 instances to write logs into our central ELK stack via Kinesis.\n *\n * If additional IAM permissions are required, create custom policies and pass them in via the `additionalPolicies` prop.\n *\n * If log shipping is not required, opt out by setting the `withoutLogShipping` prop to `true`.\n */\nexport class GuInstanceRole extends GuAppAwareConstruct(GuRole) {\n constructor(scope: GuStack, props: GuInstanceRolePropsWithApp) {\n super(scope, \"InstanceRole\", {\n path: \"/\",\n assumedBy: new ServicePrincipal(\"ec2.amazonaws.com\"),\n ...props,\n });\n\n const sharedPolicies = [\n GuDescribeEC2Policy.getInstance(scope),\n ...(props.withoutLogShipping ? [] : [GuLogShippingPolicy.getInstance(scope)]),\n ];\n\n const policies = [\n ...sharedPolicies,\n new GuGetDistributablePolicy(scope, props),\n new GuParameterStoreReadPolicy(scope, props),\n ...(props.additionalPolicies ? props.additionalPolicies : []),\n ];\n\n const managedPolicies = [ManagedPolicy.fromAwsManagedPolicyName(\"AmazonSSMManagedInstanceCore\")];\n\n policies.forEach((p) => p.attachToRole(this));\n managedPolicies.forEach((p) => this.addManagedPolicy(p));\n }\n}\n"]}
@@ -1,7 +1,5 @@
1
- import type { Duration } from "aws-cdk-lib";
2
1
  import type { BucketProps } from "aws-cdk-lib/aws-s3";
3
2
  import { Bucket } from "aws-cdk-lib/aws-s3";
4
- import type { IConstruct } from "constructs";
5
3
  import type { AppIdentity, GuStack } from "../core";
6
4
  export interface GuS3BucketProps extends Omit<BucketProps, "removalPolicy">, AppIdentity {
7
5
  }
@@ -16,93 +14,5 @@ declare const GuS3Bucket_base: {
16
14
  export declare class GuS3Bucket extends GuS3Bucket_base {
17
15
  constructor(scope: GuStack, id: string, props: GuS3BucketProps);
18
16
  }
19
- interface GuS3OriginBucketDeploymentProps {
20
- /**
21
- * Customises the SSM Parameter path, making it stage agnostic.
22
- * Useful when a single bucket is used across multiple stages.
23
- *
24
- * When `false` the path will be `/<STAGE>/<STACK>/<APP>/<APP>-origin-bucket`.
25
- * When `true` the path will be `/<STACK>/<APP>/<APP>-origin-bucket`.
26
- *
27
- * @default false
28
- */
29
- withoutStageAwareness: boolean;
30
- /**
31
- * Used to configure `bucketSsmKeyStageParam` in a generated `riff-raff.yaml` file.
32
- *
33
- * The SSM Parameter path, without a stage prefix.
34
- *
35
- * Not settable by user.
36
- *
37
- * @internal
38
- */
39
- baseParameterName: string;
40
- /**
41
- * Used to configure `cacheControl` in a generated `riff-raff.yaml` file.
42
- * Only needed if you're also using {@link GuRootExperimental}.
43
- *
44
- * Set the cache control header for the uploaded files.
45
- *
46
- * The key is a regular expression to match uploaded files.
47
- * The value is the max-age to set in the `Cache-Control` header.
48
- *
49
- * @example
50
- * To cache all files for one hour:
51
- * ```ts
52
- * { ".*", Duration.hours(1) }
53
- * ```
54
- *
55
- * @default cache nothing
56
- * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types#awss3
57
- */
58
- cacheControl: Record<string, Duration>;
59
- /**
60
- * Used to configure `surrogateControl` in a generated `riff-raff.yaml` file.
61
- * Only needed if you're also using {@link GuRootExperimental}.
62
- *
63
- * Same as [[cacheControl]], but for setting the surrogate-control cache header, which is used by Fastly.
64
- *
65
- * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types#awss3
66
- */
67
- surrogateControl: Record<string, Duration>;
68
- /**
69
- * Used to configure `mimeTypes` in a generated `riff-raff.yaml` file.
70
- * Only needed if you're also using {@link GuRootExperimental}.
71
- *
72
- * A map of file extension to MIME type.
73
- *
74
- * When a file is uploaded with a file extension that is in this map, the Content-Type header will be set to the MIME type provided.
75
- *
76
- * @example
77
- * ```ts
78
- * { "xpi", "application/x-xpinstall" }
79
- * ```
80
- *
81
- * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types#awss3
82
- */
83
- mimeTypes: Record<string, string>;
84
- }
85
- export interface GuS3OriginBucketProps extends GuS3BucketProps, Partial<Omit<GuS3OriginBucketDeploymentProps, "baseParameterName">> {
86
- }
87
- /**
88
- * An S3 bucket for use as an origin for a static site.
89
- * The bucket name will be stored in an SSM Parameter.
90
- * Other infrastructure, or applications, that use this bucket should discover its name by the Parameter.
91
- */
92
- export declare class GuS3OriginBucket extends GuS3Bucket implements IConstruct {
93
- /**
94
- * The name of the created SSM Parameter.
95
- */
96
- readonly parameterName: string;
97
- readonly app: string;
98
- /**
99
- * For internal use only, used to generate a `riff-raff.yaml` file.
100
- *
101
- * @see [[RiffRaffYamlFileExperimental]]
102
- * @internal
103
- */
104
- readonly _deploymentProps: Required<GuS3OriginBucketDeploymentProps>;
105
- constructor(scope: GuStack, id: string, props: GuS3OriginBucketProps);
106
- }
107
17
  export {};
108
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/constructs/s3/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAqB,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEpD,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,EAAE,WAAW;CAAG;;;;;;AAE3F;;GAEG;AACH,qBAAa,UAAW,SAAQ,eAA2B;gBAC7C,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe;CAQ/D;AAED,UAAU,+BAA+B;IACvC;;;;;;;;OAQG;IACH,qBAAqB,EAAE,OAAO,CAAC;IAE/B;;;;;;;;OAQG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAE1B;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEvC;;;;;;;OAOG;IACH,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;OAcG;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,qBACf,SAAQ,eAAe,EACrB,OAAO,CAAC,IAAI,CAAC,+BAA+B,EAAE,mBAAmB,CAAC,CAAC;CAAG;AAE1E;;;;GAIG;AAEH,qBAAa,gBAAiB,SAAQ,UAAW,YAAW,UAAU;IACpE;;OAEG;IACH,SAAgB,aAAa,EAAE,MAAM,CAAC;IAEtC,SAAgB,GAAG,EAAE,MAAM,CAAC;IAE5B;;;;;OAKG;IACH,SAAgB,gBAAgB,EAAE,QAAQ,CAAC,+BAA+B,CAAC,CAAC;gBAEhE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB;CA4BrE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/constructs/s3/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAqB,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEpD,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,EAAE,WAAW;CAAG;;;;;;AAE3F;;GAEG;AACH,qBAAa,UAAW,SAAQ,eAA2B;gBAC7C,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe;CAQ/D"}
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GuS3OriginBucket = exports.GuS3Bucket = void 0;
3
+ exports.GuS3Bucket = void 0;
4
4
  const aws_cdk_lib_1 = require("aws-cdk-lib");
5
5
  const aws_s3_1 = require("aws-cdk-lib/aws-s3");
6
- const aws_ssm_1 = require("aws-cdk-lib/aws-ssm");
7
6
  const app_aware_construct_1 = require("../../utils/mixin/app-aware-construct");
8
7
  /**
9
8
  * A construct to create a bucket with a "retain" policy to prevent it from being deleted. It will be orphaned instead.
@@ -19,35 +18,4 @@ class GuS3Bucket extends (0, app_aware_construct_1.GuAppAwareConstruct)(aws_s3_1
19
18
  }
20
19
  }
21
20
  exports.GuS3Bucket = GuS3Bucket;
22
- /**
23
- * An S3 bucket for use as an origin for a static site.
24
- * The bucket name will be stored in an SSM Parameter.
25
- * Other infrastructure, or applications, that use this bucket should discover its name by the Parameter.
26
- */
27
- // implementing `IConstruct` is a no-op here as `Bucket` ultimately does so already. We explicitly do so to avoid a `SuspiciousTypeOfGuard` warning in `riff-raff-yaml-file/index.ts`.
28
- class GuS3OriginBucket extends GuS3Bucket {
29
- constructor(scope, id, props) {
30
- const { stage, stack } = scope;
31
- const { app, withoutStageAwareness = false, cacheControl = {}, surrogateControl = {}, mimeTypes = {} } = props;
32
- super(scope, id, props);
33
- this.app = app;
34
- const stageAgnosticParameterParts = [stack, app, `${app}-origin-bucket`];
35
- const parameterParts = withoutStageAwareness
36
- ? stageAgnosticParameterParts
37
- : [stage, ...stageAgnosticParameterParts];
38
- this.parameterName = `/${parameterParts.join("/")}`;
39
- new aws_ssm_1.StringParameter(scope, `${id}-ssm-param`, {
40
- parameterName: this.parameterName,
41
- stringValue: this.bucketName,
42
- });
43
- this._deploymentProps = {
44
- withoutStageAwareness,
45
- cacheControl,
46
- surrogateControl,
47
- mimeTypes,
48
- baseParameterName: `/${stageAgnosticParameterParts.join("/")}`,
49
- };
50
- }
51
- }
52
- exports.GuS3OriginBucket = GuS3OriginBucket;
53
21
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/constructs/s3/index.ts"],"names":[],"mappings":";;;AACA,6CAA4C;AAE5C,+CAA+D;AAC/D,iDAAsD;AAEtD,+EAA4E;AAK5E;;GAEG;AACH,MAAa,UAAW,SAAQ,IAAA,yCAAmB,EAAC,eAAM,CAAC;IACzD,YAAY,KAAc,EAAE,EAAU,EAAE,KAAsB;QAC5D,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,aAAa,EAAE,2BAAa,CAAC,MAAM;YACnC,gBAAgB,EAAE,KAAK;YACvB,iBAAiB,EAAE,0BAAiB,CAAC,SAAS;YAC9C,GAAG,KAAK;SACT,CAAC,CAAC;IACL,CAAC;CACF;AATD,gCASC;AA6ED;;;;GAIG;AACH,sLAAsL;AACtL,MAAa,gBAAiB,SAAQ,UAAU;IAgB9C,YAAY,KAAc,EAAE,EAAU,EAAE,KAA4B;QAClE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;QAC/B,MAAM,EAAE,GAAG,EAAE,qBAAqB,GAAG,KAAK,EAAE,YAAY,GAAG,EAAE,EAAE,gBAAgB,GAAG,EAAE,EAAE,SAAS,GAAG,EAAE,EAAE,GAAG,KAAK,CAAC;QAE/G,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAExB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QAEf,MAAM,2BAA2B,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,gBAAgB,CAAC,CAAC;QACzE,MAAM,cAAc,GAAG,qBAAqB;YAC1C,CAAC,CAAC,2BAA2B;YAC7B,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,2BAA2B,CAAC,CAAC;QAE5C,IAAI,CAAC,aAAa,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAEpD,IAAI,yBAAe,CAAC,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE;YAC5C,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,WAAW,EAAE,IAAI,CAAC,UAAU;SAC7B,CAAC,CAAC;QAEH,IAAI,CAAC,gBAAgB,GAAG;YACtB,qBAAqB;YACrB,YAAY;YACZ,gBAAgB;YAChB,SAAS;YACT,iBAAiB,EAAE,IAAI,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;SAC/D,CAAC;IACJ,CAAC;CACF;AA5CD,4CA4CC","sourcesContent":["import type { Duration } from \"aws-cdk-lib\";\nimport { RemovalPolicy } from \"aws-cdk-lib\";\nimport type { BucketProps } from \"aws-cdk-lib/aws-s3\";\nimport { BlockPublicAccess, Bucket } from \"aws-cdk-lib/aws-s3\";\nimport { StringParameter } from \"aws-cdk-lib/aws-ssm\";\nimport type { IConstruct } from \"constructs\";\nimport { GuAppAwareConstruct } from \"../../utils/mixin/app-aware-construct\";\nimport type { AppIdentity, GuStack } from \"../core\";\n\nexport interface GuS3BucketProps extends Omit<BucketProps, \"removalPolicy\">, AppIdentity {}\n\n/**\n * A construct to create a bucket with a \"retain\" policy to prevent it from being deleted. It will be orphaned instead.\n */\nexport class GuS3Bucket extends GuAppAwareConstruct(Bucket) {\n constructor(scope: GuStack, id: string, props: GuS3BucketProps) {\n super(scope, id, {\n removalPolicy: RemovalPolicy.RETAIN,\n publicReadAccess: false,\n blockPublicAccess: BlockPublicAccess.BLOCK_ALL,\n ...props,\n });\n }\n}\n\ninterface GuS3OriginBucketDeploymentProps {\n /**\n * Customises the SSM Parameter path, making it stage agnostic.\n * Useful when a single bucket is used across multiple stages.\n *\n * When `false` the path will be `/<STAGE>/<STACK>/<APP>/<APP>-origin-bucket`.\n * When `true` the path will be `/<STACK>/<APP>/<APP>-origin-bucket`.\n *\n * @default false\n */\n withoutStageAwareness: boolean;\n\n /**\n * Used to configure `bucketSsmKeyStageParam` in a generated `riff-raff.yaml` file.\n *\n * The SSM Parameter path, without a stage prefix.\n *\n * Not settable by user.\n *\n * @internal\n */\n baseParameterName: string;\n\n /**\n * Used to configure `cacheControl` in a generated `riff-raff.yaml` file.\n * Only needed if you're also using {@link GuRootExperimental}.\n *\n * Set the cache control header for the uploaded files.\n *\n * The key is a regular expression to match uploaded files.\n * The value is the max-age to set in the `Cache-Control` header.\n *\n * @example\n * To cache all files for one hour:\n * ```ts\n * { \".*\", Duration.hours(1) }\n * ```\n *\n * @default cache nothing\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types#awss3\n */\n cacheControl: Record<string, Duration>;\n\n /**\n * Used to configure `surrogateControl` in a generated `riff-raff.yaml` file.\n * Only needed if you're also using {@link GuRootExperimental}.\n *\n * Same as [[cacheControl]], but for setting the surrogate-control cache header, which is used by Fastly.\n *\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types#awss3\n */\n surrogateControl: Record<string, Duration>;\n\n /**\n * Used to configure `mimeTypes` in a generated `riff-raff.yaml` file.\n * Only needed if you're also using {@link GuRootExperimental}.\n *\n * A map of file extension to MIME type.\n *\n * When a file is uploaded with a file extension that is in this map, the Content-Type header will be set to the MIME type provided.\n *\n * @example\n * ```ts\n * { \"xpi\", \"application/x-xpinstall\" }\n * ```\n *\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types#awss3\n */\n mimeTypes: Record<string, string>;\n}\n\nexport interface GuS3OriginBucketProps\n extends GuS3BucketProps,\n Partial<Omit<GuS3OriginBucketDeploymentProps, \"baseParameterName\">> {}\n\n/**\n * An S3 bucket for use as an origin for a static site.\n * The bucket name will be stored in an SSM Parameter.\n * Other infrastructure, or applications, that use this bucket should discover its name by the Parameter.\n */\n// implementing `IConstruct` is a no-op here as `Bucket` ultimately does so already. We explicitly do so to avoid a `SuspiciousTypeOfGuard` warning in `riff-raff-yaml-file/index.ts`.\nexport class GuS3OriginBucket extends GuS3Bucket implements IConstruct {\n /**\n * The name of the created SSM Parameter.\n */\n public readonly parameterName: string;\n\n public readonly app: string;\n\n /**\n * For internal use only, used to generate a `riff-raff.yaml` file.\n *\n * @see [[RiffRaffYamlFileExperimental]]\n * @internal\n */\n public readonly _deploymentProps: Required<GuS3OriginBucketDeploymentProps>;\n\n constructor(scope: GuStack, id: string, props: GuS3OriginBucketProps) {\n const { stage, stack } = scope;\n const { app, withoutStageAwareness = false, cacheControl = {}, surrogateControl = {}, mimeTypes = {} } = props;\n\n super(scope, id, props);\n\n this.app = app;\n\n const stageAgnosticParameterParts = [stack, app, `${app}-origin-bucket`];\n const parameterParts = withoutStageAwareness\n ? stageAgnosticParameterParts\n : [stage, ...stageAgnosticParameterParts];\n\n this.parameterName = `/${parameterParts.join(\"/\")}`;\n\n new StringParameter(scope, `${id}-ssm-param`, {\n parameterName: this.parameterName,\n stringValue: this.bucketName,\n });\n\n this._deploymentProps = {\n withoutStageAwareness,\n cacheControl,\n surrogateControl,\n mimeTypes,\n baseParameterName: `/${stageAgnosticParameterParts.join(\"/\")}`,\n };\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/constructs/s3/index.ts"],"names":[],"mappings":";;;AAAA,6CAA4C;AAE5C,+CAA+D;AAC/D,+EAA4E;AAK5E;;GAEG;AACH,MAAa,UAAW,SAAQ,IAAA,yCAAmB,EAAC,eAAM,CAAC;IACzD,YAAY,KAAc,EAAE,EAAU,EAAE,KAAsB;QAC5D,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,aAAa,EAAE,2BAAa,CAAC,MAAM;YACnC,gBAAgB,EAAE,KAAK;YACvB,iBAAiB,EAAE,0BAAiB,CAAC,SAAS;YAC9C,GAAG,KAAK;SACT,CAAC,CAAC;IACL,CAAC;CACF;AATD,gCASC","sourcesContent":["import { RemovalPolicy } from \"aws-cdk-lib\";\nimport type { BucketProps } from \"aws-cdk-lib/aws-s3\";\nimport { BlockPublicAccess, Bucket } from \"aws-cdk-lib/aws-s3\";\nimport { GuAppAwareConstruct } from \"../../utils/mixin/app-aware-construct\";\nimport type { AppIdentity, GuStack } from \"../core\";\n\nexport interface GuS3BucketProps extends Omit<BucketProps, \"removalPolicy\">, AppIdentity {}\n\n/**\n * A construct to create a bucket with a \"retain\" policy to prevent it from being deleted. It will be orphaned instead.\n */\nexport class GuS3Bucket extends GuAppAwareConstruct(Bucket) {\n constructor(scope: GuStack, id: string, props: GuS3BucketProps) {\n super(scope, id, {\n removalPolicy: RemovalPolicy.RETAIN,\n publicReadAccess: false,\n blockPublicAccess: BlockPublicAccess.BLOCK_ALL,\n ...props,\n });\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { GuAutoScalingGroup } from "../../../constructs/autoscaling";
2
2
  import type { CdkStacksDifferingOnlyByStage, RiffRaffDeployment, RiffRaffDeploymentProps } from "../types";
3
3
  export declare function cloudFormationDeployment(cdkStacks: CdkStacksDifferingOnlyByStage, dependencies: RiffRaffDeployment[], contentDirectory: string): RiffRaffDeployment;
4
- export declare function addAmiParametersToCloudFormationDeployment(cfnDeployment: RiffRaffDeployment, asg: GuAutoScalingGroup): RiffRaffDeploymentProps;
4
+ export declare function addAmiParametersToCloudFormationDeployment(cfnDeployment: RiffRaffDeployment, autoScalingGroups: GuAutoScalingGroup[]): RiffRaffDeploymentProps;
5
5
  //# sourceMappingURL=cloudformation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cloudformation.d.ts","sourceRoot":"","sources":["../../../../src/experimental/riff-raff-yaml-file/deployments/cloudformation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,KAAK,EAAE,6BAA6B,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAE3G,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,6BAA6B,EACxC,YAAY,EAAE,kBAAkB,EAAE,EAClC,gBAAgB,EAAE,MAAM,GACvB,kBAAkB,CAwCpB;AAED,wBAAgB,0CAA0C,CACxD,aAAa,EAAE,kBAAkB,EACjC,GAAG,EAAE,kBAAkB,GACtB,uBAAuB,CAmBzB"}
1
+ {"version":3,"file":"cloudformation.d.ts","sourceRoot":"","sources":["../../../../src/experimental/riff-raff-yaml-file/deployments/cloudformation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,KAAK,EAAE,6BAA6B,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAE3G,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,6BAA6B,EACxC,YAAY,EAAE,kBAAkB,EAAE,EAClC,gBAAgB,EAAE,MAAM,GACvB,kBAAkB,CAwCpB;AAED,wBAAgB,0CAA0C,CACxD,aAAa,EAAE,kBAAkB,EACjC,iBAAiB,EAAE,kBAAkB,EAAE,GACtC,uBAAuB,CA2BzB"}
@@ -32,21 +32,27 @@ function cloudFormationDeployment(cdkStacks, dependencies, contentDirectory) {
32
32
  };
33
33
  }
34
34
  exports.cloudFormationDeployment = cloudFormationDeployment;
35
- function addAmiParametersToCloudFormationDeployment(cfnDeployment, asg) {
36
- const { imageRecipe, app, amiParameter } = asg;
37
- if (!imageRecipe) {
38
- throw new Error(`Unable to produce a working riff-raff.yaml file; imageRecipe missing from ASG ${app}`);
39
- }
40
- return {
41
- ...cfnDeployment.props,
42
- parameters: {
43
- ...cfnDeployment.props.parameters,
44
- amiParameter: amiParameter.node.id,
45
- amiTags: {
35
+ function addAmiParametersToCloudFormationDeployment(cfnDeployment, autoScalingGroups) {
36
+ const amiParametersToTags = autoScalingGroups.reduce((acc, asg) => {
37
+ const { imageRecipe, app, amiParameter } = asg;
38
+ if (!imageRecipe) {
39
+ throw new Error(`Unable to produce a working riff-raff.yaml file; imageRecipe missing from ASG ${app}`);
40
+ }
41
+ return {
42
+ ...acc,
43
+ [amiParameter.node.id]: {
46
44
  BuiltBy: "amigo",
47
45
  Recipe: imageRecipe,
48
46
  AmigoStage: "PROD",
49
47
  },
48
+ };
49
+ }, {});
50
+ return {
51
+ ...cfnDeployment.props,
52
+ parameters: {
53
+ ...cfnDeployment.props.parameters,
54
+ // only add the `amiParametersToTags` property if there are some
55
+ ...(autoScalingGroups.length > 0 && { amiParametersToTags }),
50
56
  },
51
57
  };
52
58
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cloudformation.js","sourceRoot":"","sources":["../../../../src/experimental/riff-raff-yaml-file/deployments/cloudformation.ts"],"names":[],"mappings":";;;AAGA,SAAgB,wBAAwB,CACtC,SAAwC,EACxC,YAAkC,EAClC,gBAAwB;IAExB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE;QAC1B,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;KAC1F;IAED,qHAAqH;IACrH,8GAA8G;IAC9G,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;IAC/B,MAAM,EACJ,MAAM,EACN,KAAK,EACL,WAAW,EAAE,EAAE,IAAI,EAAE,GACtB,GAAG,QAAQ,CAAC;IAEb,yFAAyF;IACzF,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IAE9E,MAAM,kBAAkB,GAAG,SAAS,CAAC,MAAM,CACzC,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC;QACjC,GAAG,GAAG;QACN,CAAC,KAAK,CAAC,EAAE,YAAY;KACtB,CAAC,EACF,EAAE,CACH,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACtD,KAAK,EAAE;YACL,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;YAC1B,MAAM,EAAE,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;YACxB,GAAG,EAAE,cAAc;YACnB,gBAAgB;YAChB,UAAU,EAAE;gBACV,kBAAkB;aACnB;YACD,yDAAyD;YACzD,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;SACvF;KACF,CAAC;AACJ,CAAC;AA5CD,4DA4CC;AAED,SAAgB,0CAA0C,CACxD,aAAiC,EACjC,GAAuB;IAEvB,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,GAAG,CAAC;IAE/C,IAAI,CAAC,WAAW,EAAE;QAChB,MAAM,IAAI,KAAK,CAAC,iFAAiF,GAAG,EAAE,CAAC,CAAC;KACzG;IAED,OAAO;QACL,GAAG,aAAa,CAAC,KAAK;QACtB,UAAU,EAAE;YACV,GAAG,aAAa,CAAC,KAAK,CAAC,UAAU;YACjC,YAAY,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE;YAClC,OAAO,EAAE;gBACP,OAAO,EAAE,OAAO;gBAChB,MAAM,EAAE,WAAW;gBACnB,UAAU,EAAE,MAAM;aACnB;SACF;KACF,CAAC;AACJ,CAAC;AAtBD,gGAsBC","sourcesContent":["import type { GuAutoScalingGroup } from \"../../../constructs/autoscaling\";\nimport type { CdkStacksDifferingOnlyByStage, RiffRaffDeployment, RiffRaffDeploymentProps } from \"../types\";\n\nexport function cloudFormationDeployment(\n cdkStacks: CdkStacksDifferingOnlyByStage,\n dependencies: RiffRaffDeployment[],\n contentDirectory: string\n): RiffRaffDeployment {\n if (cdkStacks.length === 0) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n // The stacks in `cdkStacks` only differ by stage, so we can just use the first item in the list for key information.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `cdkStacks` is checked above\n const cdkStack = cdkStacks[0]!;\n const {\n region,\n stack,\n constructor: { name },\n } = cdkStack;\n\n // TODO remove `lodash.kebabcase` dep as it's not that much code to kebab-ise a string...\n const kebabClassName = name.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n\n const templateStagePaths = cdkStacks.reduce(\n (acc, { stage, templateFile }) => ({\n ...acc,\n [stage]: templateFile,\n }),\n {}\n );\n\n return {\n name: [\"cfn\", region, stack, kebabClassName].join(\"-\"),\n props: {\n type: \"cloud-formation\",\n regions: new Set([region]),\n stacks: new Set([stack]),\n app: kebabClassName,\n contentDirectory,\n parameters: {\n templateStagePaths,\n },\n // only add the `dependencies` property if there are some\n ...(dependencies.length > 0 && { dependencies: dependencies.map(({ name }) => name) }),\n },\n };\n}\n\nexport function addAmiParametersToCloudFormationDeployment(\n cfnDeployment: RiffRaffDeployment,\n asg: GuAutoScalingGroup\n): RiffRaffDeploymentProps {\n const { imageRecipe, app, amiParameter } = asg;\n\n if (!imageRecipe) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; imageRecipe missing from ASG ${app}`);\n }\n\n return {\n ...cfnDeployment.props,\n parameters: {\n ...cfnDeployment.props.parameters,\n amiParameter: amiParameter.node.id,\n amiTags: {\n BuiltBy: \"amigo\",\n Recipe: imageRecipe,\n AmigoStage: \"PROD\",\n },\n },\n };\n}\n"]}
1
+ {"version":3,"file":"cloudformation.js","sourceRoot":"","sources":["../../../../src/experimental/riff-raff-yaml-file/deployments/cloudformation.ts"],"names":[],"mappings":";;;AAGA,SAAgB,wBAAwB,CACtC,SAAwC,EACxC,YAAkC,EAClC,gBAAwB;IAExB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE;QAC1B,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;KAC1F;IAED,qHAAqH;IACrH,8GAA8G;IAC9G,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;IAC/B,MAAM,EACJ,MAAM,EACN,KAAK,EACL,WAAW,EAAE,EAAE,IAAI,EAAE,GACtB,GAAG,QAAQ,CAAC;IAEb,yFAAyF;IACzF,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IAE9E,MAAM,kBAAkB,GAAG,SAAS,CAAC,MAAM,CACzC,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC;QACjC,GAAG,GAAG;QACN,CAAC,KAAK,CAAC,EAAE,YAAY;KACtB,CAAC,EACF,EAAE,CACH,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACtD,KAAK,EAAE;YACL,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;YAC1B,MAAM,EAAE,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;YACxB,GAAG,EAAE,cAAc;YACnB,gBAAgB;YAChB,UAAU,EAAE;gBACV,kBAAkB;aACnB;YACD,yDAAyD;YACzD,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;SACvF;KACF,CAAC;AACJ,CAAC;AA5CD,4DA4CC;AAED,SAAgB,0CAA0C,CACxD,aAAiC,EACjC,iBAAuC;IAEvC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAChE,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,GAAG,CAAC;QAE/C,IAAI,CAAC,WAAW,EAAE;YAChB,MAAM,IAAI,KAAK,CAAC,iFAAiF,GAAG,EAAE,CAAC,CAAC;SACzG;QAED,OAAO;YACL,GAAG,GAAG;YACN,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;gBACtB,OAAO,EAAE,OAAO;gBAChB,MAAM,EAAE,WAAW;gBACnB,UAAU,EAAE,MAAM;aACnB;SACF,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO;QACL,GAAG,aAAa,CAAC,KAAK;QACtB,UAAU,EAAE;YACV,GAAG,aAAa,CAAC,KAAK,CAAC,UAAU;YAEjC,gEAAgE;YAChE,GAAG,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,mBAAmB,EAAE,CAAC;SAC7D;KACF,CAAC;AACJ,CAAC;AA9BD,gGA8BC","sourcesContent":["import type { GuAutoScalingGroup } from \"../../../constructs/autoscaling\";\nimport type { CdkStacksDifferingOnlyByStage, RiffRaffDeployment, RiffRaffDeploymentProps } from \"../types\";\n\nexport function cloudFormationDeployment(\n cdkStacks: CdkStacksDifferingOnlyByStage,\n dependencies: RiffRaffDeployment[],\n contentDirectory: string\n): RiffRaffDeployment {\n if (cdkStacks.length === 0) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n // The stacks in `cdkStacks` only differ by stage, so we can just use the first item in the list for key information.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `cdkStacks` is checked above\n const cdkStack = cdkStacks[0]!;\n const {\n region,\n stack,\n constructor: { name },\n } = cdkStack;\n\n // TODO remove `lodash.kebabcase` dep as it's not that much code to kebab-ise a string...\n const kebabClassName = name.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n\n const templateStagePaths = cdkStacks.reduce(\n (acc, { stage, templateFile }) => ({\n ...acc,\n [stage]: templateFile,\n }),\n {}\n );\n\n return {\n name: [\"cfn\", region, stack, kebabClassName].join(\"-\"),\n props: {\n type: \"cloud-formation\",\n regions: new Set([region]),\n stacks: new Set([stack]),\n app: kebabClassName,\n contentDirectory,\n parameters: {\n templateStagePaths,\n },\n // only add the `dependencies` property if there are some\n ...(dependencies.length > 0 && { dependencies: dependencies.map(({ name }) => name) }),\n },\n };\n}\n\nexport function addAmiParametersToCloudFormationDeployment(\n cfnDeployment: RiffRaffDeployment,\n autoScalingGroups: GuAutoScalingGroup[]\n): RiffRaffDeploymentProps {\n const amiParametersToTags = autoScalingGroups.reduce((acc, asg) => {\n const { imageRecipe, app, amiParameter } = asg;\n\n if (!imageRecipe) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; imageRecipe missing from ASG ${app}`);\n }\n\n return {\n ...acc,\n [amiParameter.node.id]: {\n BuiltBy: \"amigo\",\n Recipe: imageRecipe,\n AmigoStage: \"PROD\",\n },\n };\n }, {});\n\n return {\n ...cfnDeployment.props,\n parameters: {\n ...cfnDeployment.props.parameters,\n\n // only add the `amiParametersToTags` property if there are some\n ...(autoScalingGroups.length > 0 && { amiParametersToTags }),\n },\n };\n}\n"]}
@@ -9,7 +9,6 @@ import type { App } from "aws-cdk-lib";
9
9
  * - Multiple regions
10
10
  * - Lambda applications
11
11
  * - EC2 (autoscaling) applications
12
- * - Upload of static files to S3
13
12
  *
14
13
  * For lambda applications, 3 deployments will be defined:
15
14
  * 1. Lambda upload (`aws-lambda`, `action: [uploadLambda]`)
@@ -18,13 +17,9 @@ import type { App } from "aws-cdk-lib";
18
17
  *
19
18
  * For EC2 applications, 3 deployments will be defined:
20
19
  * 1. Artifact upload (`autoscaling`, `action: [uploadArtifacts]`)
21
- * 2. CloudFormation deploy (`cloud-formation`)
20
+ * 2. CloudFormation deploy (`cloud-formation`)
22
21
  * 3. Autoscaling deploy (`autoscaling`, `action: [deploy]`)
23
22
  *
24
- * For S3 uploads, 2 deployments will be defined:
25
- * 1. Artifact upload (`aws-s3`, `action: [uploadStaticFiles]`)
26
- * 2. CloudFormation deploy (`cloud-formation`)
27
- *
28
23
  * It assumes a Riff-Raff bundle structure as follows:
29
24
  *
30
25
  * ```
@@ -33,12 +28,8 @@ import type { App } from "aws-cdk-lib";
33
28
  * │ └── MyApplication.template.json
34
29
  * ├── my-application
35
30
  * │ └── my-application.deb
36
- * ├── my-lambda
37
- * │ └── my-lambda.zip
38
- * └── my-static-site
39
- * ├── index.html
40
- * ├── main.js
41
- * └── index.css
31
+ * └── my-lambda
32
+ * └── my-lambda.zip
42
33
  * ```
43
34
  *
44
35
  * That is, all CloudFormation templates are in a `cdk.out` directory, and there is a directory per app.
@@ -61,7 +52,7 @@ export declare class RiffRaffYamlFileExperimental {
61
52
  private isCdkStackPresent;
62
53
  /**
63
54
  * Check there are the appropriate number of `GuStack`s.
64
- * Expect to find an instance for each combination of `GuStack`, `stack`, `region`, and `stage`.
55
+ * Expect to find an instance for each combination of `stack`, and `stage`.
65
56
  *
66
57
  * If not valid, a message is logged describing what is missing to aid debugging.
67
58
  *
@@ -103,14 +94,12 @@ export declare class RiffRaffYamlFileExperimental {
103
94
  * ```log
104
95
  * Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)
105
96
  *
106
- * For the class: MyApplicationStack
107
- *
108
- * ┌───────────────┬────────────────────────────┐
109
- * │ (index) │ eu-west-1 │
110
- * ├───────────────┼────────────────────────────┤
111
- * │ deploy │ { CODE: '✅', PROD: '✅' } │
112
- * │ media-service │ { CODE: '❌', PROD: '✅' } │
113
- * └───────────────┴────────────────────────────┘
97
+ * ┌───────────────┬──────┬──────┐
98
+ * │ (index) │ CODE │ PROD │
99
+ * ├───────────────┼──────┼──────┤
100
+ * │ deploy │ '✅' │ '✅' │
101
+ * │ media-service │ '❌' │ '✅' │
102
+ * └───────────────┴──────┴──────┘
114
103
  * ```
115
104
  *
116
105
  * @private
@@ -119,7 +108,6 @@ export declare class RiffRaffYamlFileExperimental {
119
108
  private validateAllRegionsAreResolved;
120
109
  private getLambdas;
121
110
  private getAutoScalingGroups;
122
- private getOriginBuckets;
123
111
  constructor(app: App);
124
112
  /**
125
113
  * The `riff-raff.yaml` file as a string.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAyBvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,qBAAa,4BAA4B;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAY;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;IAEtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,OAAO,CAAC,iBAAiB;IAqBzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuDG;IACH,OAAO,CAAC,mBAAmB;IAkD3B,OAAO,CAAC,6BAA6B;IAQrC,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,gBAAgB;gBAMZ,GAAG,EAAE,GAAG;IAoEpB;;;OAGG;IACH,MAAM,IAAI,MAAM;IAiBhB;;;OAGG;IACH,KAAK,IAAI,IAAI;CAId"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAqBvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,4BAA4B;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAY;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;IAEtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,OAAO,CAAC,iBAAiB;IASzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqDG;IACH,OAAO,CAAC,mBAAmB;IAiC3B,OAAO,CAAC,6BAA6B;IAQrC,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,oBAAoB;gBAKhB,GAAG,EAAE,GAAG;IAiEpB;;;OAGG;IACH,MAAM,IAAI,MAAM;IAiBhB;;;OAGG;IACH,KAAK,IAAI,IAAI;CAId"}
@@ -7,16 +7,13 @@ exports.RiffRaffYamlFileExperimental = 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");
10
- const chalk_1 = __importDefault(require("chalk"));
11
10
  const js_yaml_1 = require("js-yaml");
12
11
  const autoscaling_1 = require("../../constructs/autoscaling");
13
12
  const core_1 = require("../../constructs/core");
14
13
  const lambda_1 = require("../../constructs/lambda");
15
- const s3_1 = require("../../constructs/s3");
16
14
  const autoscaling_2 = require("./deployments/autoscaling");
17
15
  const cloudformation_1 = require("./deployments/cloudformation");
18
16
  const lambda_2 = require("./deployments/lambda");
19
- const s3_2 = require("./deployments/s3");
20
17
  const group_by_1 = require("./group-by");
21
18
  /**
22
19
  * A class that creates a `riff-raff.yaml` file.
@@ -28,7 +25,6 @@ const group_by_1 = require("./group-by");
28
25
  * - Multiple regions
29
26
  * - Lambda applications
30
27
  * - EC2 (autoscaling) applications
31
- * - Upload of static files to S3
32
28
  *
33
29
  * For lambda applications, 3 deployments will be defined:
34
30
  * 1. Lambda upload (`aws-lambda`, `action: [uploadLambda]`)
@@ -37,13 +33,9 @@ const group_by_1 = require("./group-by");
37
33
  *
38
34
  * For EC2 applications, 3 deployments will be defined:
39
35
  * 1. Artifact upload (`autoscaling`, `action: [uploadArtifacts]`)
40
- * 2. CloudFormation deploy (`cloud-formation`)
36
+ * 2. CloudFormation deploy (`cloud-formation`)
41
37
  * 3. Autoscaling deploy (`autoscaling`, `action: [deploy]`)
42
38
  *
43
- * For S3 uploads, 2 deployments will be defined:
44
- * 1. Artifact upload (`aws-s3`, `action: [uploadStaticFiles]`)
45
- * 2. CloudFormation deploy (`cloud-formation`)
46
- *
47
39
  * It assumes a Riff-Raff bundle structure as follows:
48
40
  *
49
41
  * ```
@@ -52,12 +44,8 @@ const group_by_1 = require("./group-by");
52
44
  * │ └── MyApplication.template.json
53
45
  * ├── my-application
54
46
  * │ └── my-application.deb
55
- * ├── my-lambda
56
- * │ └── my-lambda.zip
57
- * └── my-static-site
58
- * ├── index.html
59
- * ├── main.js
60
- * └── index.css
47
+ * └── my-lambda
48
+ * └── my-lambda.zip
61
49
  * ```
62
50
  *
63
51
  * That is, all CloudFormation templates are in a `cdk.out` directory, and there is a directory per app.
@@ -71,16 +59,16 @@ const group_by_1 = require("./group-by");
71
59
  * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types
72
60
  */
73
61
  class RiffRaffYamlFileExperimental {
74
- isCdkStackPresent(expectedClassName, expectedStack, expectedRegion, expectedStage) {
62
+ isCdkStackPresent(expectedStack, expectedStage) {
75
63
  const matches = this.allCdkStacks.find((cdkStack) => {
76
- const { constructor: { name }, stack, stage, region, } = cdkStack;
77
- return (name === expectedClassName && stack === expectedStack && stage === expectedStage && region === expectedRegion);
64
+ const { stack, stage } = cdkStack;
65
+ return stack === expectedStack && stage === expectedStage;
78
66
  });
79
67
  return !!matches;
80
68
  }
81
69
  /**
82
70
  * Check there are the appropriate number of `GuStack`s.
83
- * Expect to find an instance for each combination of `GuStack`, `stack`, `region`, and `stage`.
71
+ * Expect to find an instance for each combination of `stack`, and `stage`.
84
72
  *
85
73
  * If not valid, a message is logged describing what is missing to aid debugging.
86
74
  *
@@ -122,55 +110,36 @@ class RiffRaffYamlFileExperimental {
122
110
  * ```log
123
111
  * Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)
124
112
  *
125
- * For the class: MyApplicationStack
126
- *
127
- * ┌───────────────┬────────────────────────────┐
128
- * │ (index) │ eu-west-1 │
129
- * ├───────────────┼────────────────────────────┤
130
- * │ deploy │ { CODE: '✅', PROD: '✅' } │
131
- * │ media-service │ { CODE: '❌', PROD: '✅' } │
132
- * └───────────────┴────────────────────────────┘
113
+ * ┌───────────────┬──────┬──────┐
114
+ * │ (index) │ CODE │ PROD │
115
+ * ├───────────────┼──────┼──────┤
116
+ * │ deploy │ '✅' │ '✅' │
117
+ * │ media-service │ '❌' │ '✅' │
118
+ * └───────────────┴──────┴──────┘
133
119
  * ```
134
120
  *
135
121
  * @private
136
122
  */
137
123
  validateStacksInApp() {
138
- const { allCdkStacks, allStackTags, allStageTags, allRegions } = this;
139
- const checks = allCdkStacks.reduce((accClassName, { constructor: { name } }) => {
124
+ const { allStackTags, allStageTags } = this;
125
+ const checks = allStackTags.reduce((accStackTag, stackTag) => {
140
126
  return {
141
- ...accClassName,
142
- [name]: allStackTags.reduce((accStackTag, stackTag) => {
127
+ ...accStackTag,
128
+ [stackTag]: allStageTags.reduce((accStageTag, stageTag) => {
143
129
  return {
144
- ...accStackTag,
145
- [stackTag]: allRegions.reduce((accRegion, region) => {
146
- return {
147
- ...accRegion,
148
- [region]: allStageTags.reduce((accStageTag, stageTag) => {
149
- return {
150
- ...accStageTag,
151
- [stageTag]: this.isCdkStackPresent(name, stackTag, region, stageTag) ? "✅" : "❌",
152
- };
153
- }, {}),
154
- };
155
- }, {}),
130
+ ...accStageTag,
131
+ [stageTag]: this.isCdkStackPresent(stackTag, stageTag) ? "✅" : "❌",
156
132
  };
157
133
  }, {}),
158
134
  };
159
135
  }, {});
160
136
  const missingDefinitions = Object.values(checks).flatMap((groupedByStackTag) => {
161
- return Object.values(groupedByStackTag).flatMap((groupedByRegion) => {
162
- return Object.values(groupedByRegion).flatMap((groupedByStage) => {
163
- return Object.values(groupedByStage).filter((_) => _ === "❌");
164
- });
165
- });
137
+ return Object.values(groupedByStackTag).filter((_) => _ === "❌");
166
138
  });
167
139
  if (missingDefinitions.length > 0) {
168
140
  const message = `Unable to produce a working riff-raff.yaml file; missing ${missingDefinitions.length} definitions`;
169
141
  console.log(`${message} (details below)`);
170
- Object.entries(checks).forEach(([className, detail]) => {
171
- console.log(`For the class: ${chalk_1.default.yellow(className)}`);
172
- console.table(detail);
173
- });
142
+ console.table(checks);
174
143
  throw new Error(message);
175
144
  }
176
145
  }
@@ -186,10 +155,6 @@ class RiffRaffYamlFileExperimental {
186
155
  getAutoScalingGroups(cdkStack) {
187
156
  return cdkStack.node.findAll().filter((_) => _ instanceof autoscaling_1.GuAutoScalingGroup);
188
157
  }
189
- getOriginBuckets(cdkStack) {
190
- // `GuS3OriginBucket` implements `IConstruct` to remove a `SuspiciousTypeOfGuard` warning here
191
- return cdkStack.node.findAll().filter((_) => _ instanceof s3_1.GuS3OriginBucket);
192
- }
193
158
  // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree
194
159
  constructor(app) {
195
160
  this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof core_1.GuStack);
@@ -214,7 +179,6 @@ class RiffRaffYamlFileExperimental {
214
179
  const stack = stacks[0];
215
180
  const lambdas = this.getLambdas(stack);
216
181
  const autoscalingGroups = this.getAutoScalingGroups(stack);
217
- const originBuckets = this.getOriginBuckets(stack);
218
182
  const artifactUploads = [
219
183
  lambdas.map(lambda_2.uploadLambdaArtifact),
220
184
  autoscalingGroups.map(autoscaling_2.uploadAutoscalingArtifact),
@@ -229,12 +193,8 @@ class RiffRaffYamlFileExperimental {
229
193
  autoscalingGroups.forEach((asg) => {
230
194
  const asgDeployment = (0, autoscaling_2.autoscalingDeployment)(asg, cfnDeployment);
231
195
  deployments.set(asgDeployment.name, asgDeployment.props);
232
- deployments.set(cfnDeployment.name, (0, cloudformation_1.addAmiParametersToCloudFormationDeployment)(cfnDeployment, asg));
233
- });
234
- originBuckets.forEach((bucket) => {
235
- const staticFilesDeployment = (0, s3_2.uploadStaticFilesDeployment)(this.allStageTags, bucket, cfnDeployment);
236
- deployments.set(staticFilesDeployment.name, staticFilesDeployment.props);
237
196
  });
197
+ deployments.set(cfnDeployment.name, (0, cloudformation_1.addAmiParametersToCloudFormationDeployment)(cfnDeployment, autoscalingGroups));
238
198
  });
239
199
  });
240
200
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport chalk from \"chalk\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../../constructs/autoscaling\";\nimport { GuStack } from \"../../constructs/core\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport { GuS3OriginBucket } from \"../../constructs/s3\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport { addAmiParametersToCloudFormationDeployment, cloudFormationDeployment } from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { uploadStaticFilesDeployment } from \"./deployments/s3\";\nimport { groupByClassNameStackRegionStage } from \"./group-by\";\nimport type {\n ClassName,\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 * - Upload of static files to S3\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 * For S3 uploads, 2 deployments will be defined:\n * 1. Artifact upload (`aws-s3`, `action: [uploadStaticFiles]`)\n * 2. CloudFormation deploy (`cloud-formation`)\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 * └── my-static-site\n * ├── index.html\n * ├── main.js\n * └── index.css\n * ```\n *\n * That is, all CloudFormation templates are in a `cdk.out` directory, and there is a directory per app.\n * Application artifact(s) are in the app directory.\n *\n * NOTE: The file extension is decided by you, the above file tree is used for illustration purposes.\n *\n * NOTE: Resources will be looked up by tags (Stack, Stage, App). Ensure your CFN stack is tagged appropriately!\n *\n * @see https://riffraff.gutools.co.uk/docs/reference/riff-raff.yaml.md\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\nexport class RiffRaffYamlFileExperimental {\n private readonly allCdkStacks: GuStack[];\n private readonly allStackTags: StackTag[];\n private readonly allStageTags: StageTag[];\n private readonly allRegions: Region[];\n\n private readonly riffRaffYaml: RiffRaffYaml;\n private readonly outdir: string;\n\n private isCdkStackPresent(\n expectedClassName: ClassName,\n expectedStack: StackTag,\n expectedRegion: Region,\n expectedStage: StageTag\n ): boolean {\n const matches = this.allCdkStacks.find((cdkStack) => {\n const {\n constructor: { name },\n stack,\n stage,\n region,\n } = cdkStack;\n return (\n name === expectedClassName && stack === expectedStack && stage === expectedStage && region === expectedRegion\n );\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 `GuStack`, `stack`, `region`, 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 * For the class: MyApplicationStack\n *\n * ┌───────────────┬────────────────────────────┐\n * │ (index) │ eu-west-1 │\n * ├───────────────┼────────────────────────────┤\n * │ deploy │ { CODE: '✅', PROD: '✅' } │\n * │ media-service │ { CODE: '❌', PROD: '✅' } │\n * └───────────────┴────────────────────────────┘\n * ```\n *\n * @private\n */\n private validateStacksInApp(): void {\n type Found = \"✅\";\n type NotFound = \"❌\";\n type AppValidation = Record<ClassName, Record<StackTag, Record<Region, Record<StageTag, Found | NotFound>>>>;\n\n const { allCdkStacks, allStackTags, allStageTags, allRegions } = this;\n\n const checks: AppValidation = allCdkStacks.reduce((accClassName, { constructor: { name } }) => {\n return {\n ...accClassName,\n [name]: allStackTags.reduce((accStackTag, stackTag) => {\n return {\n ...accStackTag,\n [stackTag]: allRegions.reduce((accRegion, region) => {\n return {\n ...accRegion,\n [region]: allStageTags.reduce((accStageTag, stageTag) => {\n return {\n ...accStageTag,\n [stageTag]: this.isCdkStackPresent(name, stackTag, region, stageTag) ? \"✅\" : \"❌\",\n };\n }, {}),\n };\n }, {}),\n };\n }, {}),\n };\n }, {});\n\n const missingDefinitions = Object.values(checks).flatMap((groupedByStackTag) => {\n return Object.values(groupedByStackTag).flatMap((groupedByRegion) => {\n return Object.values(groupedByRegion).flatMap((groupedByStage) => {\n return Object.values(groupedByStage).filter((_) => _ === \"❌\");\n });\n });\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 Object.entries(checks).forEach(([className, detail]) => {\n console.log(`For the class: ${chalk.yellow(className)}`);\n console.table(detail);\n });\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 getOriginBuckets(cdkStack: GuStack): GuS3OriginBucket[] {\n // `GuS3OriginBucket` implements `IConstruct` to remove a `SuspiciousTypeOfGuard` warning here\n return cdkStack.node.findAll().filter((_) => _ instanceof GuS3OriginBucket) as GuS3OriginBucket[];\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree\n constructor(app: App) {\n this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));\n this.allStageTags = Array.from(allowedStages);\n this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));\n this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));\n\n this.validateStacksInApp();\n this.validateAllRegionsAreResolved();\n\n this.outdir = app.outdir;\n\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n const groupedStacks: GroupedCdkStacks = groupByClassNameStackRegionStage(this.allCdkStacks);\n\n Object.values(groupedStacks).forEach((stackTagGroup) => {\n Object.values(stackTagGroup).forEach((regionGroup) => {\n Object.values(regionGroup).forEach((stageGroup) => {\n const stacks: GuStack[] = Object.values(stageGroup).flat();\n\n if (stacks.length === 0) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `stacks` is checked above\n const stack = stacks[0]!;\n\n const lambdas = this.getLambdas(stack);\n const autoscalingGroups = this.getAutoScalingGroups(stack);\n const originBuckets = this.getOriginBuckets(stack);\n\n const artifactUploads: RiffRaffDeployment[] = [\n lambdas.map(uploadLambdaArtifact),\n autoscalingGroups.map(uploadAutoscalingArtifact),\n ].flat();\n artifactUploads.forEach(({ name, props }) => deployments.set(name, props));\n\n const cfnDeployment = cloudFormationDeployment(stacks, artifactUploads, this.outdir);\n deployments.set(cfnDeployment.name, cfnDeployment.props);\n\n lambdas.forEach((lambda) => {\n const lambdaDeployment = updateLambdaDeployment(lambda, cfnDeployment);\n deployments.set(lambdaDeployment.name, lambdaDeployment.props);\n });\n\n autoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n\n deployments.set(cfnDeployment.name, addAmiParametersToCloudFormationDeployment(cfnDeployment, asg));\n });\n\n originBuckets.forEach((bucket) => {\n const staticFilesDeployment = uploadStaticFilesDeployment(this.allStageTags, bucket, cfnDeployment);\n deployments.set(staticFilesDeployment.name, staticFilesDeployment.props);\n });\n });\n });\n });\n\n this.riffRaffYaml = {\n allowedStages,\n deployments,\n };\n }\n\n /**\n * The `riff-raff.yaml` file as a string.\n * Useful for testing.\n */\n toYAML(): string {\n // Add support for ES6 Set and Map. See https://github.com/nodeca/js-yaml/issues/436.\n const replacer = (_key: string, value: unknown) => {\n if (value instanceof Set) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Array.from(value);\n }\n if (value instanceof Map) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Object.fromEntries(value);\n }\n return value;\n };\n\n return dump(this.riffRaffYaml, { replacer });\n }\n\n /**\n * Write the `riff-raff.yaml` file to disk.\n * It'll be located with the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n const outPath = path.join(this.outdir, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML());\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../../constructs/autoscaling\";\nimport { GuStack } from \"../../constructs/core\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport { addAmiParametersToCloudFormationDeployment, cloudFormationDeployment } from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { groupByClassNameStackRegionStage } from \"./group-by\";\nimport type {\n GroupedCdkStacks,\n Region,\n RiffRaffDeployment,\n RiffRaffDeploymentName,\n RiffRaffDeploymentProps,\n RiffRaffYaml,\n StackTag,\n StageTag,\n} from \"./types\";\n\n/**\n * A class that creates a `riff-raff.yaml` file.\n *\n * Rather than using this directly, prefer to use [[`GuRoot`]] instead.\n *\n * Supports:\n * - Multiple CloudFormation stacks\n * - Multiple regions\n * - Lambda applications\n * - EC2 (autoscaling) applications\n *\n * For lambda applications, 3 deployments will be defined:\n * 1. Lambda upload (`aws-lambda`, `action: [uploadLambda]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Lambda update (`aws-lambda`, `action: [updateLambda]`)\n *\n * For EC2 applications, 3 deployments will be defined:\n * 1. Artifact upload (`autoscaling`, `action: [uploadArtifacts]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Autoscaling deploy (`autoscaling`, `action: [deploy]`)\n *\n * It assumes a Riff-Raff bundle structure as follows:\n *\n * ```\n * .\n * ├── cdk.out\n * │ └── MyApplication.template.json\n * ├── my-application\n * │ └── my-application.deb\n * └── my-lambda\n * └── my-lambda.zip\n * ```\n *\n * That is, all CloudFormation templates are in a `cdk.out` directory, and there is a directory per app.\n * Application artifact(s) are in the app directory.\n *\n * NOTE: The file extension is decided by you, the above file tree is used for illustration purposes.\n *\n * NOTE: Resources will be looked up by tags (Stack, Stage, App). Ensure your CFN stack is tagged appropriately!\n *\n * @see https://riffraff.gutools.co.uk/docs/reference/riff-raff.yaml.md\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\nexport class RiffRaffYamlFileExperimental {\n private readonly allCdkStacks: GuStack[];\n private readonly allStackTags: StackTag[];\n private readonly allStageTags: StageTag[];\n private readonly allRegions: Region[];\n\n private readonly riffRaffYaml: RiffRaffYaml;\n private readonly outdir: string;\n\n private isCdkStackPresent(expectedStack: StackTag, expectedStage: StageTag): boolean {\n const matches = this.allCdkStacks.find((cdkStack) => {\n const { stack, stage } = cdkStack;\n return stack === expectedStack && stage === expectedStage;\n });\n\n return !!matches;\n }\n\n /**\n * Check there are the appropriate number of `GuStack`s.\n * Expect to find an instance for each combination of `stack`, and `stage`.\n *\n * If not valid, a message is logged describing what is missing to aid debugging.\n *\n * Given the following:\n *\n * ```ts\n * const app = new App();\n *\n * class MyApplicationStack extends GuStack { }\n *\n * new MyApplicationStack(app, \"App-CODE-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"CODE\"\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-media-service\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"media-service\",\n * stage: \"PROD\",\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"PROD\"\n * });\n * ```\n *\n * This will log a message like this, where ❌ denotes something missing,\n * specifically there is no `CODE` template for `media-service`.\n *\n * ```log\n * Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)\n *\n * ┌───────────────┬──────┬──────┐\n * │ (index) │ CODE │ PROD │\n * ├───────────────┼──────┼──────┤\n * │ deploy │ '✅' │ '✅' │\n * │ media-service │ '❌' │ '✅' │\n * └───────────────┴──────┴──────┘\n * ```\n *\n * @private\n */\n private validateStacksInApp(): void {\n type Found = \"✅\";\n type NotFound = \"❌\";\n type AppValidation = Record<StackTag, Record<StageTag, Found | NotFound>>;\n\n const { allStackTags, allStageTags } = this;\n\n const checks: AppValidation = allStackTags.reduce((accStackTag, stackTag) => {\n return {\n ...accStackTag,\n [stackTag]: allStageTags.reduce((accStageTag, stageTag) => {\n return {\n ...accStageTag,\n [stageTag]: this.isCdkStackPresent(stackTag, stageTag) ? \"✅\" : \"❌\",\n };\n }, {}),\n };\n }, {});\n\n const missingDefinitions: Array<Found | NotFound> = Object.values(checks).flatMap((groupedByStackTag) => {\n return Object.values(groupedByStackTag).filter((_) => _ === \"❌\");\n });\n\n if (missingDefinitions.length > 0) {\n const message = `Unable to produce a working riff-raff.yaml file; missing ${missingDefinitions.length} definitions`;\n\n console.log(`${message} (details below)`);\n console.table(checks);\n\n throw new Error(message);\n }\n }\n\n private validateAllRegionsAreResolved(): void {\n const unresolved = this.allRegions.filter((region) => Token.isUnresolved(region));\n\n if (unresolved.length !== 0) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; all stacks must have an explicit region set`);\n }\n }\n\n private getLambdas(cdkStack: GuStack): GuLambdaFunction[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuLambdaFunction) as GuLambdaFunction[];\n }\n\n private getAutoScalingGroups(cdkStack: GuStack): GuAutoScalingGroup[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuAutoScalingGroup) as GuAutoScalingGroup[];\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree\n constructor(app: App) {\n this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));\n this.allStageTags = Array.from(allowedStages);\n this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));\n this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));\n\n this.validateStacksInApp();\n this.validateAllRegionsAreResolved();\n\n this.outdir = app.outdir;\n\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n const groupedStacks: GroupedCdkStacks = groupByClassNameStackRegionStage(this.allCdkStacks);\n\n Object.values(groupedStacks).forEach((stackTagGroup) => {\n Object.values(stackTagGroup).forEach((regionGroup) => {\n Object.values(regionGroup).forEach((stageGroup) => {\n const stacks: GuStack[] = Object.values(stageGroup).flat();\n\n if (stacks.length === 0) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `stacks` is checked above\n const stack = stacks[0]!;\n\n const lambdas = this.getLambdas(stack);\n const autoscalingGroups = this.getAutoScalingGroups(stack);\n\n const artifactUploads: RiffRaffDeployment[] = [\n lambdas.map(uploadLambdaArtifact),\n autoscalingGroups.map(uploadAutoscalingArtifact),\n ].flat();\n artifactUploads.forEach(({ name, props }) => deployments.set(name, props));\n\n const cfnDeployment = cloudFormationDeployment(stacks, artifactUploads, this.outdir);\n deployments.set(cfnDeployment.name, cfnDeployment.props);\n\n lambdas.forEach((lambda) => {\n const lambdaDeployment = updateLambdaDeployment(lambda, cfnDeployment);\n deployments.set(lambdaDeployment.name, lambdaDeployment.props);\n });\n\n autoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n });\n\n deployments.set(\n cfnDeployment.name,\n addAmiParametersToCloudFormationDeployment(cfnDeployment, autoscalingGroups)\n );\n });\n });\n });\n\n this.riffRaffYaml = {\n allowedStages,\n deployments,\n };\n }\n\n /**\n * The `riff-raff.yaml` file as a string.\n * Useful for testing.\n */\n toYAML(): string {\n // Add support for ES6 Set and Map. See https://github.com/nodeca/js-yaml/issues/436.\n const replacer = (_key: string, value: unknown) => {\n if (value instanceof Set) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Array.from(value);\n }\n if (value instanceof Map) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Object.fromEntries(value);\n }\n return value;\n };\n\n return dump(this.riffRaffYaml, { replacer });\n }\n\n /**\n * Write the `riff-raff.yaml` file to disk.\n * It'll be located with the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n const outPath = path.join(this.outdir, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML());\n }\n}\n"]}
@@ -15,7 +15,7 @@ export interface RiffRaffDeploymentProps {
15
15
  stacks: Set<StackTag>;
16
16
  app: string;
17
17
  contentDirectory: string;
18
- parameters: Record<string, string | boolean | Record<string, string> | Array<Record<string, string>>>;
18
+ parameters: Record<string, string | boolean | Record<string, string>>;
19
19
  dependencies?: RiffRaffDeploymentName[];
20
20
  actions?: string[];
21
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,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,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,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACtG,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;AASD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CACnC,SAAS,EACT,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAC,CAAC,CAClF,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,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,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,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtE,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;AASD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CACnC,SAAS,EACT,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAC,CAAC,CAClF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/experimental/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 interface RiffRaffDeploymentProps {\n type: string;\n regions: Set<Region>;\n stacks: Set<StackTag>;\n app: string;\n contentDirectory: string;\n parameters: Record<string, string | boolean | Record<string, string> | Array<Record<string, string>>>;\n dependencies?: RiffRaffDeploymentName[];\n actions?: string[];\n}\n\nexport interface RiffRaffDeployment {\n name: RiffRaffDeploymentName;\n props: RiffRaffDeploymentProps;\n}\n\n/*\n The aim here is to produce an identity of a `GuStack` as a composite of:\n - Class name\n - Stack tag\n - Region\n Finally, group by stage to help form the `templateStagePaths` property for the `cloud-formation` deployment type in `riff-raff.yaml`.\n */\nexport type GroupedCdkStacks = Record<\n ClassName,\n Record<StackTag, Record<Region, Record<StageTag, CdkStacksDifferingOnlyByStage>>>\n>;\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/experimental/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 interface RiffRaffDeploymentProps {\n type: string;\n regions: Set<Region>;\n stacks: Set<StackTag>;\n app: string;\n contentDirectory: string;\n parameters: Record<string, string | boolean | Record<string, string>>;\n dependencies?: RiffRaffDeploymentName[];\n actions?: string[];\n}\n\nexport interface RiffRaffDeployment {\n name: RiffRaffDeploymentName;\n props: RiffRaffDeploymentProps;\n}\n\n/*\n The aim here is to produce an identity of a `GuStack` as a composite of:\n - Class name\n - Stack tag\n - Region\n Finally, group by stage to help form the `templateStagePaths` property for the `cloud-formation` deployment type in `riff-raff.yaml`.\n */\nexport type GroupedCdkStacks = Record<\n ClassName,\n Record<StackTag, Record<Region, Record<StageTag, CdkStacksDifferingOnlyByStage>>>\n>;\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@guardian/cdk",
3
3
  "description": "Generic Guardian flavoured AWS CDK components",
4
- "version": "49.1.0-beta.1",
4
+ "version": "49.1.0",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
7
7
  "files": [
@@ -28,36 +28,36 @@
28
28
  "cli:dev": "ts-node src/bin/index.ts"
29
29
  },
30
30
  "devDependencies": {
31
- "@guardian/eslint-config-typescript": "2.0.0",
31
+ "@guardian/eslint-config-typescript": "3.0.0",
32
32
  "@types/git-url-parse": "^9.0.1",
33
- "@types/jest": "^29.2.4",
33
+ "@types/jest": "^29.2.5",
34
34
  "@types/js-yaml": "^4.0.5",
35
35
  "@types/lodash.camelcase": "^4.3.7",
36
36
  "@types/lodash.kebabcase": "^4.1.7",
37
37
  "@types/lodash.upperfirst": "^4.3.7",
38
- "@types/node": "18.11.9",
39
- "@types/yargs": "^17.0.17",
40
- "aws-cdk": "2.54.0",
38
+ "@types/node": "18.11.18",
39
+ "@types/yargs": "^17.0.19",
40
+ "aws-cdk": "2.59.0",
41
41
  "cz-conventional-changelog": "^3.3.0",
42
- "eslint": "^8.29.0",
42
+ "eslint": "^8.32.0",
43
43
  "eslint-plugin-custom-rules": "file:tools/eslint",
44
- "gh-pages": "^4.0.0",
44
+ "gh-pages": "^5.0.0",
45
45
  "jest": "^29.3.1",
46
- "prettier": "^2.8.0",
46
+ "prettier": "^2.8.3",
47
47
  "semantic-release": "^19.0.5",
48
- "serve": "^14.1.2",
49
- "ts-jest": "^29.0.3",
48
+ "serve": "^14.2.0",
49
+ "ts-jest": "^29.0.5",
50
50
  "ts-node": "^10.9.1",
51
- "typedoc": "^0.23.22",
52
- "typescript": "~4.9.3"
51
+ "typedoc": "^0.23.24",
52
+ "typescript": "~4.9.4"
53
53
  },
54
54
  "dependencies": {
55
- "@oclif/core": "1.21.0",
56
- "aws-cdk-lib": "2.54.0",
57
- "aws-sdk": "^2.1272.0",
55
+ "@oclif/core": "1.24.2",
56
+ "aws-cdk-lib": "2.59.0",
57
+ "aws-sdk": "^2.1296.0",
58
58
  "chalk": "^4.1.2",
59
- "codemaker": "^1.72.0",
60
- "constructs": "10.1.187",
59
+ "codemaker": "^1.73.0",
60
+ "constructs": "10.1.215",
61
61
  "git-url-parse": "^13.1.0",
62
62
  "js-yaml": "^4.1.0",
63
63
  "lodash.camelcase": "^4.3.0",
@@ -67,9 +67,9 @@
67
67
  "yargs": "^17.6.2"
68
68
  },
69
69
  "peerDependencies": {
70
- "aws-cdk": "2.54.0",
71
- "aws-cdk-lib": "2.54.0",
72
- "constructs": "10.1.187"
70
+ "aws-cdk": "2.59.0",
71
+ "aws-cdk-lib": "2.59.0",
72
+ "constructs": "10.1.215"
73
73
  },
74
74
  "config": {
75
75
  "commitizen": {
@@ -1,8 +0,0 @@
1
- import type { GuStack } from "../../core";
2
- import { GuAllowPolicy } from "./base-policy";
3
- export declare class GuSSMRunCommandPolicy extends GuAllowPolicy {
4
- private static instance;
5
- private constructor();
6
- static getInstance(stack: GuStack): GuSSMRunCommandPolicy;
7
- }
8
- //# sourceMappingURL=ssm.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ssm.d.ts","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/ssm.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,qBAAa,qBAAsB,SAAQ,aAAa;IACtD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAoC;IAE3D,OAAO;WAuBO,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,qBAAqB;CAOjE"}
@@ -1,37 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GuSSMRunCommandPolicy = void 0;
4
- const singleton_1 = require("../../../utils/singleton");
5
- const base_policy_1 = require("./base-policy");
6
- class GuSSMRunCommandPolicy extends base_policy_1.GuAllowPolicy {
7
- constructor(scope) {
8
- super(scope, "SSMRunCommandPolicy", {
9
- policyName: "ssm-run-command-policy",
10
- resources: ["*"],
11
- actions: [
12
- "ec2messages:AcknowledgeMessage",
13
- "ec2messages:DeleteMessage",
14
- "ec2messages:FailMessage",
15
- "ec2messages:GetEndpoint",
16
- "ec2messages:GetMessages",
17
- "ec2messages:SendReply",
18
- "ssm:UpdateInstanceInformation",
19
- "ssm:ListInstanceAssociations",
20
- "ssm:DescribeInstanceProperties",
21
- "ssm:DescribeDocumentParameters",
22
- "ssmmessages:CreateControlChannel",
23
- "ssmmessages:CreateDataChannel",
24
- "ssmmessages:OpenControlChannel",
25
- "ssmmessages:OpenDataChannel",
26
- ],
27
- });
28
- }
29
- static getInstance(stack) {
30
- if (!this.instance || !(0, singleton_1.isSingletonPresentInStack)(stack, this.instance)) {
31
- this.instance = new GuSSMRunCommandPolicy(stack);
32
- }
33
- return this.instance;
34
- }
35
- }
36
- exports.GuSSMRunCommandPolicy = GuSSMRunCommandPolicy;
37
- //# sourceMappingURL=ssm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ssm.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/ssm.ts"],"names":[],"mappings":";;;AAAA,wDAAqE;AAErE,+CAA8C;AAE9C,MAAa,qBAAsB,SAAQ,2BAAa;IAGtD,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,qBAAqB,EAAE;YAClC,UAAU,EAAE,wBAAwB;YACpC,SAAS,EAAE,CAAC,GAAG,CAAC;YAChB,OAAO,EAAE;gBACP,gCAAgC;gBAChC,2BAA2B;gBAC3B,yBAAyB;gBACzB,yBAAyB;gBACzB,yBAAyB;gBACzB,uBAAuB;gBACvB,+BAA+B;gBAC/B,8BAA8B;gBAC9B,gCAAgC;gBAChC,gCAAgC;gBAChC,kCAAkC;gBAClC,+BAA+B;gBAC/B,gCAAgC;gBAChC,6BAA6B;aAC9B;SACF,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YACtE,IAAI,CAAC,QAAQ,GAAG,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAC;SAClD;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAjCD,sDAiCC","sourcesContent":["import { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../../core\";\nimport { GuAllowPolicy } from \"./base-policy\";\n\nexport class GuSSMRunCommandPolicy extends GuAllowPolicy {\n private static instance: GuSSMRunCommandPolicy | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"SSMRunCommandPolicy\", {\n policyName: \"ssm-run-command-policy\",\n resources: [\"*\"],\n actions: [\n \"ec2messages:AcknowledgeMessage\",\n \"ec2messages:DeleteMessage\",\n \"ec2messages:FailMessage\",\n \"ec2messages:GetEndpoint\",\n \"ec2messages:GetMessages\",\n \"ec2messages:SendReply\",\n \"ssm:UpdateInstanceInformation\",\n \"ssm:ListInstanceAssociations\",\n \"ssm:DescribeInstanceProperties\",\n \"ssm:DescribeDocumentParameters\",\n \"ssmmessages:CreateControlChannel\",\n \"ssmmessages:CreateDataChannel\",\n \"ssmmessages:OpenControlChannel\",\n \"ssmmessages:OpenDataChannel\",\n ],\n });\n }\n\n public static getInstance(stack: GuStack): GuSSMRunCommandPolicy {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuSSMRunCommandPolicy(stack);\n }\n\n return this.instance;\n }\n}\n"]}
@@ -1,4 +0,0 @@
1
- import type { GuS3OriginBucket } from "../../../constructs/s3";
2
- import type { RiffRaffDeployment } from "../types";
3
- export declare function uploadStaticFilesDeployment(stages: string[], originBucket: GuS3OriginBucket, { name: cfnDeployName }: RiffRaffDeployment): RiffRaffDeployment;
4
- //# sourceMappingURL=s3.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../../../../src/experimental/riff-raff-yaml-file/deployments/s3.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,EAAE,EAChB,YAAY,EAAE,gBAAgB,EAC9B,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,kBAAkB,GAC1C,kBAAkB,CAoDpB"}
@@ -1,48 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.uploadStaticFilesDeployment = void 0;
4
- function uploadStaticFilesDeployment(stages, originBucket, { name: cfnDeployName }) {
5
- const { app, _deploymentProps } = originBucket;
6
- const { withoutStageAwareness, baseParameterName, cacheControl, surrogateControl, mimeTypes } = _deploymentProps;
7
- const { stack, region } = originBucket.stack;
8
- const cacheControlValue = Object.entries(cacheControl).map(([pattern, duration]) => {
9
- return {
10
- pattern,
11
- value: `public, max-age=${duration.toSeconds()}`,
12
- };
13
- });
14
- const surrogateControlValue = Object.entries(surrogateControl).map(([pattern, duration]) => {
15
- return {
16
- pattern,
17
- value: `public, max-age=${duration.toSeconds()}`,
18
- };
19
- });
20
- return {
21
- name: ["upload-static-files", region, stack, app].join("-"),
22
- props: {
23
- type: "aws-s3",
24
- actions: ["uploadStaticFiles"],
25
- dependencies: [cfnDeployName],
26
- stacks: new Set([stack]),
27
- regions: new Set([region]),
28
- app,
29
- contentDirectory: app,
30
- parameters: {
31
- bucketSsmKeyStageParam: stages.reduce((acc, stage) => ({
32
- ...acc,
33
- [stage]: withoutStageAwareness ? baseParameterName : `/${stage}${baseParameterName}`,
34
- }), {}),
35
- // Never create per object ACLs.
36
- // If the bucket content needs to be public, it’s better to control this via the bucket policy.
37
- publicReadAcl: false,
38
- cacheControl: cacheControlValue.length > 0 ? cacheControlValue : "private",
39
- // only add the `surrogateControl` property if there are some
40
- ...(surrogateControlValue.length > 0 && { surrogateControl: surrogateControlValue }),
41
- // only add the `mimeTypes` property if there are some
42
- ...(Object.keys(mimeTypes).length > 0 && { mimeTypes }),
43
- },
44
- },
45
- };
46
- }
47
- exports.uploadStaticFilesDeployment = uploadStaticFilesDeployment;
48
- //# sourceMappingURL=s3.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"s3.js","sourceRoot":"","sources":["../../../../src/experimental/riff-raff-yaml-file/deployments/s3.ts"],"names":[],"mappings":";;;AAIA,SAAgB,2BAA2B,CACzC,MAAgB,EAChB,YAA8B,EAC9B,EAAE,IAAI,EAAE,aAAa,EAAsB;IAE3C,MAAM,EAAE,GAAG,EAAE,gBAAgB,EAAE,GAAG,YAAY,CAAC;IAC/C,MAAM,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,YAAY,EAAE,gBAAgB,EAAE,SAAS,EAAE,GAAG,gBAAgB,CAAC;IACjH,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,KAAgB,CAAC;IAExD,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE;QACjF,OAAO;YACL,OAAO;YACP,KAAK,EAAE,mBAAmB,QAAQ,CAAC,SAAS,EAAE,EAAE;SACjD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,qBAAqB,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE;QACzF,OAAO;YACL,OAAO;YACP,KAAK,EAAE,mBAAmB,QAAQ,CAAC,SAAS,EAAE,EAAE;SACjD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,CAAC,qBAAqB,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAC3D,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,CAAC,mBAAmB,CAAC;YAC9B,YAAY,EAAE,CAAC,aAAa,CAAC;YAC7B,MAAM,EAAE,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;YACxB,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;YAC1B,GAAG;YACH,gBAAgB,EAAE,GAAG;YACrB,UAAU,EAAE;gBACV,sBAAsB,EAAE,MAAM,CAAC,MAAM,CACnC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;oBACf,GAAG,GAAG;oBACN,CAAC,KAAK,CAAC,EAAE,qBAAqB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,iBAAiB,EAAE;iBACrF,CAAC,EACF,EAAE,CACH;gBAED,gCAAgC;gBAChC,+FAA+F;gBAC/F,aAAa,EAAE,KAAK;gBAEpB,YAAY,EAAE,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS;gBAE1E,6DAA6D;gBAC7D,GAAG,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,CAAC;gBAEpF,sDAAsD;gBACtD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;aACxD;SACF;KACF,CAAC;AACJ,CAAC;AAxDD,kEAwDC","sourcesContent":["import type { GuStack } from \"../../../constructs/core\";\nimport type { GuS3OriginBucket } from \"../../../constructs/s3\";\nimport type { RiffRaffDeployment } from \"../types\";\n\nexport function uploadStaticFilesDeployment(\n stages: string[],\n originBucket: GuS3OriginBucket,\n { name: cfnDeployName }: RiffRaffDeployment\n): RiffRaffDeployment {\n const { app, _deploymentProps } = originBucket;\n const { withoutStageAwareness, baseParameterName, cacheControl, surrogateControl, mimeTypes } = _deploymentProps;\n const { stack, region } = originBucket.stack as GuStack;\n\n const cacheControlValue = Object.entries(cacheControl).map(([pattern, duration]) => {\n return {\n pattern,\n value: `public, max-age=${duration.toSeconds()}`,\n };\n });\n\n const surrogateControlValue = Object.entries(surrogateControl).map(([pattern, duration]) => {\n return {\n pattern,\n value: `public, max-age=${duration.toSeconds()}`,\n };\n });\n\n return {\n name: [\"upload-static-files\", region, stack, app].join(\"-\"),\n props: {\n type: \"aws-s3\",\n actions: [\"uploadStaticFiles\"],\n dependencies: [cfnDeployName],\n stacks: new Set([stack]),\n regions: new Set([region]),\n app,\n contentDirectory: app,\n parameters: {\n bucketSsmKeyStageParam: stages.reduce(\n (acc, stage) => ({\n ...acc,\n [stage]: withoutStageAwareness ? baseParameterName : `/${stage}${baseParameterName}`,\n }),\n {}\n ),\n\n // Never create per object ACLs.\n // If the bucket content needs to be public, it’s better to control this via the bucket policy.\n publicReadAcl: false,\n\n cacheControl: cacheControlValue.length > 0 ? cacheControlValue : \"private\",\n\n // only add the `surrogateControl` property if there are some\n ...(surrogateControlValue.length > 0 && { surrogateControl: surrogateControlValue }),\n\n // only add the `mimeTypes` property if there are some\n ...(Object.keys(mimeTypes).length > 0 && { mimeTypes }),\n },\n },\n };\n}\n"]}