@fjall/components-infrastructure 39.0.5 → 39.0.6
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/patterns/aws/computeEcs.d.ts +65 -21
- package/dist/lib/patterns/aws/computeEcs.js +243 -95
- package/dist/lib/patterns/aws/computeEcsTypes.d.ts +49 -25
- package/dist/lib/resources/aws/compute/ecs.d.ts +3 -0
- package/dist/lib/resources/aws/compute/ecs.js +4 -0
- package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.d.ts +32 -62
- package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.js +96 -50
- package/dist/lib/resources/aws/compute/ecsRolloutBarrier.d.ts +61 -0
- package/dist/lib/resources/aws/compute/ecsRolloutBarrier.js +185 -0
- package/dist/lib/resources/aws/compute/ecsRolloutBarrierLambda.source.cjs +475 -0
- package/dist/lib/resources/aws/compute/ecsTaskDefinition.d.ts +19 -8
- package/dist/lib/resources/aws/compute/ecsTaskDefinition.js +16 -7
- package/dist/lib/resources/aws/compute/ecsValidation.d.ts +3 -3
- package/dist/lib/resources/aws/compute/ecsValidation.js +3 -3
- package/dist/lib/resources/aws/compute/lambda.d.ts +6 -0
- package/dist/lib/resources/aws/compute/lambda.js +18 -12
- package/dist/lib/resources/aws/compute/lifecycleHookLambda.source.cjs +329 -82
- package/package.json +5 -4
|
@@ -2,7 +2,7 @@ import { type ICluster, type IBaseService, type TaskDefinition, type FargateTask
|
|
|
2
2
|
import { type Connections, type ISecurityGroup } from "aws-cdk-lib/aws-ec2";
|
|
3
3
|
import { type Grant, type IGrantable, type IRole } from "aws-cdk-lib/aws-iam";
|
|
4
4
|
import { type IApplicationLoadBalancer, type ApplicationListener } from "aws-cdk-lib/aws-elasticloadbalancingv2";
|
|
5
|
-
import { Construct } from "constructs";
|
|
5
|
+
import { Construct, type IDependable } from "constructs";
|
|
6
6
|
import { type IEcsCompute } from "./interfaces/compute.js";
|
|
7
7
|
import { type SecretImport } from "../../resources/aws/secrets/index.js";
|
|
8
8
|
import EcsCluster, { type EcsClusterProps, type EcsIngressProfile } from "../../resources/aws/compute/ecs.js";
|
|
@@ -100,6 +100,10 @@ export declare class EcsCompute extends Construct implements IEcsCompute {
|
|
|
100
100
|
private readonly clusterId;
|
|
101
101
|
private readonly appName;
|
|
102
102
|
private readonly migrationTaskDefinitions;
|
|
103
|
+
/** The cluster's physical name, as a literal. */
|
|
104
|
+
private readonly clusterName;
|
|
105
|
+
/** Service name → its rollout barrier, made on first use. */
|
|
106
|
+
private readonly rolloutBarriers;
|
|
103
107
|
/**
|
|
104
108
|
* Service name → exact `@fjall/schema-gate` semver, for every service that
|
|
105
109
|
* materialised the gate container with the DEFAULT image this synth.
|
|
@@ -151,11 +155,6 @@ export declare class EcsCompute extends Construct implements IEcsCompute {
|
|
|
151
155
|
* - `migrations.mode: "post-deploy"` — expected is deliberately ahead of
|
|
152
156
|
* the DB during scale-up, so a materialised gate would refuse every task
|
|
153
157
|
* (synth warning)
|
|
154
|
-
* - `migrations.mode: "lifecycle-hook"` WITHOUT `separateTaskDef` — the
|
|
155
|
-
* hook's migration RunTask reuses the service task definition, so a
|
|
156
|
-
* materialised gate would refuse the migration task itself while the DB
|
|
157
|
-
* still holds the pre-migration schema (synth warning; adding
|
|
158
|
-
* `separateTaskDef` restores full gating)
|
|
159
158
|
* - No eligible half survives the v1 scope filters: the relational half
|
|
160
159
|
* requires `tool: "prisma"` and a postgres-family connection scheme
|
|
161
160
|
* (per-half synth warnings; env injection into app containers stays on)
|
|
@@ -195,30 +194,45 @@ export declare class EcsCompute extends Construct implements IEcsCompute {
|
|
|
195
194
|
* Without `awaitMigrationsFrom` the sibling rolls out in parallel with the
|
|
196
195
|
* owner, so its gate-refused task churn can trip the deployment circuit
|
|
197
196
|
* breaker before the migration lands. The gate refusing is by design (new
|
|
198
|
-
* code must not serve the old schema); the missing
|
|
199
|
-
* author-fixable part — warn, don't disable.
|
|
197
|
+
* code must not serve the old schema); the missing ordering on the owner's
|
|
198
|
+
* rollout barrier is the author-fixable part — warn, don't disable.
|
|
200
199
|
*/
|
|
201
200
|
private warnUngatedSiblingsOfHookOwners;
|
|
202
201
|
/**
|
|
203
202
|
* For each service whose `migrations.mode` is a lambda-hook variant
|
|
204
203
|
* (`"lifecycle-hook"` for PRE_SCALE_UP, `"post-deploy"` for POST_SCALE_UP),
|
|
205
|
-
* synthesise the
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
204
|
+
* synthesise the migration's own task definition and the Lambda + IAM role
|
|
205
|
+
* + log group that backs the deployment lifecycle hook. Every hook
|
|
206
|
+
* migration runs from a task definition of its own, which the service's
|
|
207
|
+
* task definition names in its `fjall:migration-task-definition` tag and
|
|
208
|
+
* its primary container's docker label: the hook reads the tag from the
|
|
209
|
+
* revision each deployment targets, and the label where a copy carries no
|
|
210
|
+
* tag. The
|
|
211
|
+
* init-container path is unaffected — services without `mode` (or with
|
|
212
|
+
* `mode: "init-container"`) still get the synthetic migrate container
|
|
213
|
+
* injected by `expandMigrationsSugar`.
|
|
209
214
|
*/
|
|
210
215
|
private wireLifecycleHookMigrations;
|
|
211
216
|
/**
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
217
|
+
* Orders each service that declares `awaitMigrationsFrom` after the named
|
|
218
|
+
* migrate-owning service's rollout, so a DB-connecting worker never starts
|
|
219
|
+
* before the owner's migrations have applied. Each owner gets one rollout
|
|
220
|
+
* barrier (`EcsRolloutBarrier`): a custom resource that completes only once
|
|
221
|
+
* ECS reports the owner's deployment of its task definition finished, its
|
|
222
|
+
* lifecycle-hook migration included, and fails once ECS rolled that
|
|
223
|
+
* deployment back. Every dependant's `DependsOn` names the barrier.
|
|
224
|
+
*
|
|
225
|
+
* A `DependsOn` on the owner service itself no longer orders this: since
|
|
226
|
+
* 2026-10-01 CloudFormation starts the dependants of an updating ECS
|
|
227
|
+
* service at its eventual-consistency check, 20-31 s into the update, while
|
|
228
|
+
* a custom resource's dependants wait for its response (FJL-901).
|
|
229
|
+
*
|
|
230
|
+
* Shape (target exists, declares hook migrations, no self / cycle) is
|
|
231
|
+
* already guaranteed by `validateEcsProps`.
|
|
220
232
|
*/
|
|
221
233
|
private wireServiceMigrationDependencies;
|
|
234
|
+
/** The service's one rollout barrier, made on first use. */
|
|
235
|
+
private rolloutBarrierOf;
|
|
222
236
|
/**
|
|
223
237
|
* Synthesise a dedicated migration task definition for a lifecycle-hook
|
|
224
238
|
* migration when `separateTaskDef` is set. Creates the migration's own
|
|
@@ -227,6 +241,19 @@ export declare class EcsCompute extends Construct implements IEcsCompute {
|
|
|
227
241
|
* with the migration container baked in.
|
|
228
242
|
*/
|
|
229
243
|
private synthesiseMigrationTaskDef;
|
|
244
|
+
/**
|
|
245
|
+
* The migration task definition of a lifecycle-hook migration without
|
|
246
|
+
* `separateTaskDef`. It runs what the hook's `RunTask` of the service's
|
|
247
|
+
* own task definition, its command and environment overridden, ran until
|
|
248
|
+
* FJL-901: as the service's own roles, at the service's size, in the
|
|
249
|
+
* service's log group, from the service's image, with the primary
|
|
250
|
+
* container's environment, entry point and secrets beneath the
|
|
251
|
+
* migration's own. A connected database's contributed secrets and role
|
|
252
|
+
* policies, such as its schema administrator's, reach only a
|
|
253
|
+
* `separateTaskDef` migration, whose roles are its own, so they never
|
|
254
|
+
* widen the service's.
|
|
255
|
+
*/
|
|
256
|
+
private synthesiseInheritedMigrationTaskDef;
|
|
230
257
|
private resolveMigrationSecrets;
|
|
231
258
|
/** Get the ECS cluster. */
|
|
232
259
|
getCluster(): ICluster;
|
|
@@ -249,9 +276,26 @@ export declare class EcsCompute extends Construct implements IEcsCompute {
|
|
|
249
276
|
* Get the migration task definition for a service. Returns `undefined` when
|
|
250
277
|
* the service has no `migrations: { mode: "lifecycle-hook", separateTaskDef }`
|
|
251
278
|
* configured — escape hatch for callers that need to attach grants (e.g.
|
|
252
|
-
* `bucket.grantReadWrite(td.taskRole)`) to the migration task role.
|
|
279
|
+
* `bucket.grantReadWrite(td.taskRole)`) to the migration task role. Without
|
|
280
|
+
* `separateTaskDef` the migration runs in a task definition of its own that
|
|
281
|
+
* this does not return: its task role is the service's, so a grant to it
|
|
282
|
+
* would widen the service.
|
|
253
283
|
*/
|
|
254
284
|
getMigrationTaskDefinition(serviceName: string): FargateTaskDefinition | undefined;
|
|
285
|
+
/**
|
|
286
|
+
* The rollout barrier of a service: a custom resource that completes only
|
|
287
|
+
* once ECS reports the service's deployment of its task definition
|
|
288
|
+
* finished, and fails once ECS rolled that deployment back. A construct
|
|
289
|
+
* that depends on it is created or updated only after the service has
|
|
290
|
+
* rolled out, for orderings `awaitMigrationsFrom` cannot express:
|
|
291
|
+
* `compute.getService("worker")?.node.addDependency(compute.getRolloutBarrier("app"))`.
|
|
292
|
+
* A `DependsOn` on the service itself does not order this: CloudFormation
|
|
293
|
+
* may start a service's dependants at its eventual-consistency check, long
|
|
294
|
+
* before its deployment finishes (FJL-901). A service has one barrier,
|
|
295
|
+
* shared with `awaitMigrationsFrom`; one the cluster does not run is
|
|
296
|
+
* refused.
|
|
297
|
+
*/
|
|
298
|
+
getRolloutBarrier(serviceName: string): IDependable;
|
|
255
299
|
/** Get the security group for the cluster. */
|
|
256
300
|
getSecurityGroup(): ISecurityGroup;
|
|
257
301
|
/**
|