@fjall/components-infrastructure 0.94.1 → 0.96.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/app.d.ts +25 -109
- package/dist/lib/app.js +37 -136
- package/dist/lib/patterns/aws/account.js +5 -4
- package/dist/lib/patterns/aws/computeEcs.d.ts +8 -397
- package/dist/lib/patterns/aws/computeEcs.js +13 -9
- package/dist/lib/patterns/aws/computeEcsTypes.d.ts +386 -0
- package/dist/lib/patterns/aws/computeEcsTypes.js +2 -0
- package/dist/lib/patterns/aws/domain.js +4 -5
- package/dist/lib/patterns/aws/index.d.ts +2 -0
- package/dist/lib/patterns/aws/index.js +2 -0
- package/dist/lib/patterns/aws/interfaces/compute.d.ts +6 -0
- package/dist/lib/patterns/aws/interfaces/connector.d.ts +1 -1
- package/dist/lib/patterns/aws/interfaces/connector.js +1 -1
- package/dist/lib/patterns/aws/interfaces/index.d.ts +2 -1
- package/dist/lib/patterns/aws/interfaces/index.js +1 -1
- package/dist/lib/patterns/aws/interfaces/vpcPeer.d.ts +7 -0
- package/dist/lib/patterns/aws/interfaces/vpcPeer.js +1 -0
- package/dist/lib/patterns/aws/organisation.js +2 -1
- package/dist/lib/patterns/aws/vpcPeer.d.ts +34 -0
- package/dist/lib/patterns/aws/vpcPeer.js +36 -0
- package/dist/lib/patterns/aws/vpcPeerAccepter.d.ts +29 -0
- package/dist/lib/patterns/aws/vpcPeerAccepter.js +196 -0
- package/dist/lib/resources/aws/analytics/clickhouse.js +10 -1
- package/dist/lib/resources/aws/analytics/clickhouseAlarms.d.ts +34 -0
- package/dist/lib/resources/aws/analytics/clickhouseAlarms.js +89 -0
- package/dist/lib/resources/aws/analytics/clickhouseConstants.d.ts +1 -1
- package/dist/lib/resources/aws/analytics/clickhouseConstants.js +3 -1
- package/dist/lib/resources/aws/analytics/clickhouseTypes.d.ts +6 -0
- package/dist/lib/resources/aws/analytics/clickhouseUserData.d.ts +1 -0
- package/dist/lib/resources/aws/analytics/clickhouseUserData.js +3 -2
- package/dist/lib/resources/aws/analytics/index.d.ts +2 -0
- package/dist/lib/resources/aws/analytics/index.js +1 -0
- package/dist/lib/resources/aws/compute/ecsRemoteConnections.d.ts +38 -0
- package/dist/lib/resources/aws/compute/ecsRemoteConnections.js +80 -0
- package/dist/lib/resources/aws/compute/ecsTaskDefinition.js +8 -0
- package/dist/lib/resources/aws/compute/ecsTypes.d.ts +7 -0
- package/dist/lib/resources/aws/iam/delegationRole.js +11 -4
- package/dist/lib/resources/aws/networking/crossAccountDelegationRecord.js +2 -1
- package/dist/lib/resources/aws/networking/crossAccountReturnRoutes.d.ts +40 -0
- package/dist/lib/resources/aws/networking/crossAccountReturnRoutes.js +154 -0
- package/dist/lib/resources/aws/networking/dnsRecord/dnsRecordBase.js +2 -1
- package/dist/lib/resources/aws/networking/domainCertificate.js +2 -1
- package/dist/lib/resources/aws/networking/hostedZone.js +2 -1
- package/dist/lib/resources/aws/networking/index.d.ts +3 -0
- package/dist/lib/resources/aws/networking/index.js +3 -0
- package/dist/lib/resources/aws/networking/vpc.js +6 -2
- package/dist/lib/resources/aws/networking/vpcPeeringAccepterRole.d.ts +18 -0
- package/dist/lib/resources/aws/networking/vpcPeeringAccepterRole.js +61 -0
- package/dist/lib/resources/aws/networking/vpcPeeringConnection.d.ts +49 -0
- package/dist/lib/resources/aws/networking/vpcPeeringConnection.js +88 -0
- package/dist/lib/utils/bastionFactory.d.ts +10 -0
- package/dist/lib/utils/bastionFactory.js +29 -0
- package/dist/lib/utils/capitaliseString.d.ts +1 -1
- package/dist/lib/utils/capitaliseString.js +1 -1
- package/dist/lib/utils/cdkContext.d.ts +8 -0
- package/dist/lib/utils/cdkContext.js +11 -0
- package/dist/lib/utils/connections.d.ts +7 -1
- package/dist/lib/utils/connections.js +15 -0
- package/dist/lib/utils/connector.d.ts +18 -2
- package/dist/lib/utils/connector.js +6 -1
- package/dist/lib/utils/costAllocationTags.d.ts +6 -0
- package/dist/lib/utils/costAllocationTags.js +6 -0
- package/dist/lib/utils/index.d.ts +3 -0
- package/dist/lib/utils/index.js +3 -0
- package/dist/lib/utils/vpcPeerInterface.d.ts +22 -0
- package/dist/lib/utils/vpcPeerInterface.js +1 -0
- package/package.json +4 -3
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { type Repository } from "aws-cdk-lib/aws-ecr";
|
|
2
|
+
import { type RepositoryImage } from "aws-cdk-lib/aws-ecs";
|
|
3
|
+
import { type IVpc } from "aws-cdk-lib/aws-ec2";
|
|
4
|
+
import { type PolicyDocument, type IManagedPolicy } from "aws-cdk-lib/aws-iam";
|
|
5
|
+
import type { ITopic } from "aws-cdk-lib/aws-sns";
|
|
6
|
+
import { type ConnectionSpec } from "./interfaces/connector.js";
|
|
7
|
+
import { type RemoteConnectionSpec } from "../../resources/aws/compute/ecsRemoteConnections.js";
|
|
8
|
+
import { type EcsRoutingConfig } from "../../resources/aws/compute/ecsTypes.js";
|
|
9
|
+
import { ScalingType, type DomainConfig, type EcsCapacityProvider, type Ec2CapacityConfig } from "../../resources/aws/compute/ecs.js";
|
|
10
|
+
import type { EcsServiceAlarmThresholds } from "../../resources/aws/monitoring/index.js";
|
|
11
|
+
import { type SecretImport } from "../../resources/aws/secrets/index.js";
|
|
12
|
+
export type { RemoteConnectionSpec };
|
|
13
|
+
export { ScalingType };
|
|
14
|
+
export type { EcsCapacityProvider, Ec2CapacityConfig };
|
|
15
|
+
/**
|
|
16
|
+
* Configuration for ECS capacity providers.
|
|
17
|
+
*/
|
|
18
|
+
export interface EcsCapacityProviderConfig {
|
|
19
|
+
/** Whether this uses Spot pricing */
|
|
20
|
+
usesSpot: boolean;
|
|
21
|
+
/** Whether this runs on EC2 instances (vs serverless Fargate) */
|
|
22
|
+
usesEc2Instances: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Configuration for a container in an ECS task.
|
|
26
|
+
*
|
|
27
|
+
* For single-container services, `name` is optional and defaults to `${serviceName}Container`.
|
|
28
|
+
* For multi-container tasks, the first container with a `port` is the **primary container**
|
|
29
|
+
* that receives load balancer traffic.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // Single container (name auto-generated)
|
|
33
|
+
* containers: [{ port: 3000 }]
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* // Multi-container with sidecars
|
|
37
|
+
* containers: [
|
|
38
|
+
* { name: "app", port: 3000 }, // Primary - receives ALB traffic
|
|
39
|
+
* { name: "datadog", image: "datadog/agent" } // Sidecar - monitoring
|
|
40
|
+
* ]
|
|
41
|
+
*/
|
|
42
|
+
export interface EcsContainerConfig {
|
|
43
|
+
/** Container name. Optional for single-container services. */
|
|
44
|
+
name?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Container image. Options:
|
|
47
|
+
* - Omit: Uses app's default ECR repository (primary container only)
|
|
48
|
+
* - string: ECR repository name or public image URL
|
|
49
|
+
* - Repository: CDK ECR Repository construct
|
|
50
|
+
*/
|
|
51
|
+
image?: string | Repository;
|
|
52
|
+
/**
|
|
53
|
+
* Port the container listens on.
|
|
54
|
+
* The first container with a port becomes the **primary container**
|
|
55
|
+
* and is registered with the load balancer.
|
|
56
|
+
*/
|
|
57
|
+
port?: number;
|
|
58
|
+
/** Environment variables */
|
|
59
|
+
environment?: Record<string, string>;
|
|
60
|
+
/**
|
|
61
|
+
* Secrets from AWS SSM Parameter Store.
|
|
62
|
+
* Array of secret names that will be fetched from the service's SSM namespace.
|
|
63
|
+
* The namespace path is auto-determined from app/cluster/service names.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* // Secrets at /myapp/api-cluster/users/API_KEY and /myapp/api-cluster/users/DB_PASSWORD
|
|
67
|
+
* secrets: ["API_KEY", "DB_PASSWORD"]
|
|
68
|
+
*/
|
|
69
|
+
secrets?: string[];
|
|
70
|
+
/** Secrets imported from other CDK resources (AWS Secrets Manager) */
|
|
71
|
+
secretsImport?: Record<string, SecretImport>;
|
|
72
|
+
/** Command to run in the container */
|
|
73
|
+
command?: string[];
|
|
74
|
+
/** Entry point for the container */
|
|
75
|
+
entryPoint?: string[];
|
|
76
|
+
/**
|
|
77
|
+
* Whether this container is essential.
|
|
78
|
+
* If an essential container stops, all containers in the task stop.
|
|
79
|
+
* Default: true
|
|
80
|
+
*/
|
|
81
|
+
essential?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Health check configuration.
|
|
84
|
+
* Default: For primary container with port, uses curl health check.
|
|
85
|
+
*/
|
|
86
|
+
healthCheck?: {
|
|
87
|
+
command: string[];
|
|
88
|
+
interval?: number;
|
|
89
|
+
timeout?: number;
|
|
90
|
+
retries?: number;
|
|
91
|
+
startPeriod?: number;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* ECS scaling configuration.
|
|
96
|
+
* - Omit: enabled with defaults
|
|
97
|
+
* - `{}`: enabled with defaults
|
|
98
|
+
* - `{ minCapacity: 2, maxCapacity: 10 }`: custom scaling
|
|
99
|
+
* - `false`: explicitly disabled
|
|
100
|
+
*/
|
|
101
|
+
export interface EcsScalingConfig {
|
|
102
|
+
minCapacity?: number;
|
|
103
|
+
maxCapacity?: number;
|
|
104
|
+
scalingType?: ScalingType;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Cluster-level configuration.
|
|
108
|
+
* Controls the shared ALB for all services in this cluster.
|
|
109
|
+
*/
|
|
110
|
+
export interface EcsClusterConfig {
|
|
111
|
+
/**
|
|
112
|
+
* Domain for HTTPS access.
|
|
113
|
+
* - Omit: ALB created with default DNS (*.elb.amazonaws.com)
|
|
114
|
+
* - Specified: Creates ACM certificate + Route53 DNS A record
|
|
115
|
+
*/
|
|
116
|
+
domain?: string;
|
|
117
|
+
/**
|
|
118
|
+
* Load balancer configuration.
|
|
119
|
+
* - Omit or "public": Internet-facing ALB (default)
|
|
120
|
+
* - "internal": VPC-only ALB
|
|
121
|
+
* - false: No ALB (for workers/background processors)
|
|
122
|
+
*/
|
|
123
|
+
loadBalancer?: false | "public" | "internal";
|
|
124
|
+
/**
|
|
125
|
+
* Enable direct EC2 access without ALB.
|
|
126
|
+
* Uses host network mode for predictable ports.
|
|
127
|
+
* Access via EC2 public IP at container port.
|
|
128
|
+
*/
|
|
129
|
+
directAccess?: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Advanced domain configuration for routing policies (latency, weighted, geo).
|
|
132
|
+
* Only used when domain is specified.
|
|
133
|
+
* Allows for multi-region deployments with advanced DNS routing.
|
|
134
|
+
*/
|
|
135
|
+
domainConfig?: DomainConfig;
|
|
136
|
+
}
|
|
137
|
+
export type { EcsRoutingConfig };
|
|
138
|
+
/**
|
|
139
|
+
* Configuration for a service in an ECS cluster.
|
|
140
|
+
* Each service gets its own task definition, scaling config, and target group.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* // Simple service
|
|
144
|
+
* { name: "api", containers: [{ port: 3000 }] }
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* // Service with routing (for multi-service clusters)
|
|
148
|
+
* { name: "users", containers: [{ port: 3000 }], routing: { path: "/users/*", priority: 100 } }
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* // Service with multiple routing rules (same target group)
|
|
152
|
+
* { name: "web", containers: [{ port: 3000 }], routing: [
|
|
153
|
+
* { path: "/api/v2/*", priority: 50 },
|
|
154
|
+
* { path: "/*", priority: 200 },
|
|
155
|
+
* ]}
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* // Service with sidecars
|
|
159
|
+
* {
|
|
160
|
+
* name: "api",
|
|
161
|
+
* containers: [
|
|
162
|
+
* { name: "app", port: 3000 },
|
|
163
|
+
* { name: "datadog", image: "datadog/agent" }
|
|
164
|
+
* ]
|
|
165
|
+
* }
|
|
166
|
+
*/
|
|
167
|
+
export interface EcsServiceConfig {
|
|
168
|
+
/** Service name (unique within cluster) */
|
|
169
|
+
name: string;
|
|
170
|
+
/**
|
|
171
|
+
* Container image for this service (applies to first container without explicit image).
|
|
172
|
+
* - Omit: Uses app's default ECR repository
|
|
173
|
+
* - string: ECR repository name or public image URL
|
|
174
|
+
* - Repository: CDK ECR Repository construct
|
|
175
|
+
*/
|
|
176
|
+
image?: string | Repository;
|
|
177
|
+
/**
|
|
178
|
+
* Container configuration(s) for this service.
|
|
179
|
+
* For single-container services, container name is optional and auto-generated.
|
|
180
|
+
* For multi-container services, the first container with a port is the primary container.
|
|
181
|
+
*/
|
|
182
|
+
containers?: EcsContainerConfig[];
|
|
183
|
+
/**
|
|
184
|
+
* Routing rules for this service on the cluster's ALB.
|
|
185
|
+
* Required when cluster has multiple services with ports.
|
|
186
|
+
* Optional for single service (gets /* automatically).
|
|
187
|
+
* Can be a single rule or an array of rules pointing to the same target group.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* // Multiple routes for the same service
|
|
191
|
+
* routing: [
|
|
192
|
+
* { path: "/api/v2/*", priority: 50 },
|
|
193
|
+
* { path: "/*", priority: 200 },
|
|
194
|
+
* ]
|
|
195
|
+
*/
|
|
196
|
+
routing?: EcsRoutingConfig | EcsRoutingConfig[];
|
|
197
|
+
/** CPU units for this service's tasks (256-4096) */
|
|
198
|
+
cpu?: number;
|
|
199
|
+
/** Memory in MiB for this service's tasks (512-30720) */
|
|
200
|
+
memoryLimitMiB?: number;
|
|
201
|
+
/** Desired number of tasks. Default: 2 */
|
|
202
|
+
desiredCount?: number;
|
|
203
|
+
/**
|
|
204
|
+
* Scaling configuration.
|
|
205
|
+
* - Omit: enabled with defaults
|
|
206
|
+
* - false: disabled
|
|
207
|
+
*/
|
|
208
|
+
scaling?: EcsScalingConfig | false;
|
|
209
|
+
/**
|
|
210
|
+
* Path to Dockerfile for building this service's image.
|
|
211
|
+
* Metadata for CLI build process, not used during CDK synthesis.
|
|
212
|
+
*/
|
|
213
|
+
dockerfilePath?: string;
|
|
214
|
+
/**
|
|
215
|
+
* Docker build target stage for multi-stage Dockerfiles.
|
|
216
|
+
* When specified, the CLI builds with `--target <dockerTarget>`.
|
|
217
|
+
* The image tag suffix is also updated: `<service>-<target>-latest`.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* // Dockerfile: FROM node AS base ... FROM base AS api ... FROM base AS worker
|
|
221
|
+
* { name: "api", dockerTarget: "api" } // builds: myapp-api-api-latest
|
|
222
|
+
* { name: "worker", dockerTarget: "worker" } // builds: myapp-worker-worker-latest
|
|
223
|
+
*/
|
|
224
|
+
dockerTarget?: string;
|
|
225
|
+
/**
|
|
226
|
+
* Additional inline policies for this service's task role.
|
|
227
|
+
* Added on top of the default ECS Exec permissions.
|
|
228
|
+
* Use for service-specific AWS permissions (S3, DynamoDB, SQS, etc.).
|
|
229
|
+
*/
|
|
230
|
+
taskRoleInlinePolicies?: Record<string, PolicyDocument>;
|
|
231
|
+
/**
|
|
232
|
+
* Additional managed policies for this service's task role.
|
|
233
|
+
* Added on top of the default ECS Exec permissions.
|
|
234
|
+
*/
|
|
235
|
+
taskRoleManagedPolicies?: IManagedPolicy[];
|
|
236
|
+
/**
|
|
237
|
+
* Resources this service needs to connect to (e.g., databases, S3 buckets, SQS queues).
|
|
238
|
+
* Creates security group rules for IConnectable resources and IAM grants for IAM resources.
|
|
239
|
+
* Follows least-privilege - only this service gets access, not all services in the cluster.
|
|
240
|
+
*
|
|
241
|
+
* Supports:
|
|
242
|
+
* - IConnectable: Security group resources (RDS, ECS, etc.)
|
|
243
|
+
* - IStorageConnector: S3 buckets (IAM grants)
|
|
244
|
+
* - IDynamoDBConnector: DynamoDB tables (IAM grants)
|
|
245
|
+
* - IQueueConnector: SQS queues (IAM grants)
|
|
246
|
+
* - ConnectionConfig: Explicit access level configuration
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* // Simple connections (default permissions)
|
|
250
|
+
* connections: [database, bucket, cache, queue]
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* // Explicit access levels
|
|
254
|
+
* connections: [
|
|
255
|
+
* database, // Security group (RDS)
|
|
256
|
+
* { resource: cache, access: "read" }, // Read-only DynamoDB
|
|
257
|
+
* { resource: bucket, access: "write" }, // Write-only S3
|
|
258
|
+
* { resource: queue, access: "consume" } // Consume-only SQS
|
|
259
|
+
* ]
|
|
260
|
+
*/
|
|
261
|
+
connections?: ConnectionSpec[];
|
|
262
|
+
/**
|
|
263
|
+
* Cross-app resources reachable via VPC peering. Each entry resolves the
|
|
264
|
+
* peered app's exposed resource at synth time (SSM `valueForStringParameter`
|
|
265
|
+
* reads) and injects `${PREFIX}_HOST` + `${PREFIX}_PORT` env vars into every
|
|
266
|
+
* container in this service's task definition.
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* remoteConnections: [
|
|
270
|
+
* { peer, resource: "MainDatabase" },
|
|
271
|
+
* { peer, resource: "CoreApi", envPrefix: "DATA_PLATFORM_API" }
|
|
272
|
+
* ]
|
|
273
|
+
*/
|
|
274
|
+
remoteConnections?: RemoteConnectionSpec[];
|
|
275
|
+
/**
|
|
276
|
+
* Capacity provider for this service. REQUIRED.
|
|
277
|
+
* Each service specifies its own capacity provider.
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* // Mixed FARGATE and EC2 services in same cluster
|
|
281
|
+
* {
|
|
282
|
+
* services: [
|
|
283
|
+
* { name: "api", capacityProvider: "FARGATE" },
|
|
284
|
+
* { name: "worker", capacityProvider: "EC2", ec2Config: { instanceType: "t4g.micro" } }
|
|
285
|
+
* ]
|
|
286
|
+
* }
|
|
287
|
+
*/
|
|
288
|
+
capacityProvider: EcsCapacityProvider;
|
|
289
|
+
/**
|
|
290
|
+
* EC2 capacity configuration for this service.
|
|
291
|
+
* Only used when service capacityProvider is "EC2".
|
|
292
|
+
* Services with matching ec2Config share an ASG for efficiency.
|
|
293
|
+
*/
|
|
294
|
+
ec2Config?: Ec2CapacityConfig;
|
|
295
|
+
/**
|
|
296
|
+
* SSM Parameter Store path for secrets.
|
|
297
|
+
* If not specified, secrets are fetched from /<app>/<cluster>/<service>.
|
|
298
|
+
* Use this to override the default convention.
|
|
299
|
+
*
|
|
300
|
+
* @example
|
|
301
|
+
* // Override default path
|
|
302
|
+
* ssmSecretsPath: "/custom/path/to/secrets"
|
|
303
|
+
*/
|
|
304
|
+
ssmSecretsPath?: string;
|
|
305
|
+
/**
|
|
306
|
+
* Per-service alarm configuration.
|
|
307
|
+
* - undefined: use defaults (CPU, memory, running tasks, 5xx if ALB)
|
|
308
|
+
* - false: disable alarms for this service
|
|
309
|
+
* - object: override specific thresholds
|
|
310
|
+
*/
|
|
311
|
+
alarms?: EcsServiceAlarmThresholds | false;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* ECS compute configuration.
|
|
315
|
+
* Creates an ECS cluster with one or more services sharing a load balancer.
|
|
316
|
+
*
|
|
317
|
+
* @example
|
|
318
|
+
* // Single service
|
|
319
|
+
* app.addCompute(ComputeFactory.build("WebApp", {
|
|
320
|
+
* type: "ecs",
|
|
321
|
+
* cluster: { domain: "app.example.com" },
|
|
322
|
+
* services: [{ name: "web", containers: [{ port: 3000 }] }]
|
|
323
|
+
* }));
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* // Multi-service cluster with routing
|
|
327
|
+
* app.addCompute(ComputeFactory.build("ApiCluster", {
|
|
328
|
+
* type: "ecs",
|
|
329
|
+
* cluster: { domain: "api.example.com" },
|
|
330
|
+
* services: [
|
|
331
|
+
* { name: "users", containers: [{ port: 3000 }], routing: { path: "/users/*" } },
|
|
332
|
+
* { name: "orders", containers: [{ port: 3001 }], routing: { path: "/orders/*" } }
|
|
333
|
+
* ]
|
|
334
|
+
* }));
|
|
335
|
+
*
|
|
336
|
+
* @example
|
|
337
|
+
* // Internal workers (no ALB)
|
|
338
|
+
* app.addCompute(ComputeFactory.build("Workers", {
|
|
339
|
+
* type: "ecs",
|
|
340
|
+
* cluster: { loadBalancer: false },
|
|
341
|
+
* services: [{ name: "processor" }, { name: "emailer" }]
|
|
342
|
+
* }));
|
|
343
|
+
*/
|
|
344
|
+
export interface EcsComputeProps {
|
|
345
|
+
type: "ecs";
|
|
346
|
+
vpc?: IVpc;
|
|
347
|
+
/**
|
|
348
|
+
* Application name for SSM secrets namespace.
|
|
349
|
+
* When containers use secrets, the path is derived as: /<appName>/<clusterName>/<serviceName>
|
|
350
|
+
* Auto-derived from App.getName() if not specified.
|
|
351
|
+
*/
|
|
352
|
+
appName?: string;
|
|
353
|
+
/**
|
|
354
|
+
* Cluster configuration.
|
|
355
|
+
* Controls the shared ALB for all services in this cluster.
|
|
356
|
+
* - Omit: ALB created with default settings
|
|
357
|
+
* - `{ domain: "..." }`: ALB with HTTPS + DNS
|
|
358
|
+
* - `{ loadBalancer: false }`: No ALB (internal workers)
|
|
359
|
+
*/
|
|
360
|
+
cluster?: EcsClusterConfig;
|
|
361
|
+
/**
|
|
362
|
+
* Services in this cluster.
|
|
363
|
+
* Each service gets its own task definition, scaling, and target group.
|
|
364
|
+
* Each service MUST specify its own capacityProvider.
|
|
365
|
+
* All services share the cluster's ALB (unless disabled).
|
|
366
|
+
*/
|
|
367
|
+
services: EcsServiceConfig[];
|
|
368
|
+
/**
|
|
369
|
+
* ECR repository for all services (default image).
|
|
370
|
+
* Individual services can override with their own `image` property.
|
|
371
|
+
*/
|
|
372
|
+
ecrRepository?: Repository | RepositoryImage;
|
|
373
|
+
/**
|
|
374
|
+
* Path to Dockerfile for building custom image.
|
|
375
|
+
* Note: This is metadata for the CLI build process,
|
|
376
|
+
* not used during CDK synthesis.
|
|
377
|
+
*/
|
|
378
|
+
dockerfilePath?: string;
|
|
379
|
+
/**
|
|
380
|
+
* SNS topic for alarm notifications. Resolved to ITopic and passed to EcsCluster.
|
|
381
|
+
* Accepts either an ITopic directly or a topic ARN string (resolved internally).
|
|
382
|
+
*/
|
|
383
|
+
alertsTopic?: ITopic | string;
|
|
384
|
+
/** Application ID for alarm tagging (used by webhook to map alarms to applications). */
|
|
385
|
+
applicationId?: string;
|
|
386
|
+
}
|
|
@@ -6,6 +6,7 @@ import { validateDomainProps } from "./domainValidation.js";
|
|
|
6
6
|
import { composeApexDomain } from "./apexDomainPattern.js";
|
|
7
7
|
import { composeDelegatedDomain } from "./delegatedDomainPattern.js";
|
|
8
8
|
import { composeExternalRecords } from "./externalRecordsPattern.js";
|
|
9
|
+
import { DEFAULT_COST_ALLOCATION_ENVIRONMENT } from "../../utils/costAllocationTags.js";
|
|
9
10
|
/**
|
|
10
11
|
* User-facing Route53-oriented domain construct. Dispatches on
|
|
11
12
|
* `props.registrar` to one of three per-registrar patterns:
|
|
@@ -73,7 +74,7 @@ export class Domain extends Construct {
|
|
|
73
74
|
const effectiveZone = resolveEffectiveZoneName(props);
|
|
74
75
|
const description = props.description ?? `Fjall-managed domain for ${effectiveZone}`;
|
|
75
76
|
Tags.of(this).add("fjall:description", description);
|
|
76
|
-
Tags.of(this).add("fjall:costAllocation:environment", props.costAllocationEnvironment ??
|
|
77
|
+
Tags.of(this).add("fjall:costAllocation:environment", props.costAllocationEnvironment ?? DEFAULT_COST_ALLOCATION_ENVIRONMENT);
|
|
77
78
|
Tags.of(this).add("fjall:costAllocation:service", "domain");
|
|
78
79
|
Tags.of(this).add("fjall:costAllocation:domain", props.zoneName);
|
|
79
80
|
}
|
|
@@ -107,9 +108,7 @@ export class Domain extends Construct {
|
|
|
107
108
|
}
|
|
108
109
|
function resolveEffectiveZoneName(props) {
|
|
109
110
|
if (props.registrar === "external-delegated") {
|
|
110
|
-
|
|
111
|
-
return `${delegated.delegatedSubdomain}.${delegated.zoneName}`;
|
|
111
|
+
return `${props.delegatedSubdomain}.${props.zoneName}`;
|
|
112
112
|
}
|
|
113
|
-
|
|
114
|
-
return narrowed.zoneName;
|
|
113
|
+
return props.zoneName;
|
|
115
114
|
}
|
|
@@ -54,6 +54,12 @@ export interface IEcsCompute extends ICompute, IConnectable {
|
|
|
54
54
|
getAllServices(): IBaseService[];
|
|
55
55
|
/** Get the security group for the cluster. */
|
|
56
56
|
getSecurityGroup(): ISecurityGroup;
|
|
57
|
+
/**
|
|
58
|
+
* Returns the primary ALB listener port if one exists, else `undefined`.
|
|
59
|
+
* Use as a sensible default when consumers do not specify a port (e.g. 443
|
|
60
|
+
* for HTTPS, 80 for HTTP); does not indicate protocol.
|
|
61
|
+
*/
|
|
62
|
+
getPrimaryListenerPort(): number | undefined;
|
|
57
63
|
}
|
|
58
64
|
/**
|
|
59
65
|
* Lambda compute interface.
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* Connector types are shared between resources and patterns layers,
|
|
4
4
|
* so they belong in utils per the infrastructure layer boundary rules.
|
|
5
5
|
*/
|
|
6
|
-
export { type ConnectorType, type ConnectionAccess, type MessagingAccess, type IConnector, type IStorageConnector, type IDynamoDBConnector, type IQueueConnector, type ISecurityGroupConnector, type AnyConnector, type ConnectionConfig, type ConnectionSpec, CONNECTION_TYPE, type ConnectionType, type ConnectionResult, isConnectionAccess, isMessagingAccess, isConnector, isConnectable, isConnectionConfig, isStorageConnector, isDynamoDBConnector, isQueueConnector, isSecurityGroupConnector } from "../../../utils/connector.js";
|
|
6
|
+
export { type ConnectorType, type ConnectionAccess, type MessagingAccess, type IConnector, type IStorageConnector, type IDynamoDBConnector, type IQueueConnector, type ISecurityGroupConnector, type IRemoteConnector, type AnyConnector, type ConnectionConfig, type ConnectionSpec, CONNECTION_TYPE, type ConnectionType, type ConnectionResult, isConnectionAccess, isMessagingAccess, isConnector, isConnectable, isConnectionConfig, isStorageConnector, isDynamoDBConnector, isQueueConnector, isSecurityGroupConnector, isRemoteConnector } from "../../../utils/connector.js";
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* Connector types are shared between resources and patterns layers,
|
|
4
4
|
* so they belong in utils per the infrastructure layer boundary rules.
|
|
5
5
|
*/
|
|
6
|
-
export { CONNECTION_TYPE, isConnectionAccess, isMessagingAccess, isConnector, isConnectable, isConnectionConfig, isStorageConnector, isDynamoDBConnector, isQueueConnector, isSecurityGroupConnector } from "../../../utils/connector.js";
|
|
6
|
+
export { CONNECTION_TYPE, isConnectionAccess, isMessagingAccess, isConnector, isConnectable, isConnectionConfig, isStorageConnector, isDynamoDBConnector, isQueueConnector, isSecurityGroupConnector, isRemoteConnector } from "../../../utils/connector.js";
|
|
@@ -9,7 +9,8 @@ export { type DatabaseType, type RelationalDatabaseType, type IDatabase, type IR
|
|
|
9
9
|
export { type MessagingType, type IMessaging, type IQueueMessaging, type ITopicMessaging, type IEventBusMessaging, type AnyMessaging, isMessaging, isQueueMessaging, isTopicMessaging, isEventBusMessaging } from "./messaging.js";
|
|
10
10
|
export { type IStorage, isStorage } from "./storage.js";
|
|
11
11
|
export { type CdnType, type ICdn, type AnyCdn, isCdn } from "./cdn.js";
|
|
12
|
-
export { type ConnectorType, type ConnectionAccess, type MessagingAccess, type IConnector, type IStorageConnector, type IDynamoDBConnector, type IQueueConnector, type ISecurityGroupConnector, type AnyConnector, type ConnectionConfig, type ConnectionSpec, type ConnectionResult, isConnector, isConnectable, isConnectionConfig, isStorageConnector, isDynamoDBConnector, isQueueConnector, isSecurityGroupConnector } from "./connector.js";
|
|
12
|
+
export { type ConnectorType, type ConnectionAccess, type MessagingAccess, type ConnectionType, CONNECTION_TYPE, type IConnector, type IStorageConnector, type IDynamoDBConnector, type IQueueConnector, type ISecurityGroupConnector, type IRemoteConnector, type AnyConnector, type ConnectionConfig, type ConnectionSpec, type ConnectionResult, isConnector, isConnectable, isConnectionConfig, isConnectionAccess, isMessagingAccess, isStorageConnector, isDynamoDBConnector, isQueueConnector, isSecurityGroupConnector, isRemoteConnector } from "./connector.js";
|
|
13
13
|
export { type PatternType, type IPattern, type IPayload, type IPayloadProps, type IPatternProps, type AnyPattern, type PayloadDatabaseConfig, type PayloadComputeConfig, type PayloadCdnConfig, isPayloadPattern, isPattern } from "./pattern.js";
|
|
14
14
|
export { type OrganisationType, type IOrganisation, type IPlatform, type IAccount, type AnyOrganisation, isOrganisation, isPlatform, isAccount, isOrganisationResource } from "./organisation.js";
|
|
15
|
+
export { type IVpcPeer } from "./vpcPeer.js";
|
|
15
16
|
export { type DnsRecordInput, type DelegationInput, type CertificateInput, type DomainApexProps, type DomainDelegatedProps, type IDomainProps } from "./domain.js";
|
|
@@ -15,7 +15,7 @@ export { isStorage } from "./storage.js";
|
|
|
15
15
|
// CDN interfaces
|
|
16
16
|
export { isCdn } from "./cdn.js";
|
|
17
17
|
// Connector interfaces
|
|
18
|
-
export { isConnector, isConnectable, isConnectionConfig, isStorageConnector, isDynamoDBConnector, isQueueConnector, isSecurityGroupConnector } from "./connector.js";
|
|
18
|
+
export { CONNECTION_TYPE, isConnector, isConnectable, isConnectionConfig, isConnectionAccess, isMessagingAccess, isStorageConnector, isDynamoDBConnector, isQueueConnector, isSecurityGroupConnector, isRemoteConnector } from "./connector.js";
|
|
19
19
|
// Pattern interfaces
|
|
20
20
|
export { isPayloadPattern, isPattern } from "./pattern.js";
|
|
21
21
|
// Organisation interfaces
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-export from canonical location in lib/utils/.
|
|
3
|
+
* `IVpcPeer` is shared between `resources/` (SSM lookup helper) and
|
|
4
|
+
* `patterns/` (consumer-facing `RemoteConnectionSpec`), so it belongs in
|
|
5
|
+
* `utils/` per the infrastructure layer boundary rules.
|
|
6
|
+
*/
|
|
7
|
+
export { type IVpcPeer } from "../../../utils/vpcPeerInterface.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,6 +4,7 @@ import { IdentityCenter } from "../../config/aws/identityCenter.js";
|
|
|
4
4
|
import { ScpPreset } from "../../config/aws/scpPreset.js";
|
|
5
5
|
import { OrganisationResource, OrganisationAccount, CostAllocationTagActivator } from "../../resources/aws/organisation/index.js";
|
|
6
6
|
import { stripAndCamelCase } from "../../utils/stripAndCamelCase.js";
|
|
7
|
+
import { CDK_CONTEXT_KEYS } from "../../utils/cdkContext.js";
|
|
7
8
|
import { getConfig } from "../../utils/getConfig.js";
|
|
8
9
|
import { extractAccountNames } from "../../utils/accountsUtils.js";
|
|
9
10
|
/**
|
|
@@ -40,7 +41,7 @@ export class Organisation extends Stack {
|
|
|
40
41
|
this.accountMap[key.toLowerCase()] = value;
|
|
41
42
|
}
|
|
42
43
|
this.accountsConfig = props.accounts;
|
|
43
|
-
const orgId = this.node.tryGetContext(
|
|
44
|
+
const orgId = this.node.tryGetContext(CDK_CONTEXT_KEYS.ORG_ID);
|
|
44
45
|
const rootId = this.node.tryGetContext("rootId");
|
|
45
46
|
const managementAccountId = this.node.tryGetContext("managementAccountId") ?? this.account;
|
|
46
47
|
if (!orgId || !rootId) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type Construct } from "constructs";
|
|
2
|
+
import type App from "../../app.js";
|
|
3
|
+
import { VpcPeeringConnection } from "../../resources/aws/networking/vpcPeeringConnection.js";
|
|
4
|
+
export interface IVpcPeerProps {
|
|
5
|
+
/** Name of the remote Fjall app to peer with. */
|
|
6
|
+
peerAppName: string;
|
|
7
|
+
/** AWS account ID of the remote app. */
|
|
8
|
+
peerAccountId: string;
|
|
9
|
+
/** Region of the remote app's VPC. Defaults to the local region. */
|
|
10
|
+
peerRegion?: string;
|
|
11
|
+
/** Remote VPC ID. Resolved from SSM (`{prefix}/vpc-id`) if omitted. */
|
|
12
|
+
peerVpcId?: string;
|
|
13
|
+
/** Remote VPC CIDR. Resolved from SSM (`{prefix}/vpc-cidr`) if omitted. */
|
|
14
|
+
peerVpcCidr?: string;
|
|
15
|
+
/** Accepter role ARN. Resolved from SSM (`{prefix}/peering-role-arn`) if omitted. */
|
|
16
|
+
peerRoleArn?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Accepter route-table IDs. Resolved from the SSM `StringListParameter`
|
|
19
|
+
* (`{prefix}/route-table-ids`) via `valueForTypedListParameter` if omitted.
|
|
20
|
+
*/
|
|
21
|
+
peerRouteTableIds?: string[];
|
|
22
|
+
/** Name of the local VPC to peer from. Defaults to the app's default VPC. */
|
|
23
|
+
localVpcName?: string;
|
|
24
|
+
/** Enable DNS resolution across the peering. Defaults to true. */
|
|
25
|
+
enableDnsResolution?: boolean;
|
|
26
|
+
/** Cost-allocation override — forwarded to the underlying construct. */
|
|
27
|
+
costAllocationEnvironment?: string;
|
|
28
|
+
/** Cost-allocation override — forwarded to the underlying construct. */
|
|
29
|
+
costAllocationDomain?: string;
|
|
30
|
+
}
|
|
31
|
+
export type VpcPeer = VpcPeeringConnection;
|
|
32
|
+
export declare class VpcPeerFactory {
|
|
33
|
+
static build(id: string, props: IVpcPeerProps): (app: App, scope: Construct) => VpcPeer;
|
|
34
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { StringListParameter, StringParameter } from "aws-cdk-lib/aws-ssm";
|
|
2
|
+
import { buildSsmPrefix, DEFAULT_ORG_ID, resolveOrgId } from "../../utils/cdkContext.js";
|
|
3
|
+
import { VpcPeeringConnection } from "../../resources/aws/networking/vpcPeeringConnection.js";
|
|
4
|
+
export class VpcPeerFactory {
|
|
5
|
+
static build(id, props) {
|
|
6
|
+
return (app, scope) => {
|
|
7
|
+
const localVpc = app.getVpc(props.localVpcName);
|
|
8
|
+
const orgId = resolveOrgId(app.node, DEFAULT_ORG_ID);
|
|
9
|
+
const ssmPrefix = buildSsmPrefix(orgId, props.peerAppName);
|
|
10
|
+
const peerVpcId = props.peerVpcId ??
|
|
11
|
+
StringParameter.valueForStringParameter(scope, `${ssmPrefix}/vpc-id`);
|
|
12
|
+
const peerVpcCidr = props.peerVpcCidr ??
|
|
13
|
+
StringParameter.valueForStringParameter(scope, `${ssmPrefix}/vpc-cidr`);
|
|
14
|
+
const peerRoleArn = props.peerRoleArn ??
|
|
15
|
+
StringParameter.valueForStringParameter(scope, `${ssmPrefix}/peering-role-arn`);
|
|
16
|
+
const peerRouteTableIds = props.peerRouteTableIds ??
|
|
17
|
+
StringListParameter.valueForTypedListParameter(scope, `${ssmPrefix}/route-table-ids`);
|
|
18
|
+
const resolvedPeerOrgId = orgId !== DEFAULT_ORG_ID ? orgId : undefined;
|
|
19
|
+
return new VpcPeeringConnection(scope, id, {
|
|
20
|
+
localVpc,
|
|
21
|
+
localVpcCidr: localVpc.vpcCidrBlock,
|
|
22
|
+
peerVpcId,
|
|
23
|
+
peerVpcCidr,
|
|
24
|
+
peerAccountId: props.peerAccountId,
|
|
25
|
+
peerRegion: props.peerRegion,
|
|
26
|
+
peerRoleArn,
|
|
27
|
+
peerRouteTableIds,
|
|
28
|
+
enableDnsResolution: props.enableDnsResolution,
|
|
29
|
+
peerAppName: props.peerAppName,
|
|
30
|
+
peerOrgId: resolvedPeerOrgId,
|
|
31
|
+
costAllocationEnvironment: props.costAllocationEnvironment,
|
|
32
|
+
costAllocationDomain: props.costAllocationDomain
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type Construct } from "constructs";
|
|
2
|
+
import type App from "../../app.js";
|
|
3
|
+
import { VpcPeeringAccepterRole } from "../../resources/aws/networking/vpcPeeringAccepterRole.js";
|
|
4
|
+
import { type IRelationalDatabase } from "./interfaces/database.js";
|
|
5
|
+
import { type IEcsCompute } from "./interfaces/compute.js";
|
|
6
|
+
export type ExposedResource = {
|
|
7
|
+
resource: IRelationalDatabase;
|
|
8
|
+
name: string;
|
|
9
|
+
allowedFromCidrs: string[];
|
|
10
|
+
access?: "read" | "write" | "readWrite";
|
|
11
|
+
} | {
|
|
12
|
+
resource: IEcsCompute;
|
|
13
|
+
serviceName: string;
|
|
14
|
+
name: string;
|
|
15
|
+
allowedFromCidrs: string[];
|
|
16
|
+
port?: number;
|
|
17
|
+
};
|
|
18
|
+
export interface IVpcPeerAccepterProps {
|
|
19
|
+
requesterAccountIds: string[];
|
|
20
|
+
localVpcName?: string;
|
|
21
|
+
publishToSsm?: boolean;
|
|
22
|
+
exposedResources?: ExposedResource[];
|
|
23
|
+
costAllocationEnvironment?: string;
|
|
24
|
+
costAllocationDomain?: string;
|
|
25
|
+
}
|
|
26
|
+
export type VpcPeerAccepter = VpcPeeringAccepterRole;
|
|
27
|
+
export declare class VpcPeerAccepterFactory {
|
|
28
|
+
static build(id: string, props: IVpcPeerAccepterProps): (app: App, scope: Construct) => VpcPeerAccepter;
|
|
29
|
+
}
|