@fjall/components-infrastructure 0.77.4 → 0.78.5

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 (64) hide show
  1. package/dist/lib/app.d.ts +8 -5
  2. package/dist/lib/app.js +19 -7
  3. package/dist/lib/patterns/aws/buildkite.js +4 -7
  4. package/dist/lib/patterns/aws/compute.d.ts +479 -48
  5. package/dist/lib/patterns/aws/compute.js +307 -94
  6. package/dist/lib/patterns/aws/database.d.ts +1 -0
  7. package/dist/lib/patterns/aws/database.js +4 -1
  8. package/dist/lib/patterns/aws/hostedZone.js +4 -7
  9. package/dist/lib/patterns/aws/loadBalancer.d.ts +163 -0
  10. package/dist/lib/patterns/aws/loadBalancer.js +278 -0
  11. package/dist/lib/patterns/aws/network.d.ts +1 -0
  12. package/dist/lib/patterns/aws/network.js +2 -1
  13. package/dist/lib/resources/aws/compute/capacityProviderDrainWaiter.d.ts +20 -0
  14. package/dist/lib/resources/aws/compute/capacityProviderDrainWaiter.js +180 -0
  15. package/dist/lib/resources/aws/compute/ecs.d.ts +294 -57
  16. package/dist/lib/resources/aws/compute/ecs.js +745 -261
  17. package/dist/lib/resources/aws/compute/ecsFreeTier.js +1 -1
  18. package/dist/lib/resources/aws/compute/ecsSpot.js +1 -1
  19. package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.d.ts +20 -0
  20. package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.js +180 -0
  21. package/dist/lib/resources/aws/database/rdsAurora.d.ts +1 -0
  22. package/dist/lib/resources/aws/database/rdsAurora.js +2 -2
  23. package/dist/lib/resources/aws/database/rdsAuroraGlobal.d.ts +1 -0
  24. package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +2 -1
  25. package/dist/lib/resources/aws/database/rdsDeletionWaiter.d.ts +33 -0
  26. package/dist/lib/resources/aws/database/rdsDeletionWaiter.js +74 -0
  27. package/dist/lib/resources/aws/database/rdsInstance.d.ts +1 -0
  28. package/dist/lib/resources/aws/database/rdsInstance.js +3 -3
  29. package/dist/lib/resources/aws/networking/vpc.d.ts +1 -0
  30. package/dist/lib/resources/aws/networking/vpc.js +4 -3
  31. package/dist/lib/resources/aws/networking/vpcEndpoint.d.ts +2 -2
  32. package/dist/lib/resources/aws/networking/vpcEndpoint.js +1 -1
  33. package/dist/lib/resources/aws/networking/vpcEndpoints.d.ts +71 -0
  34. package/dist/lib/resources/aws/networking/vpcEndpoints.js +125 -0
  35. package/dist/lib/resources/aws/secrets/kms.d.ts +14 -0
  36. package/dist/lib/resources/aws/secrets/kms.js +5 -2
  37. package/dist/lib/resources/aws/secrets/secret.js +1 -1
  38. package/dist/lib/utils/standardTagsAspect.d.ts +26 -12
  39. package/dist/lib/utils/standardTagsAspect.js +67 -477
  40. package/dist/lib/utils/tagResource.d.ts +18 -3
  41. package/dist/lib/utils/tagResource.js +23 -6
  42. package/package.json +3 -3
  43. package/dist/lib/aspects/resourceInventory.d.ts +0 -41
  44. package/dist/lib/aspects/resourceInventory.js +0 -56
  45. package/dist/lib/config/audit.d.ts +0 -18
  46. package/dist/lib/config/audit.js +0 -22
  47. package/dist/lib/patterns/aws/auditRole.d.ts +0 -44
  48. package/dist/lib/patterns/aws/auditRole.js +0 -58
  49. package/dist/lib/patterns/aws/basicApp.d.ts +0 -0
  50. package/dist/lib/patterns/aws/basicApp.js +0 -150
  51. package/dist/lib/patterns/aws/ec2.d.ts +0 -43
  52. package/dist/lib/patterns/aws/ec2.js +0 -123
  53. package/dist/lib/patterns/aws/freeTierApp.d.ts +0 -44
  54. package/dist/lib/patterns/aws/freeTierApp.js +0 -83
  55. package/dist/lib/patterns/aws/spotInstanceApp.d.ts +0 -45
  56. package/dist/lib/patterns/aws/spotInstanceApp.js +0 -85
  57. package/dist/lib/resources/aws/audit/auditRole.d.ts +0 -32
  58. package/dist/lib/resources/aws/audit/auditRole.js +0 -46
  59. package/dist/lib/resources/aws/database/databaseFreeTier.d.ts +0 -15
  60. package/dist/lib/resources/aws/database/databaseFreeTier.js +0 -29
  61. package/dist/lib/resources/aws/database/rdsFreeTier.d.ts +0 -37
  62. package/dist/lib/resources/aws/database/rdsFreeTier.js +0 -84
  63. package/dist/lib/utils/getCidr.d.ts +0 -8
  64. package/dist/lib/utils/getCidr.js +0 -40
@@ -1,13 +1,12 @@
1
- import { ContainerImage, type RepositoryImage } from "aws-cdk-lib/aws-ecs";
1
+ import { Cluster as CdkCluster, FargateService, Ec2Service, type RepositoryImage } from "aws-cdk-lib/aws-ecs";
2
2
  import { Connections, type IConnectable, type IVpc } from "aws-cdk-lib/aws-ec2";
3
3
  import { Construct } from "constructs";
4
4
  import { type StackBuilder } from "../base/awsStack";
5
- import { type SecretValue } from "aws-cdk-lib";
5
+ import { type ApplicationListener, ApplicationLoadBalancer } from "aws-cdk-lib/aws-elasticloadbalancingv2";
6
6
  import { type IManagedPolicy, PolicyDocument } from "aws-cdk-lib/aws-iam";
7
7
  import { Certificate } from "aws-cdk-lib/aws-certificatemanager";
8
8
  import { type GeoLocation } from "aws-cdk-lib/aws-route53";
9
9
  import { Repository } from "aws-cdk-lib/aws-ecr";
10
- import { type KeyValue } from "../../../types";
11
10
  import { HostedZone as FjallHostedZone } from "../../../patterns/aws/hostedZone";
12
11
  import { type SecretImport } from "../secrets";
13
12
  export declare enum Protocol {
@@ -18,14 +17,25 @@ export declare enum ScalingType {
18
17
  CPU = "ECSServiceAverageCPUUtilization",
19
18
  MEMORY = "ECSServiceAverageMemoryUtilization"
20
19
  }
21
- export interface ContainerSecret {
22
- [key: string]: SecretValue;
20
+ export type EcsCapacityProvider = "FARGATE" | "FARGATE_SPOT" | "EC2";
21
+ /**
22
+ * EC2 capacity configuration for ECS EC2-backed clusters.
23
+ * Only used when capacityProvider is "EC2".
24
+ */
25
+ export interface Ec2CapacityConfig {
26
+ /** EC2 instance type. Default: "t3.micro" */
27
+ instanceType?: string;
28
+ /** AMI hardware type. Default: "ARM" (Graviton - better cost/performance) */
29
+ amiHardwareType?: "ARM" | "STANDARD";
30
+ /** Minimum number of instances. Default: 2 */
31
+ minCapacity?: number;
32
+ /** Maximum number of instances. Default: 3 */
33
+ maxCapacity?: number;
34
+ /** Memory limit in MiB for the container. Default: 1024 */
35
+ memoryLimitMiB?: number;
23
36
  }
24
37
  /**
25
- * DomainConfiguration
26
- * - When supplied a domain name, a hosted zone, certificate and ARecord will be created
27
- * - When supplied a domain name and hosted zone, a certificate and ARecord will be created
28
- * - When all properties are supplied only a target will be created
38
+ * Domain configuration for HTTPS and DNS.
29
39
  */
30
40
  export interface DomainBaseConfig {
31
41
  domainName: string;
@@ -43,67 +53,294 @@ export interface GeoLocationDomainConfig extends DomainBaseConfig {
43
53
  geoLocation: GeoLocation;
44
54
  }
45
55
  export type DomainConfig = DomainBaseConfig | LatencyDomainConfig | WeightedDomainConfig | GeoLocationDomainConfig;
46
- export type FargateClusterProps = {
47
- ecrRepository: Repository | RepositoryImage;
48
- clusterName: string;
49
- containerCommand?: string[];
50
- containerEnvironment?: KeyValue;
51
- containerSecrets?: ContainerSecret;
52
- containerSecretsImport?: {
56
+ /**
57
+ * Internal configuration for a container in a multi-container ECS task.
58
+ *
59
+ * In multi-container tasks, the first container with a `port` is the **primary container**
60
+ * that receives load balancer traffic. All other containers are **sidecars** that provide
61
+ * supporting functionality (logging, monitoring, proxies, etc.).
62
+ *
63
+ * @example
64
+ * // Primary container (has port) + sidecar (no port)
65
+ * containers: [
66
+ * { name: "app", port: 3000 }, // Primary - receives ALB traffic
67
+ * { name: "datadog", image: "datadog/agent" } // Sidecar - monitoring
68
+ * ]
69
+ *
70
+ * @internal
71
+ */
72
+ export interface EcsClusterContainerConfig {
73
+ /** Unique container name */
74
+ name: string;
75
+ /**
76
+ * Container image. Options:
77
+ * - Omit: Uses default ECR repository (primary container only)
78
+ * - string: ECR repository name or public image URL
79
+ * - Repository: CDK ECR Repository construct
80
+ */
81
+ image?: string | Repository;
82
+ /**
83
+ * Port the container listens on.
84
+ * The first container with a port becomes the **primary container**
85
+ * and is registered with the load balancer.
86
+ */
87
+ port?: number;
88
+ /** Environment variables */
89
+ environment?: Record<string, string>;
90
+ /** Secrets imported from other resources */
91
+ secretsImport?: {
53
92
  [key: string]: SecretImport;
54
93
  };
55
- containerPort?: number;
56
- cpu?: number;
94
+ /** Command to run in the container */
95
+ command?: string[];
96
+ /** Entry point for the container */
97
+ entryPoint?: string[];
98
+ /**
99
+ * Whether this container is essential.
100
+ * If an essential container stops, all containers in the task stop.
101
+ * Default: true for primary container, true for sidecars
102
+ */
103
+ essential?: boolean;
104
+ /**
105
+ * Health check configuration.
106
+ * Default: For primary container with port, uses curl health check.
107
+ */
108
+ healthCheck?: {
109
+ command: string[];
110
+ interval?: number;
111
+ timeout?: number;
112
+ retries?: number;
113
+ startPeriod?: number;
114
+ };
115
+ }
116
+ /**
117
+ * Cluster-level configuration.
118
+ * Controls the shared ALB for all services in this cluster.
119
+ */
120
+ export interface EcsClusterClusterConfig {
121
+ /**
122
+ * Domain for HTTPS access.
123
+ * - Omit: ALB created with default DNS (*.elb.amazonaws.com)
124
+ * - Specified: Creates ACM certificate + Route53 DNS A record
125
+ */
126
+ domain?: string;
127
+ /**
128
+ * Load balancer configuration.
129
+ * - false: No ALB (for workers/internal services)
130
+ * - "public": Internet-facing ALB (default)
131
+ * - "internal": VPC-only ALB
132
+ */
133
+ loadBalancer?: false | "public" | "internal";
134
+ /**
135
+ * Enable direct EC2 access without ALB.
136
+ * Opens container ports on security group for direct access via EC2 public IP.
137
+ * Uses host network mode for predictable port mapping (container:3000 → host:3000).
138
+ * Only valid with EC2 capacity provider.
139
+ */
140
+ directAccess?: boolean;
141
+ /**
142
+ * Domain configuration for advanced routing policies (latency, weighted, geo).
143
+ * Only used when domain is specified.
144
+ */
57
145
  domainConfig?: DomainConfig;
58
- desiredCount?: number;
146
+ }
147
+ /**
148
+ * Routing configuration for path/host-based routing on the ALB.
149
+ */
150
+ export interface EcsRoutingConfig {
151
+ /** Path pattern for routing (e.g., "/api/*", "/users/*") */
152
+ path?: string;
153
+ /** Host header for routing (e.g., "api.example.com") */
154
+ host?: string;
155
+ /** Priority for this routing rule (1-50000). Lower = higher priority. */
156
+ priority?: number;
157
+ /** Health check path for this service's target group. Default: "/" */
59
158
  healthCheckPath?: string;
60
- listenerPort?: number;
159
+ }
160
+ /**
161
+ * Configuration for a service in an ECS cluster.
162
+ * Each service gets its own task definition, scaling, and target group.
163
+ */
164
+ export interface EcsServiceProps {
165
+ /** Service name (unique within cluster) */
166
+ name: string;
167
+ /**
168
+ * Container image for this service.
169
+ * - Omit: Uses cluster's default ECR repository
170
+ * - string: ECR repository name or public image URL
171
+ * - Repository: CDK ECR Repository construct
172
+ */
173
+ image?: string | Repository;
174
+ /**
175
+ * Container configurations for this service.
176
+ * The first container with a port is the **primary container** (receives ALB traffic).
177
+ */
178
+ containers: EcsClusterContainerConfig[];
179
+ /** CPU units for this service's tasks (256-4096) */
180
+ cpu?: number;
181
+ /** Memory in MiB for this service's tasks (512-30720) */
61
182
  memoryLimitMiB?: number;
62
- publicLoadBalancer?: boolean;
63
- protocol: Protocol;
183
+ /** Desired number of tasks. Default: 2 */
184
+ desiredCount?: number;
185
+ /** Scaling type (CPU or MEMORY). Omit to disable auto-scaling. */
64
186
  scalingType?: ScalingType;
65
- serviceName: string;
187
+ /** Minimum number of tasks for auto-scaling. Default: 2 */
188
+ minCapacity?: number;
189
+ /** Maximum number of tasks for auto-scaling. Default: 10 */
190
+ maxCapacity?: number;
191
+ /**
192
+ * Routing rules for this service on the cluster's ALB.
193
+ * Required when cluster has multiple services with ports.
194
+ */
195
+ routing?: EcsRoutingConfig;
196
+ /**
197
+ * Additional inline policies for this service's task role.
198
+ * Added on top of the default ECS Exec permissions.
199
+ */
66
200
  taskRoleInlinePolicies?: {
67
201
  [name: string]: PolicyDocument;
68
202
  };
203
+ /**
204
+ * Additional managed policies for this service's task role.
205
+ * Added on top of the default ECS Exec permissions.
206
+ */
69
207
  taskRoleManagedPolicies?: IManagedPolicy[];
208
+ /**
209
+ * Resources this service needs to connect to (e.g., databases).
210
+ * Creates security group rules to allow traffic from this specific service only.
211
+ */
212
+ connections?: IConnectable[];
213
+ }
214
+ /**
215
+ * Props for creating an ECS cluster with multiple services.
216
+ */
217
+ export type EcsClusterProps = {
218
+ /** Cluster name */
219
+ clusterName: string;
220
+ /** VPC to deploy into */
70
221
  vpc?: IVpc;
222
+ /** Default ECR repository or container image */
223
+ ecrRepository: Repository | RepositoryImage | string;
224
+ /** Capacity provider determines Fargate vs EC2 infrastructure */
225
+ capacityProvider?: EcsCapacityProvider;
226
+ /** EC2-specific configuration. Only used when capacityProvider is "EC2" */
227
+ ec2Config?: Ec2CapacityConfig;
228
+ /**
229
+ * Cluster configuration.
230
+ * Controls the shared ALB for all services.
231
+ */
232
+ cluster?: EcsClusterClusterConfig;
233
+ /**
234
+ * Services in this cluster.
235
+ * Each service gets its own task definition, scaling, and target group.
236
+ * All services share the cluster's ALB (unless disabled).
237
+ * Task role policies are configured per-service for least-privilege.
238
+ */
239
+ services: EcsServiceProps[];
71
240
  };
72
- export default class FargateCluster extends Construct implements IConnectable {
241
+ /**
242
+ * ECS Cluster supporting multiple services with a shared ALB.
243
+ *
244
+ * @example
245
+ * // Single service cluster
246
+ * new EcsCluster(scope, "WebCluster", {
247
+ * clusterName: "WebCluster",
248
+ * ecrRepository: ecr,
249
+ * services: [
250
+ * { name: "web", containers: [{ name: "app", port: 3000 }] }
251
+ * ]
252
+ * });
253
+ *
254
+ * @example
255
+ * // Multi-service cluster with routing
256
+ * new EcsCluster(scope, "ApiCluster", {
257
+ * clusterName: "ApiCluster",
258
+ * cluster: { domain: "api.example.com" },
259
+ * ecrRepository: ecr,
260
+ * services: [
261
+ * { name: "users", containers: [{ name: "app", port: 3000 }], routing: { path: "/users/*" } },
262
+ * { name: "orders", containers: [{ name: "app", port: 3001 }], routing: { path: "/orders/*" } }
263
+ * ]
264
+ * });
265
+ *
266
+ * @example
267
+ * // Worker cluster (no ALB)
268
+ * new EcsCluster(scope, "Workers", {
269
+ * clusterName: "Workers",
270
+ * cluster: { loadBalancer: false },
271
+ * ecrRepository: ecr,
272
+ * services: [
273
+ * { name: "processor", containers: [{ name: "worker" }] }
274
+ * ]
275
+ * });
276
+ */
277
+ export default class EcsCluster extends Construct implements IConnectable {
73
278
  connections: Connections;
74
279
  private cluster;
75
- private loadBalancer;
76
- private executionRole;
77
- private taskDefinition;
78
- private containerDefinition;
79
- private fargateService;
80
- private scalingPolicy;
81
- private hostedZone;
82
- private certificate;
83
- private aRecord;
84
- private loadBalancerListener;
85
- private secrets;
280
+ private loadBalancer?;
281
+ private loadBalancerListener?;
282
+ private hostedZone?;
283
+ private certificate?;
284
+ private aRecord?;
285
+ private autoScalingGroup?;
286
+ private asgSecurityGroup?;
287
+ private asgCapacityProvider?;
288
+ private loadBalancerSecurityGroup?;
289
+ private drainWaiter?;
290
+ private fargateCapacityProviderAssociations?;
291
+ private services;
86
292
  private scope;
87
- constructor(scope: Construct, id: string, props: FargateClusterProps);
88
- addCluster(props: FargateClusterProps): void;
89
- /**
90
- * #todo: change this to create new secrets instead
91
- * @deprecated use importSecrets instead
92
- */
93
- addSecrets(props: FargateClusterProps): void;
94
- /**
95
- * Automatically import secrets from another resource or stack
96
- */
97
- importSecrets(props: FargateClusterProps): void;
98
- addExecutionRole(props: FargateClusterProps): void;
99
- addTaskDefinition(props: FargateClusterProps): void;
100
- addContainerDefinition(props: FargateClusterProps): void;
101
- addFargateService(props: FargateClusterProps): void;
102
- addScalingPolicy(props: FargateClusterProps): void;
103
- registerLoadBalancerTargets(props: FargateClusterProps): void;
104
- addLoadBalancer(props: FargateClusterProps): void;
105
- addLoadBalancerListener(props: FargateClusterProps): void;
106
- addHostedZone(props: FargateClusterProps): void;
107
- getImage(props: FargateClusterProps): ContainerImage;
108
- static build(id: string, props: FargateClusterProps): (sb: StackBuilder) => Construct;
293
+ private props;
294
+ private capacityProvider;
295
+ private loadBalancerDisabled;
296
+ private directAccessEnabled;
297
+ private nextPriority;
298
+ constructor(scope: Construct, id: string, props: EcsClusterProps);
299
+ /** Get the cluster's load balancer. Undefined if disabled. */
300
+ getLoadBalancer(): ApplicationLoadBalancer | undefined;
301
+ /** Get the load balancer's listener. Undefined if disabled. */
302
+ getListener(): ApplicationListener | undefined;
303
+ /** Get a specific service by name. */
304
+ getService(name: string): FargateService | Ec2Service | undefined;
305
+ /** Get all services in this cluster. */
306
+ getServices(): Map<string, FargateService | Ec2Service>;
307
+ /** Get the ECS cluster construct. */
308
+ getCluster(): CdkCluster;
309
+ /** Get the ALB URL (http:// or https://). */
310
+ getUrl(): string | undefined;
311
+ /**
312
+ * Add a service to the cluster.
313
+ * Each service gets its own task definition, containers, and target group.
314
+ */
315
+ private addServiceToCluster;
316
+ private validateProps;
317
+ private setupConnections;
318
+ /**
319
+ * Creates the execution role for ECS infrastructure operations.
320
+ * Used by the ECS agent to pull images, write logs, and inject secrets.
321
+ * NOT used by application code - that's the task role.
322
+ */
323
+ private createExecutionRole;
324
+ /**
325
+ * Creates the task role for application code running in the container.
326
+ * This role is assumed by the application, not the ECS agent.
327
+ * Includes default ECS Exec permissions plus any service-specific policies.
328
+ */
329
+ private createTaskRole;
330
+ private createTaskDefinition;
331
+ private addContainersToTask;
332
+ private getContainerImage;
333
+ private createService;
334
+ private registerServiceWithALB;
335
+ private buildRoutingConditions;
336
+ private addServiceScaling;
337
+ private isEc2;
338
+ private isFargate;
339
+ addCluster(props: EcsClusterProps): void;
340
+ addAutoScalingGroup(props: EcsClusterProps): void;
341
+ addLoadBalancer(props: EcsClusterProps): void;
342
+ private addDirectAccessOutputs;
343
+ addLoadBalancerListener(props: EcsClusterProps): void;
344
+ addHostedZone(props: EcsClusterProps): void;
345
+ static build(id: string, props: EcsClusterProps): (sb: StackBuilder) => Construct;
109
346
  }