@fjall/components-infrastructure 0.96.0 → 0.99.3

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 (209) hide show
  1. package/dist/lib/app.d.ts +68 -1
  2. package/dist/lib/app.js +113 -4
  3. package/dist/lib/config/aws/__t17fixture.d.ts +1 -0
  4. package/dist/lib/config/aws/__t17fixture.js +3 -0
  5. package/dist/lib/config/aws/__t17fixtureType.d.ts +2 -0
  6. package/dist/lib/config/aws/__t17fixtureType.js +1 -0
  7. package/dist/lib/config/aws/alarmTopic.js +8 -4
  8. package/dist/lib/config/aws/cloudTrail.js +1 -1
  9. package/dist/lib/config/aws/disasterRecovery.js +11 -16
  10. package/dist/lib/config/aws/ecrDefaultImage.d.ts +0 -1
  11. package/dist/lib/config/aws/ecrDefaultImage.js +13 -23
  12. package/dist/lib/config/aws/identityCenter.d.ts +10 -3
  13. package/dist/lib/config/aws/identityCenter.js +101 -37
  14. package/dist/lib/config/aws/identityCenterGroupMembership.js +8 -2
  15. package/dist/lib/config/aws/identityCenterMembership.d.ts +11 -0
  16. package/dist/lib/config/aws/identityCenterMembership.js +61 -0
  17. package/dist/lib/config/aws/index.d.ts +1 -1
  18. package/dist/lib/config/aws/index.js +1 -1
  19. package/dist/lib/config/aws/ipam.js +6 -11
  20. package/dist/lib/config/aws/oidcConnector.js +5 -1
  21. package/dist/lib/config/aws/scpPreset.js +4 -1
  22. package/dist/lib/patterns/aws/_eslint_test_tmp/leak.d.ts +1 -0
  23. package/dist/lib/patterns/aws/_eslint_test_tmp/leak.js +4 -0
  24. package/dist/lib/patterns/aws/account.js +2 -4
  25. package/dist/lib/patterns/aws/apexDomainPattern.js +10 -10
  26. package/dist/lib/patterns/aws/bastionFactory.d.ts +10 -0
  27. package/dist/lib/patterns/aws/bastionFactory.js +29 -0
  28. package/dist/lib/patterns/aws/buildkite.d.ts +2 -2
  29. package/dist/lib/patterns/aws/buildkite.js +51 -97
  30. package/dist/lib/patterns/aws/cdn.js +1 -1
  31. package/dist/lib/patterns/aws/clickhouseDatabase.d.ts +173 -0
  32. package/dist/lib/patterns/aws/clickhouseDatabase.js +601 -0
  33. package/dist/lib/patterns/aws/compute.d.ts +4 -6
  34. package/dist/lib/patterns/aws/compute.js +7 -13
  35. package/dist/lib/patterns/aws/computeEcs.d.ts +93 -5
  36. package/dist/lib/patterns/aws/computeEcs.js +867 -37
  37. package/dist/lib/patterns/aws/computeEcsTypes.d.ts +528 -25
  38. package/dist/lib/patterns/aws/computeEcsTypes.js +10 -0
  39. package/dist/lib/patterns/aws/computeLambda.d.ts +0 -5
  40. package/dist/lib/patterns/aws/computeLambda.js +1 -2
  41. package/dist/lib/patterns/aws/database.d.ts +50 -8
  42. package/dist/lib/patterns/aws/database.js +183 -27
  43. package/dist/lib/patterns/aws/domain.js +6 -4
  44. package/dist/lib/patterns/aws/index.d.ts +1 -0
  45. package/dist/lib/patterns/aws/index.js +1 -0
  46. package/dist/lib/patterns/aws/interfaces/compute.d.ts +7 -1
  47. package/dist/lib/patterns/aws/interfaces/database.d.ts +187 -8
  48. package/dist/lib/patterns/aws/interfaces/database.js +17 -3
  49. package/dist/lib/patterns/aws/interfaces/index.d.ts +2 -1
  50. package/dist/lib/patterns/aws/interfaces/index.js +3 -1
  51. package/dist/lib/patterns/aws/interfaces/messaging.d.ts +7 -0
  52. package/dist/lib/patterns/aws/interfaces/migrationContributor.d.ts +47 -0
  53. package/dist/lib/patterns/aws/interfaces/migrationContributor.js +9 -0
  54. package/dist/lib/patterns/aws/messaging.d.ts +66 -10
  55. package/dist/lib/patterns/aws/messaging.js +115 -20
  56. package/dist/lib/patterns/aws/network.js +16 -7
  57. package/dist/lib/patterns/aws/organisation.d.ts +4 -0
  58. package/dist/lib/patterns/aws/organisation.js +22 -4
  59. package/dist/lib/patterns/aws/storage.d.ts +1 -2
  60. package/dist/lib/patterns/aws/storage.js +3 -2
  61. package/dist/lib/patterns/aws/vpcPeer.js +3 -1
  62. package/dist/lib/resources/aws/analytics/clickhouse.js +18 -9
  63. package/dist/lib/resources/aws/analytics/clickhouseAlarms.d.ts +24 -9
  64. package/dist/lib/resources/aws/analytics/clickhouseAlarms.js +61 -10
  65. package/dist/lib/resources/aws/analytics/clickhouseConstants.d.ts +3 -3
  66. package/dist/lib/resources/aws/analytics/clickhouseConstants.js +3 -3
  67. package/dist/lib/resources/aws/analytics/clickhouseTypes.d.ts +7 -1
  68. package/dist/lib/resources/aws/analytics/clickhouseUserData.d.ts +1 -1
  69. package/dist/lib/resources/aws/analytics/clickhouseUserData.js +53 -3
  70. package/dist/lib/resources/aws/base/awsStack.js +4 -2
  71. package/dist/lib/resources/aws/compute/__tmp__/regression-shape.d.ts +2 -0
  72. package/dist/lib/resources/aws/compute/__tmp__/regression-shape.js +11 -0
  73. package/dist/lib/resources/aws/compute/asgInlineLifecycleHook.d.ts +52 -0
  74. package/dist/lib/resources/aws/compute/asgInlineLifecycleHook.js +60 -0
  75. package/dist/lib/resources/aws/compute/blockDeviceVolume.d.ts +8 -0
  76. package/dist/lib/resources/aws/compute/blockDeviceVolume.js +10 -0
  77. package/dist/lib/resources/aws/compute/ec2.d.ts +132 -12
  78. package/dist/lib/resources/aws/compute/ec2.js +163 -23
  79. package/dist/lib/resources/aws/compute/ec2GracefulTerminationHandler.d.ts +41 -0
  80. package/dist/lib/resources/aws/compute/ec2GracefulTerminationHandler.js +194 -0
  81. package/dist/lib/resources/aws/compute/ec2GracefulTerminationLambda.source.cjs +458 -0
  82. package/dist/lib/resources/aws/compute/ecs.d.ts +27 -1
  83. package/dist/lib/resources/aws/compute/ecs.js +42 -2
  84. package/dist/lib/resources/aws/compute/ecsConstants.d.ts +9 -0
  85. package/dist/lib/resources/aws/compute/ecsConstants.js +16 -0
  86. package/dist/lib/resources/aws/compute/ecsImages.js +32 -20
  87. package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.d.ts +96 -0
  88. package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.js +113 -0
  89. package/dist/lib/resources/aws/compute/ecsNetworking.d.ts +2 -1
  90. package/dist/lib/resources/aws/compute/ecsNetworking.js +18 -6
  91. package/dist/lib/resources/aws/compute/ecsServiceFactory.d.ts +13 -4
  92. package/dist/lib/resources/aws/compute/ecsServiceFactory.js +155 -33
  93. package/dist/lib/resources/aws/compute/ecsTaskDefinition.d.ts +31 -1
  94. package/dist/lib/resources/aws/compute/ecsTaskDefinition.js +102 -6
  95. package/dist/lib/resources/aws/compute/ecsTypes.d.ts +173 -13
  96. package/dist/lib/resources/aws/compute/ecsValidation.d.ts +9 -0
  97. package/dist/lib/resources/aws/compute/ecsValidation.js +63 -0
  98. package/dist/lib/resources/aws/compute/index.d.ts +2 -0
  99. package/dist/lib/resources/aws/compute/index.js +2 -0
  100. package/dist/lib/resources/aws/compute/lambda.d.ts +7 -13
  101. package/dist/lib/resources/aws/compute/lambda.js +30 -38
  102. package/dist/lib/resources/aws/compute/lifecycleHookLambda.source.cjs +192 -0
  103. package/dist/lib/resources/aws/compute/persistentDataVolume.d.ts +104 -0
  104. package/dist/lib/resources/aws/compute/persistentDataVolume.js +245 -0
  105. package/dist/lib/resources/aws/compute/persistentDataVolumeLambda.source.cjs +398 -0
  106. package/dist/lib/resources/aws/compute/samApplication.d.ts +15 -0
  107. package/dist/lib/resources/aws/compute/samApplication.js +27 -0
  108. package/dist/lib/resources/aws/database/clickhouseConstants.d.ts +159 -0
  109. package/dist/lib/resources/aws/database/clickhouseConstants.js +181 -0
  110. package/dist/lib/resources/aws/database/clickhouseSchemas.d.ts +71 -0
  111. package/dist/lib/resources/aws/database/clickhouseSchemas.js +160 -0
  112. package/dist/lib/resources/aws/database/clickhouseSecurityGroup.d.ts +14 -0
  113. package/dist/lib/resources/aws/database/clickhouseSecurityGroup.js +23 -0
  114. package/dist/lib/resources/aws/database/clickhouseUserData.d.ts +69 -0
  115. package/dist/lib/resources/aws/database/clickhouseUserData.js +371 -0
  116. package/dist/lib/resources/aws/database/clickhouseXmlRenderer.d.ts +56 -0
  117. package/dist/lib/resources/aws/database/clickhouseXmlRenderer.js +112 -0
  118. package/dist/lib/resources/aws/database/rdsAurora.d.ts +8 -1
  119. package/dist/lib/resources/aws/database/rdsAurora.js +42 -32
  120. package/dist/lib/resources/aws/database/rdsAuroraGlobal.d.ts +15 -2
  121. package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +39 -43
  122. package/dist/lib/resources/aws/database/rdsDefaults.d.ts +6 -0
  123. package/dist/lib/resources/aws/database/rdsDefaults.js +7 -1
  124. package/dist/lib/resources/aws/database/rdsHelpers.d.ts +3 -3
  125. package/dist/lib/resources/aws/database/rdsHelpers.js +1 -0
  126. package/dist/lib/resources/aws/database/rdsInstance.d.ts +8 -1
  127. package/dist/lib/resources/aws/database/rdsInstance.js +51 -34
  128. package/dist/lib/resources/aws/database/rdsProxyOutput.d.ts +1 -1
  129. package/dist/lib/resources/aws/database/rdsProxyOutput.js +1 -1
  130. package/dist/lib/resources/aws/iam/delegationRole.js +1 -1
  131. package/dist/lib/resources/aws/iam/identityCenter/groupMembership.d.ts +9 -0
  132. package/dist/lib/resources/aws/iam/identityCenter/groupMembership.js +12 -0
  133. package/dist/lib/resources/aws/iam/identityCenter/index.d.ts +1 -0
  134. package/dist/lib/resources/aws/iam/identityCenter/index.js +1 -0
  135. package/dist/lib/resources/aws/iam/identityCenter/permissionSet.d.ts +1 -0
  136. package/dist/lib/resources/aws/iam/identityCenter/permissionSet.js +1 -0
  137. package/dist/lib/resources/aws/logging/logGroup.d.ts +0 -8
  138. package/dist/lib/resources/aws/logging/logGroup.js +0 -11
  139. package/dist/lib/resources/aws/messaging/defaultEventBus.d.ts +7 -0
  140. package/dist/lib/resources/aws/messaging/defaultEventBus.js +21 -0
  141. package/dist/lib/resources/aws/messaging/eventBridgeRule.d.ts +96 -0
  142. package/dist/lib/resources/aws/messaging/eventBridgeRule.js +110 -0
  143. package/dist/lib/resources/aws/messaging/eventTargets.d.ts +84 -0
  144. package/dist/lib/resources/aws/messaging/eventTargets.js +152 -0
  145. package/dist/lib/resources/aws/messaging/eventbridge.d.ts +25 -2
  146. package/dist/lib/resources/aws/messaging/eventbridge.js +22 -10
  147. package/dist/lib/resources/aws/messaging/index.d.ts +5 -0
  148. package/dist/lib/resources/aws/messaging/index.js +2 -0
  149. package/dist/lib/resources/aws/messaging/schedule.d.ts +118 -0
  150. package/dist/lib/resources/aws/messaging/schedule.js +64 -0
  151. package/dist/lib/resources/aws/messaging/sns.d.ts +2 -1
  152. package/dist/lib/resources/aws/messaging/sqs.d.ts +2 -1
  153. package/dist/lib/resources/aws/messaging/subscription.d.ts +112 -0
  154. package/dist/lib/resources/aws/messaging/subscription.js +67 -0
  155. package/dist/lib/resources/aws/messaging/utils.d.ts +6 -0
  156. package/dist/lib/resources/aws/messaging/utils.js +10 -0
  157. package/dist/lib/resources/aws/monitoring/clickhouseAlarms.d.ts +60 -0
  158. package/dist/lib/resources/aws/monitoring/clickhouseAlarms.js +139 -0
  159. package/dist/lib/resources/aws/monitoring/index.d.ts +2 -0
  160. package/dist/lib/resources/aws/monitoring/index.js +2 -0
  161. package/dist/lib/resources/aws/monitoring/scheduleAlarms.d.ts +47 -0
  162. package/dist/lib/resources/aws/monitoring/scheduleAlarms.js +106 -0
  163. package/dist/lib/resources/aws/networking/crossAccountDelegationRecord.js +6 -4
  164. package/dist/lib/resources/aws/networking/crossAccountReturnRoutes.js +17 -13
  165. package/dist/lib/resources/aws/networking/dnsRecord/dnsRecordBase.js +7 -5
  166. package/dist/lib/resources/aws/networking/domainCertificate.d.ts +2 -2
  167. package/dist/lib/resources/aws/networking/domainCertificate.js +6 -4
  168. package/dist/lib/resources/aws/networking/hostedZone.js +6 -5
  169. package/dist/lib/resources/aws/networking/serviceDiscovery.d.ts +96 -0
  170. package/dist/lib/resources/aws/networking/serviceDiscovery.js +96 -0
  171. package/dist/lib/resources/aws/networking/vpc.d.ts +4 -1
  172. package/dist/lib/resources/aws/networking/vpc.js +4 -1
  173. package/dist/lib/resources/aws/networking/vpcPeeringConnection.js +21 -3
  174. package/dist/lib/resources/aws/organisation/costAllocationTagActivator.d.ts +16 -5
  175. package/dist/lib/resources/aws/organisation/costAllocationTagActivator.js +17 -3
  176. package/dist/lib/resources/aws/organisation/index.d.ts +1 -1
  177. package/dist/lib/resources/aws/organisation/organisationPolicy.d.ts +2 -0
  178. package/dist/lib/resources/aws/organisation/organisationPolicy.js +3 -2
  179. package/dist/lib/resources/aws/secrets/secret.d.ts +7 -0
  180. package/dist/lib/resources/aws/secrets/secret.js +4 -3
  181. package/dist/lib/resources/aws/storage/bucketDeployment.d.ts +16 -0
  182. package/dist/lib/resources/aws/storage/bucketDeployment.js +17 -0
  183. package/dist/lib/resources/aws/storage/ecr.js +5 -5
  184. package/dist/lib/resources/aws/storage/index.d.ts +1 -0
  185. package/dist/lib/resources/aws/storage/index.js +1 -0
  186. package/dist/lib/resources/aws/storage/s3.js +10 -3
  187. package/dist/lib/resources/aws/utilities/customResource.js +18 -9
  188. package/dist/lib/synth_dump.d.ts +1 -0
  189. package/dist/lib/synth_dump.js +42 -0
  190. package/dist/lib/utils/cdkContext.d.ts +2 -0
  191. package/dist/lib/utils/cdkContext.js +4 -2
  192. package/dist/lib/utils/connections.js +6 -0
  193. package/dist/lib/utils/connector.d.ts +12 -0
  194. package/dist/lib/utils/costAllocationTags.d.ts +9 -0
  195. package/dist/lib/utils/costAllocationTags.js +11 -1
  196. package/dist/lib/utils/databaseTypes.d.ts +14 -0
  197. package/dist/lib/utils/getConfig.d.ts +2 -0
  198. package/dist/lib/utils/getConfig.js +2 -0
  199. package/dist/lib/utils/index.d.ts +1 -0
  200. package/dist/lib/utils/index.js +1 -0
  201. package/dist/lib/utils/manifestWriter.d.ts +6 -89
  202. package/dist/lib/utils/manifestWriter.js +36 -23
  203. package/dist/lib/utils/migrationVersionResolvers.d.ts +2 -0
  204. package/dist/lib/utils/migrationVersionResolvers.js +2 -0
  205. package/dist/lib/utils/orgConfigParser.js +2 -1
  206. package/dist/lib/utils/resolveAlertsTopic.d.ts +14 -0
  207. package/dist/lib/utils/resolveAlertsTopic.js +30 -0
  208. package/dist/lib/utils/validationLogger.js +6 -3
  209. package/package.json +22 -19
@@ -1,27 +1,27 @@
1
- import { Duration, Stack, Tags } from "aws-cdk-lib";
1
+ import { Stack, Tags } from "aws-cdk-lib";
2
2
  import { CompositePrincipal, ServicePrincipal, PolicyDocument, PolicyStatement } from "aws-cdk-lib/aws-iam";
3
3
  import { FjallLogger } from "../../utils/validationLogger.js";
4
- import { BlockDeviceVolume, InstanceClass, InstanceSize, InstanceType, LaunchTemplate, LaunchTemplateHttpTokens, MachineImage, MultipartBody, MultipartUserData, SubnetType, UserData } from "aws-cdk-lib/aws-ec2";
5
- import { AutoScalingGroup, GroupMetrics, SpotAllocationStrategy, TerminationPolicy, UpdatePolicy } from "aws-cdk-lib/aws-autoscaling";
6
- import { CfnApplication } from "aws-cdk-lib/aws-sam";
7
- import { PhysicalResourceId } from "aws-cdk-lib/custom-resources";
8
- import { BucketDeployment, Source } from "aws-cdk-lib/aws-s3-deployment";
4
+ import { InstanceClass, InstanceSize, InstanceType, MachineImage, MultipartBody, MultipartUserData, SubnetType, UserData } from "aws-cdk-lib/aws-ec2";
5
+ import { safeEbs } from "../../resources/aws/compute/blockDeviceVolume.js";
6
+ import { Source } from "aws-cdk-lib/aws-s3-deployment";
9
7
  import { Vpc } from "../../resources/aws/networking/vpc.js";
10
8
  import { Policy, Role } from "../../resources/aws/iam/index.js";
11
- import { S3Bucket } from "../../resources/aws/storage/index.js";
9
+ import { BucketDeployment, S3Bucket } from "../../resources/aws/storage/index.js";
12
10
  import { SecureStringParameter } from "../../resources/aws/secrets/index.js";
13
- import { AwsCustomResource } from "../../resources/aws/utilities/awsCustomResource.js";
14
- var agentRelease;
15
- (function (agentRelease) {
16
- agentRelease["STABLE"] = "stable";
17
- agentRelease["BETA"] = "beta";
18
- agentRelease["EDGE"] = "edge";
19
- })(agentRelease || (agentRelease = {}));
11
+ import { Ec2Instance } from "../../resources/aws/compute/ec2.js";
12
+ import { SamApplication } from "../../resources/aws/compute/samApplication.js";
13
+ import { applyCostAllocationTags } from "../../utils/costAllocationTags.js";
14
+ export var AgentRelease;
15
+ (function (AgentRelease) {
16
+ AgentRelease["STABLE"] = "stable";
17
+ AgentRelease["BETA"] = "beta";
18
+ AgentRelease["EDGE"] = "edge";
19
+ })(AgentRelease || (AgentRelease = {}));
20
20
  export const BuildkiteDefaultProps = {
21
21
  // Buildkite Agent Configuration
22
22
  elasticStackVersion: "v6.30.0",
23
23
  keyName: "",
24
- buildkiteAgentRelease: agentRelease.STABLE,
24
+ buildkiteAgentRelease: AgentRelease.STABLE,
25
25
  buildkiteAgentTags: "",
26
26
  buildkiteAgentTimestampLines: false,
27
27
  buildkiteAgentExperiments: "",
@@ -66,13 +66,13 @@ export const BuildkiteDefaultProps = {
66
66
  export class Buildkite extends Stack {
67
67
  constructor(scope, id, props) {
68
68
  super(scope, id, props);
69
- // TODO: Make this immutable and enforce the tags being set
70
- const tags = {
71
- ...props.tags,
72
- "fjall:costAllocation:environment": props.environment || "platform",
73
- "fjall:costAllocation:service": "buildkite",
74
- "fjall:costAllocation:owner": props.owner || "engineer" // TODO: this will have to be the platform account name?
75
- };
69
+ applyCostAllocationTags(this, {
70
+ service: "buildkite",
71
+ domain: "platform",
72
+ environment: props.environment || "platform",
73
+ owner: props.owner ?? "engineer"
74
+ });
75
+ const tags = { ...props.tags };
76
76
  // VPC
77
77
  const vpc = new Vpc(this, `${id}Vpc`, {
78
78
  accountId: props.accountId,
@@ -85,25 +85,29 @@ export class Buildkite extends Stack {
85
85
  });
86
86
  // Artifacts Bucket
87
87
  const artifactBucket = new S3Bucket(this, `${id}ArtifactBucket`);
88
- // Managed Secrets
89
88
  const managedSecretsBucket = new S3Bucket(this, `${id}ManagedSecretsBucket`);
90
- if (process.env.BUILDKITE_PRIVATE_SSH_KEY) {
89
+ const buildkitePrivateSshKey = process.env.BUILDKITE_PRIVATE_SSH_KEY;
90
+ const hasBuildkitePrivateSshKey = buildkitePrivateSshKey !== undefined && buildkitePrivateSshKey !== "";
91
+ if (hasBuildkitePrivateSshKey) {
92
+ // Synth-time secret bake: Source.data() inlines the env var into the
93
+ // CDK asset bundle uploaded to the bootstrap S3 staging bucket. The
94
+ // synth host MUST hold the secret in env, and the CDK staging bucket
95
+ // inherits the secret's blast radius. Treat as Buildkite-only opt-in.
91
96
  new BucketDeployment(this, `${id}SshKeyDeployment`, {
92
- sources: [
93
- Source.data("private_ssh_key", process.env.BUILDKITE_PRIVATE_SSH_KEY)
94
- ],
97
+ sources: [Source.data("private_ssh_key", buildkitePrivateSshKey)],
95
98
  destinationBucket: managedSecretsBucket
96
99
  });
97
100
  }
98
101
  else {
99
102
  FjallLogger.warn("'BUILDKITE_PRIVATE_SSH_KEY' environment variable not declared. Skipping upload of private SSH key.");
100
103
  }
101
- // Encrypted Buildkite Agent Token
104
+ const buildkiteAgentToken = process.env.BUILDKITE_AGENT_TOKEN;
105
+ const hasBuildkiteAgentToken = buildkiteAgentToken !== undefined && buildkiteAgentToken !== "";
102
106
  const agentToken = new SecureStringParameter(this, `${id}AgentToken`, {
103
107
  name: `/buildkite/agentToken`,
104
108
  aliasName: `buildkiteAgentToken`,
105
- value: process.env.BUILDKITE_AGENT_TOKEN,
106
- overwrite: process.env.BUILDKITE_AGENT_TOKEN ? true : false,
109
+ value: buildkiteAgentToken,
110
+ overwrite: hasBuildkiteAgentToken,
107
111
  tags: tags,
108
112
  accountId: this.account,
109
113
  region: this.region
@@ -241,10 +245,11 @@ export class Buildkite extends Stack {
241
245
  installElasticStackUserData.addCommands(`BUILDKITE_STACK_NAME='${id}' \\`, `BUILDKITE_STACK_VERSION='${props.elasticStackVersion}' \\`, `BUILDKITE_SCALE_IN_IDLE_PERIOD='${props.scaleInIdlePeriod}' \\`, `BUILDKITE_SECRETS_BUCKET='${managedSecretsBucket.bucketName}' \\`, `BUILDKITE_SECRETS_BUCKET_REGION='${props.env?.region}' \\`, `BUILDKITE_AGENT_TOKEN_PATH='${agentToken.name}' \\`, `BUILDKITE_AGENTS_PER_INSTANCE='${props.agentsPerInstance}' \\`, `BUILDKITE_AGENT_TAGS='${props.buildkiteAgentTags}' \\`, `BUILDKITE_AGENT_TIMESTAMP_LINES='${props.buildkiteAgentTimestampLines}' \\`, `BUILDKITE_AGENT_EXPERIMENTS='${props.buildkiteAgentExperiments}' \\`, `BUILDKITE_AGENT_TRACING_BACKEND='${props.buildkiteAgentTracingBackend}' \\`, `BUILDKITE_AGENT_RELEASE='${props.buildkiteAgentRelease}' \\`, `BUILDKITE_AGENT_CANCEL_GRACE_PERIOD='${props.buildkiteAgentCancelGracePeriod}' \\`, `BUILDKITE_AGENT_SIGNING_KMS_KEY='${props.pipelineSigningKMSKey}' \\`, `BUILDKITE_AGENT_SIGNING_FAILURE_BEHAVIOR='${props.pipelineSigningVerificationFailureBehavior}' \\`, `BUILDKITE_QUEUE='${props.buildkiteQueue}' \\`, `BUILDKITE_AGENT_ENABLE_GIT_MIRRORS='${props.buildkiteAgentEnableGitMirrors}' \\`, `BUILDKITE_ELASTIC_BOOTSTRAP_SCRIPT='${props.bootstrapScriptUrl}' \\`, `BUILDKITE_ENV_FILE_URL='${props.agentEnvFileUrl}' \\`, `BUILDKITE_ENABLE_INSTANCE_STORAGE='${props.enableInstanceStorage}' \\`, `BUILDKITE_AUTHORIZED_USERS_URL='${props.authorizedUsersUrl}' \\`, `BUILDKITE_ECR_POLICY='${props.ecrAccessPolicy}' \\`, `BUILDKITE_TERMINATE_INSTANCE_AFTER_JOB='${props.buildkiteTerminateInstanceAfterJob}' \\`, `BUILDKITE_ADDITIONAL_SUDO_PERMISSIONS='${props.buildkiteAdditionalSudoPermissions}' \\`, `AWS_DEFAULT_REGION='${props.env?.region}' \\`, `SECRETS_PLUGIN_ENABLED='${props.enableSecretsPlugin}' \\`, `ECR_PLUGIN_ENABLED='${props.enableEcrPlugin}' \\`, `DOCKER_LOGIN_PLUGIN_ENABLED='${props.enableDockerLoginPlugin}' \\`, `DOCKER_EXPERIMENTAL='${props.enableDockerExperimental}' \\`, `DOCKER_USERNS_REMAP='${props.enableDockerUserNamespaceRemap}' \\`, `AWS_REGION='${props.env?.region}' \\`, "/usr/local/bin/bk-install-elastic-stack.sh");
242
246
  // Merge User Data
243
247
  multipartUserData.addPart(MultipartBody.fromUserData(installElasticStackUserData, "text/x-shellscript; charset='us-ascii'"));
244
- // Launch Template
245
- const launchTemplate = new LaunchTemplate(this, `${id}AgentLaunchTemplate`, {
246
- launchTemplateName: `buildkiteLaunchTemplate`,
247
- instanceType: props.agentInstanceType,
248
+ const ec2Instance = new Ec2Instance(this, `${id}Agent`, {
249
+ serviceName: `${id}Agent`,
250
+ vpc,
251
+ vpcSubnets: { subnetType: SubnetType.PUBLIC },
252
+ instanceType: props.agentInstanceType.toString(),
248
253
  machineImage: MachineImage.lookup({
249
254
  name: "buildkite-stack-linux-x86_64-*",
250
255
  owners: ["172840064832"],
@@ -257,46 +262,17 @@ export class Buildkite extends Stack {
257
262
  blockDevices: [
258
263
  {
259
264
  deviceName: "/dev/xvda",
260
- volume: BlockDeviceVolume.ebs(props.agentVolumeSize)
265
+ volume: safeEbs(props.agentVolumeSize)
261
266
  }
262
267
  ],
263
- detailedMonitoring: true,
264
- requireImdsv2: false,
265
- httpPutResponseHopLimit: 2,
266
- httpTokens: LaunchTemplateHttpTokens.REQUIRED,
267
- instanceMetadataTags: true
268
- });
269
- // Functional tags for buildkite agent identification
270
- Tags.of(launchTemplate).add("Role", "buildkiteAgent");
271
- Tags.of(launchTemplate).add("BuildkiteAgentRelease", agentRelease.STABLE);
272
- Tags.of(launchTemplate).add("BuildkiteQueue", props.buildkiteQueue);
273
- // Autoscaling Group
274
- const autoScalingGroup = new AutoScalingGroup(this, `${id}AgentAutoScalingGroup`, {
275
- vpc: vpc,
276
- mixedInstancesPolicy: {
277
- launchTemplate: launchTemplate,
278
- instancesDistribution: {
279
- onDemandPercentageAboveBaseCapacity: props.spotCapacityPercentage,
280
- spotAllocationStrategy: SpotAllocationStrategy.CAPACITY_OPTIMIZED
281
- },
282
- launchTemplateOverrides: [
283
- {
284
- instanceType: props.agentInstanceType
285
- }
286
- ]
287
- },
288
268
  minCapacity: props.agentMinInstances,
289
269
  maxCapacity: props.agentMaxInstances,
290
- cooldown: Duration.seconds(60),
291
- groupMetrics: [GroupMetrics.all()],
292
- updatePolicy: UpdatePolicy.replacingUpdate(),
293
- newInstancesProtectedFromScaleIn: true,
294
- terminationPolicies: [
295
- TerminationPolicy.OLDEST_LAUNCH_CONFIGURATION,
296
- TerminationPolicy.CLOSEST_TO_NEXT_INSTANCE_HOUR
297
- ],
298
- ssmSessionPermissions: true
270
+ spotCapacityPercentage: props.spotCapacityPercentage
299
271
  });
272
+ Tags.of(ec2Instance).add("Role", "buildkiteAgent");
273
+ Tags.of(ec2Instance).add("BuildkiteAgentRelease", props.buildkiteAgentRelease);
274
+ Tags.of(ec2Instance).add("BuildkiteQueue", props.buildkiteQueue);
275
+ const autoScalingGroup = ec2Instance.getAutoScalingGroup();
300
276
  agentRole.attachInlinePolicy(new Policy(this, `${id}UpdateAutoScalingGroupPolicy`, {
301
277
  statements: [
302
278
  new PolicyStatement({
@@ -308,33 +284,9 @@ export class Buildkite extends Stack {
308
284
  })
309
285
  ]
310
286
  }));
311
- // Buildkite Suspend Austoscaling Group Custom Resource
312
- new AwsCustomResource(this, `${id}SuspendAutoscalingProcess`, {
313
- onCreate: {
314
- service: "AutoScaling",
315
- action: "suspendProcesses",
316
- parameters: {
317
- AutoScalingGroupName: autoScalingGroup.autoScalingGroupName,
318
- ScalingProcesses: ["AZRebalance"]
319
- },
320
- physicalResourceId: PhysicalResourceId.of("suspendAutoScalingProcessess")
321
- },
322
- onUpdate: {
323
- service: "AutoScaling",
324
- action: "suspendProcesses",
325
- parameters: {
326
- AutoScalingGroupName: autoScalingGroup.autoScalingGroupName,
327
- ScalingProcesses: ["AZRebalance"]
328
- },
329
- physicalResourceId: PhysicalResourceId.of("suspendAutoScalingProcessess")
330
- },
331
- resourceType: "Custom::buildkiteSuspendAutoscaling"
332
- });
333
- new CfnApplication(this, `${id}AgentScaler`, {
334
- location: {
335
- applicationId: "arn:aws:serverlessrepo:us-east-1:172840064832:applications/buildkite-agent-scaler",
336
- semanticVersion: props.buildkiteAgentScalerVersion
337
- },
287
+ new SamApplication(this, `${id}AgentScaler`, {
288
+ applicationId: "arn:aws:serverlessrepo:us-east-1:172840064832:applications/buildkite-agent-scaler",
289
+ semanticVersion: props.buildkiteAgentScalerVersion,
338
290
  parameters: {
339
291
  BuildkiteAgentTokenParameter: `${agentToken.name}`,
340
292
  BuildkiteAgentTokenParameterStoreKMSKey: agentToken.cmk.key.keyId,
@@ -349,7 +301,9 @@ export class Buildkite extends Stack {
349
301
  EventSchedulePeriod: props.scalerEventSchedulePeriod,
350
302
  MinPollInterval: props.scalerMinPollInterval,
351
303
  LogRetentionDays: `${props.logRetentionDays}`
352
- }
304
+ },
305
+ costAllocationService: "buildkite",
306
+ costAllocationDomain: "buildkite-agent-scaler"
353
307
  });
354
308
  }
355
309
  }
@@ -57,6 +57,7 @@ function validateCdnProps(props) {
57
57
  */
58
58
  export class Cdn extends CloudFrontDistribution {
59
59
  constructor(scope, id, props) {
60
+ validateCdnProps(props);
60
61
  const resolvedProps = Cdn.resolveProps(scope, id, props);
61
62
  super(scope, id, resolvedProps);
62
63
  }
@@ -247,7 +248,6 @@ export class CdnFactory {
247
248
  */
248
249
  static build(id, props) {
249
250
  return (_app, scope) => {
250
- validateCdnProps(props);
251
251
  return new Cdn(scope, id, props);
252
252
  };
253
253
  }
@@ -0,0 +1,173 @@
1
+ import { Connections, type IConnectable, type IVpc } from "aws-cdk-lib/aws-ec2";
2
+ import { type TaskDefinition } from "aws-cdk-lib/aws-ecs";
3
+ import { type IBucket } from "aws-cdk-lib/aws-s3";
4
+ import { Construct } from "constructs";
5
+ import { Secret } from "../../resources/aws/secrets/secret.js";
6
+ import { type ClickHouseSchemaAdmin, type ProfileSpec } from "../../resources/aws/database/clickhouseSchemas.js";
7
+ import { type IClickHouseDatabase } from "./interfaces/database.js";
8
+ import { type ISecurityGroupConnector } from "./interfaces/connector.js";
9
+ import { type MigrationContributions } from "./interfaces/migrationContributor.js";
10
+ /**
11
+ * ClickHouse analytics database configuration properties (D8 + D12 + D16).
12
+ */
13
+ export interface ClickHouseDatabaseProps {
14
+ type: "ClickHouse";
15
+ /** VPC to deploy into. Falls back to `app.getVpc()` via the factory. */
16
+ vpc?: IVpc;
17
+ /** EC2 instance type. Default: `m7g.medium` (1 vCPU sustained, 4 GiB).
18
+ * CH user-data is tuned for 1 vCPU; raise per-user `max_threads` and
19
+ * `max_concurrent_queries` if bumping to a >=2 vCPU host. */
20
+ instanceType?: string;
21
+ /**
22
+ * ECS service desired task count. Defaults to 1 (single-node, single-task
23
+ * by design). Override to 0 via the `clickhouseDesiredCount` CDK context
24
+ * (`cdk deploy -c clickhouseDesiredCount=0 …`) to deploy the cluster + ASG
25
+ * without scheduling a CH task — useful when bringing up a fresh stack so
26
+ * a failed task placement does not trigger CFN circuit-breaker rollback
27
+ * before the operator can inspect logs.
28
+ *
29
+ * Once the stack is stable, redeploy without the context flag (or set it
30
+ * back to 1) to schedule the CH task.
31
+ *
32
+ * Numeric context-value parsing handles both string ("0" via `--context`)
33
+ * and number (0 via `cdk.json`) shapes. */
34
+ desiredCount?: number;
35
+ /**
36
+ * Cold-tier configuration (D27 + D12).
37
+ * - omitted/undefined: cold tier ENABLED (S3 bucket provisioned).
38
+ * - `false`: cold tier DISABLED (single-tier hot storage on EBS only).
39
+ * - `{ mode: "s3" }`: cold tier ENABLED (explicit).
40
+ */
41
+ coldTier?: false | {
42
+ mode: "s3";
43
+ };
44
+ /** Tier 4 escape hatch (D16): bring-your-own backup bucket. */
45
+ backupBucket?: IBucket;
46
+ /** Tier 4 escape hatch (D16): bring-your-own cold-tier bucket. */
47
+ coldTierBucket?: IBucket;
48
+ /**
49
+ * OPTIMIZE TABLE FINAL schedule (D19). Schedule string validated by CDK
50
+ * `Schedule.expression(...)` at synth time. `false` disables the sidecar.
51
+ * Default: `OPTIMISE_FINAL_SCHEDULE` from `clickhouseConstants.ts`.
52
+ */
53
+ optimiseSchedule?: string | false;
54
+ /**
55
+ * BACKUP DATABASE TO S3 schedule (D19). Schedule string validated by CDK
56
+ * `Schedule.expression(...)` at synth time. `false` disables the sidecar
57
+ * (and skips the backup-task log group).
58
+ * Default: `BACKUP_SCHEDULE` from `clickhouseConstants.ts`.
59
+ */
60
+ backupSchedule?: string | false;
61
+ /**
62
+ * Backup-bucket lifecycle expiration in days for both current and noncurrent
63
+ * versions. Default: `BACKUP_RETENTION_DAYS` from `clickhouseConstants.ts`.
64
+ * Ignored when `backupBucket` is supplied (caller-owned lifecycle).
65
+ */
66
+ backupRetentionDays?: number;
67
+ /**
68
+ * Bootstrap-privileged user. Owns DDL + GRANTs, runs customer SQL
69
+ * migrations. Rendered into `users.d/fjall.xml` with
70
+ * `<access_management>1</access_management>` so it can manage GRANT /
71
+ * CREATE USER from SQL. `profile` MUST name a key in `profiles:` (or
72
+ * `ClickHouseDefaultProfiles`) and is bound directly via the XML config.
73
+ * Scheduled tasks (OPTIMIZE FINAL, BACKUP DATABASE) authenticate as this
74
+ * user — one set of credentials, one IAM grant chain.
75
+ */
76
+ schemaAdmin: ClickHouseSchemaAdmin;
77
+ /**
78
+ * Workload user names. The framework mints a Secret for each, grants the
79
+ * EC2 instance role read on it, and the migration helper issues
80
+ * `CREATE USER … IDENTIFIED WITH sha256_password …` at runtime. Profile
81
+ * binding and GRANTs flow via customer SQL — the framework owns identity
82
+ * + password material only.
83
+ *
84
+ * Names MUST be lowercase snake_case (`^[a-z][a-z0-9_]*$`), unique, and
85
+ * not overlap with `schemaAdmin.name`. Default: empty.
86
+ */
87
+ managedPasswords?: string[];
88
+ /**
89
+ * Per-profile resource caps. Profile keys MUST match lowercase snake_case
90
+ * (`^[a-z][a-z0-9_]*$`). Defaults to `ClickHouseDefaultProfiles` when
91
+ * omitted — four workload-class profiles
92
+ * (`high_throughput_ingest`, `audit_append`, `read_only`, `ddl_admin`).
93
+ *
94
+ * Throws `Error` on validation failure — unknown profile fields,
95
+ * non-snake_case names.
96
+ */
97
+ profiles?: Record<string, ProfileSpec>;
98
+ }
99
+ /**
100
+ * ClickHouse analytics database wrapper implementing IClickHouseDatabase.
101
+ *
102
+ * Composes `EcsCompute` directly per Phase 5e D7 — one EC2-pinned service
103
+ * (single-instance, AWS_VPC mode, Cloud Map registered) plus two scheduled
104
+ * tasks (optimise + backup). Per-role secrets, dual S3 buckets, and 10
105
+ * CfnOutputs are owned by `ClickHouseDatabase` itself; every taggable
106
+ * resource routes through its Fjall wrapper (AC45d-g).
107
+ */
108
+ export declare class ClickHouseDatabase extends Construct implements IClickHouseDatabase, ISecurityGroupConnector {
109
+ #private;
110
+ readonly databaseType: "ClickHouse";
111
+ readonly connectorType: "relational";
112
+ readonly additionalTcpPorts: number[];
113
+ readonly id: string;
114
+ readonly connections: Connections;
115
+ constructor(scope: Construct, id: string, props: ClickHouseDatabaseProps);
116
+ /**
117
+ * Returns the Fjall `Secret` wrapper for the named user. Throws with a
118
+ * `Known users:` list if the name is not present in the construct's
119
+ * `schemaAdmin:` / `managedPasswords:` props.
120
+ */
121
+ getUser(name: string): Secret;
122
+ /**
123
+ * Non-throwing sibling of `getUser`. Returns the Fjall `Secret` wrapper for
124
+ * the named user, or `undefined` when no such user is declared. Used by
125
+ * `getMigrationContributions()` to gracefully skip credential wiring when the
126
+ * caller did not declare a `migrationUser:` on the database.
127
+ */
128
+ tryGetUser(name: string): Secret | undefined;
129
+ getHttpPort(): number;
130
+ getNativePort(): number;
131
+ getHostEndpoint(): string;
132
+ getHttpUrl(): string;
133
+ getNativeUrl(): string;
134
+ getDatabaseName(): string;
135
+ getBackupBucket(): IBucket;
136
+ getColdTierBucket(): IBucket | undefined;
137
+ grantConnect(grantee: IConnectable): void;
138
+ /**
139
+ * Migration contributions for a task connecting to this ClickHouse cluster
140
+ * via `service.connections:`. Contributes env (`CLICKHOUSE_URL`,
141
+ * `CLICKHOUSE_DATABASE`, plus the managed-user manifest under
142
+ * `CLICKHOUSE_MANAGED_USERS`) and egress to the cluster's HTTP port.
143
+ *
144
+ * **Schema admin.** The bootstrap-privileged user's password is imported as
145
+ * `SCHEMA_ADMIN_PASSWORD` so customer SQL migrations can authenticate. The
146
+ * schema admin is defined in `users.d/fjall.xml` (users_xml storage =
147
+ * read-only); its password syncs via XML reload on EC2 boot or via the
148
+ * Custom::AWS SYSTEM RELOAD USERS resource on stack updates — NOT via the
149
+ * migration helper. The admin is therefore NOT included in the manifest.
150
+ *
151
+ * **Managed-password workload users.** Every entry in `managedPasswords` is
152
+ * added to the manifest (name only — profile binding is customer SQL's
153
+ * concern) AND its `password` secret is imported as `USER_<NAME>_PASSWORD`
154
+ * so the migration container boots with each plaintext already in
155
+ * `process.env`. The helper reads the env vars directly — no runtime
156
+ * `secretsmanager:GetSecretValue` SDK call is needed; ECS executionRole
157
+ * carries the IAM grant via the standard `secretsImport` framework path.
158
+ */
159
+ getMigrationContributions(): MigrationContributions;
160
+ /**
161
+ * Wires a task definition to connect to ClickHouse as `opts.user` (if
162
+ * supplied). Adds `CLICKHOUSE_URL` / `CLICKHOUSE_DATABASE` env vars to the
163
+ * task's default container; when `opts.user` is set, also adds
164
+ * `CLICKHOUSE_USER` (plain env) and `CLICKHOUSE_PASSWORD` (Secrets
165
+ * Manager-backed env var resolved from the user's secret). Throws if the
166
+ * user is unknown. Callers separately call `grantConnect(service)` on the
167
+ * resulting ECS service for the network grant — `TaskDefinition` itself
168
+ * isn't `IConnectable`.
169
+ */
170
+ connectFromTask(task: TaskDefinition, opts?: {
171
+ user?: string;
172
+ }): void;
173
+ }