@fjall/components-infrastructure 2.31.1 → 2.32.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 +27 -1
- package/dist/lib/app.js +35 -4
- package/dist/lib/patterns/aws/database.d.ts +19 -1
- package/dist/lib/patterns/aws/database.js +22 -3
- package/dist/lib/patterns/aws/devSubstrate.d.ts +85 -0
- package/dist/lib/patterns/aws/devSubstrate.js +390 -0
- package/dist/lib/patterns/aws/devSubstrate.waker.source.cjs +13 -0
- package/dist/lib/resources/aws/compute/applicationLoadBalancer.d.ts +17 -0
- package/dist/lib/resources/aws/compute/applicationLoadBalancer.js +23 -0
- package/dist/lib/resources/aws/compute/ecsNetworking.d.ts +4 -10
- package/dist/lib/resources/aws/compute/ecsNetworking.js +13 -48
- package/dist/lib/resources/aws/compute/ecsRoles.d.ts +25 -0
- package/dist/lib/resources/aws/compute/ecsRoles.js +39 -20
- package/dist/lib/resources/aws/compute/hostHeaderListenerRule.d.ts +23 -0
- package/dist/lib/resources/aws/compute/hostHeaderListenerRule.js +59 -0
- package/dist/lib/resources/aws/compute/lambdaAlbTarget.d.ts +17 -0
- package/dist/lib/resources/aws/compute/lambdaAlbTarget.js +18 -0
- package/dist/lib/resources/aws/compute/listenerRouting.d.ts +21 -0
- package/dist/lib/resources/aws/compute/listenerRouting.js +20 -0
- package/dist/lib/resources/aws/database/rdsAurora.d.ts +16 -0
- package/dist/lib/resources/aws/database/rdsAurora.js +57 -3
- package/dist/lib/resources/aws/database/rdsDefaults.d.ts +28 -0
- package/dist/lib/resources/aws/database/rdsDefaults.js +28 -0
- package/dist/lib/utils/devSubstrateTags.d.ts +22 -0
- package/dist/lib/utils/devSubstrateTags.js +22 -0
- package/package.json +5 -5
package/dist/lib/app.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { type RemovalPolicyString } from "./resources/aws/messaging/utils.js";
|
|
|
16
16
|
import { type ServiceRegistrationProps } from "./resources/aws/networking/serviceDiscovery.js";
|
|
17
17
|
import { type IPrivateDnsNamespace, type IService } from "aws-cdk-lib/aws-servicediscovery";
|
|
18
18
|
import { type AnyCompute } from "./patterns/aws/compute.js";
|
|
19
|
+
import { DevSubstrate, type IDevSubstrateProps } from "./patterns/aws/devSubstrate.js";
|
|
19
20
|
import { type Storage, type StorageFactoryFn } from "./patterns/aws/storage.js";
|
|
20
21
|
import { type AnyPattern, type PatternFactoryFn } from "./patterns/aws/pattern.js";
|
|
21
22
|
import { type BackupTier } from "./utils/backupTierMapping.js";
|
|
@@ -242,6 +243,23 @@ export declare class App extends CdkApp {
|
|
|
242
243
|
*/
|
|
243
244
|
addCompute<T extends AnyCompute & Construct>(fn: (app: App, scope: Construct) => T): T;
|
|
244
245
|
addComputeResource(resource: Construct): void;
|
|
246
|
+
/**
|
|
247
|
+
* Instantiate the internal `DevSubstrate` construct on the default compute
|
|
248
|
+
* stack (fast dev-envs Phase 3).
|
|
249
|
+
*
|
|
250
|
+
* Deliberately NOT routed through `PATTERN_TYPE_VALUES` / the pattern registry
|
|
251
|
+
* / `PatternFactory` / the `IPatternProps` union — the substrate is
|
|
252
|
+
* Fjall-managed dev infrastructure, never offered on the customer
|
|
253
|
+
* create/scaffold surface (design R5).
|
|
254
|
+
*
|
|
255
|
+
* Placement is load-bearing at DEPLOY time, not just synth: deploy-core selects
|
|
256
|
+
* stacks by a fixed six-category enum and derives deploy-order flags from
|
|
257
|
+
* post-synth stack-name suffixes (`endsWith("Compute")`), so scoping the
|
|
258
|
+
* substrate under `${stackPrefix}Compute` via `getDefaultComputeStack()` is
|
|
259
|
+
* what makes it actually deploy (design VF2). A dedicated `…DevSubstrate` stack
|
|
260
|
+
* would synth and hash but never deploy.
|
|
261
|
+
*/
|
|
262
|
+
addDevSubstrate(props: IDevSubstrateProps): DevSubstrate;
|
|
245
263
|
/**
|
|
246
264
|
* Add a database resource to the default database stack using the factory pattern.
|
|
247
265
|
* Returns the appropriate database type based on the factory used.
|
|
@@ -341,8 +359,16 @@ export declare class App extends CdkApp {
|
|
|
341
359
|
* visibilityTimeout: 300,
|
|
342
360
|
* contentBasedDeduplication: true
|
|
343
361
|
* }));
|
|
362
|
+
*
|
|
363
|
+
* Pass `stackPlacement: "compute"` to co-locate the queue in the compute stack
|
|
364
|
+
* (mirrors `addStorage`/`addSchedule`). Required when a bucket's notification
|
|
365
|
+
* targets the queue within one app: an S3 notification and its auto-generated
|
|
366
|
+
* SQS queue policy reference each other's ARN, so splitting the two across the
|
|
367
|
+
* Storage and Messaging stacks synthesises a fatal cross-stack dependency cycle.
|
|
344
368
|
*/
|
|
345
|
-
addMessaging<T extends AnyMessaging & Construct>(fn: (app: App, scope: Construct) => T
|
|
369
|
+
addMessaging<T extends AnyMessaging & Construct>(fn: (app: App, scope: Construct) => T, opts?: {
|
|
370
|
+
stackPlacement?: "messaging" | "compute";
|
|
371
|
+
}): T;
|
|
346
372
|
/**
|
|
347
373
|
* Register an EventBridge schedule against a Fjall wrapper target.
|
|
348
374
|
*
|
package/dist/lib/app.js
CHANGED
|
@@ -9,6 +9,7 @@ import { NetworkFactory } from "./patterns/aws/network.js";
|
|
|
9
9
|
import { MessagingFactory } from "./patterns/aws/messaging.js";
|
|
10
10
|
import { Schedule } from "./resources/aws/messaging/schedule.js";
|
|
11
11
|
import { ServiceDiscoveryNamespace } from "./resources/aws/networking/serviceDiscovery.js";
|
|
12
|
+
import { DevSubstrate } from "./patterns/aws/devSubstrate.js";
|
|
12
13
|
import { StandardTagsAspect } from "./utils/standardTagsAspect.js";
|
|
13
14
|
import { BACKUP_TIER_TAG_KEY, BACKUP_TIER_TAG_MAP } from "./utils/backupTierMapping.js";
|
|
14
15
|
import { randomBytes } from "crypto";
|
|
@@ -413,6 +414,28 @@ export class App extends CdkApp {
|
|
|
413
414
|
const computeStack = this.getDefaultComputeStack();
|
|
414
415
|
computeStack.addConstruct(resource);
|
|
415
416
|
}
|
|
417
|
+
/**
|
|
418
|
+
* Instantiate the internal `DevSubstrate` construct on the default compute
|
|
419
|
+
* stack (fast dev-envs Phase 3).
|
|
420
|
+
*
|
|
421
|
+
* Deliberately NOT routed through `PATTERN_TYPE_VALUES` / the pattern registry
|
|
422
|
+
* / `PatternFactory` / the `IPatternProps` union — the substrate is
|
|
423
|
+
* Fjall-managed dev infrastructure, never offered on the customer
|
|
424
|
+
* create/scaffold surface (design R5).
|
|
425
|
+
*
|
|
426
|
+
* Placement is load-bearing at DEPLOY time, not just synth: deploy-core selects
|
|
427
|
+
* stacks by a fixed six-category enum and derives deploy-order flags from
|
|
428
|
+
* post-synth stack-name suffixes (`endsWith("Compute")`), so scoping the
|
|
429
|
+
* substrate under `${stackPrefix}Compute` via `getDefaultComputeStack()` is
|
|
430
|
+
* what makes it actually deploy (design VF2). A dedicated `…DevSubstrate` stack
|
|
431
|
+
* would synth and hash but never deploy.
|
|
432
|
+
*/
|
|
433
|
+
addDevSubstrate(props) {
|
|
434
|
+
const computeStack = this.getDefaultComputeStack();
|
|
435
|
+
const substrate = new DevSubstrate(computeStack.getStack(), "DevSubstrate", this, props);
|
|
436
|
+
computeStack.addConstruct(substrate);
|
|
437
|
+
return substrate;
|
|
438
|
+
}
|
|
416
439
|
/**
|
|
417
440
|
* Add a database resource to the default database stack using the factory pattern.
|
|
418
441
|
* Returns the appropriate database type based on the factory used.
|
|
@@ -556,11 +579,19 @@ export class App extends CdkApp {
|
|
|
556
579
|
* visibilityTimeout: 300,
|
|
557
580
|
* contentBasedDeduplication: true
|
|
558
581
|
* }));
|
|
582
|
+
*
|
|
583
|
+
* Pass `stackPlacement: "compute"` to co-locate the queue in the compute stack
|
|
584
|
+
* (mirrors `addStorage`/`addSchedule`). Required when a bucket's notification
|
|
585
|
+
* targets the queue within one app: an S3 notification and its auto-generated
|
|
586
|
+
* SQS queue policy reference each other's ARN, so splitting the two across the
|
|
587
|
+
* Storage and Messaging stacks synthesises a fatal cross-stack dependency cycle.
|
|
559
588
|
*/
|
|
560
|
-
addMessaging(fn) {
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
|
|
589
|
+
addMessaging(fn, opts = {}) {
|
|
590
|
+
const stack = opts.stackPlacement === "compute"
|
|
591
|
+
? this.getDefaultComputeStack()
|
|
592
|
+
: this.getDefaultMessagingStack();
|
|
593
|
+
const messaging = fn(this, stack.getStack());
|
|
594
|
+
stack.addConstruct(messaging);
|
|
564
595
|
return messaging;
|
|
565
596
|
}
|
|
566
597
|
/**
|
|
@@ -28,7 +28,7 @@ export declare const DATABASE_ENGINE_CONFIG: Record<DatabaseEngine, {
|
|
|
28
28
|
defaultUsername: string;
|
|
29
29
|
sslParameters: Record<string, string>;
|
|
30
30
|
}>;
|
|
31
|
-
export declare function getAuroraClusterEngine(engine: DatabaseEngine): IClusterEngine;
|
|
31
|
+
export declare function getAuroraClusterEngine(engine: DatabaseEngine, engineVersion?: string): IClusterEngine;
|
|
32
32
|
export declare function getInstanceEngine(engine: DatabaseEngine): IInstanceEngine;
|
|
33
33
|
export declare function getEngineConfig(engine: DatabaseEngine): EngineConfig;
|
|
34
34
|
/**
|
|
@@ -59,6 +59,24 @@ export interface AuroraDatabaseProps extends BaseDatabaseProps {
|
|
|
59
59
|
databaseEngine?: DatabaseEngine;
|
|
60
60
|
/** Overrides databaseEngine if provided */
|
|
61
61
|
engine?: IClusterEngine;
|
|
62
|
+
/**
|
|
63
|
+
* Aurora PostgreSQL version to build the engine at, e.g. `"16.6"`. Overrides
|
|
64
|
+
* the `databaseEngine` default version; ignored when `engine` is supplied.
|
|
65
|
+
* Required `>= 16.3` when `serverlessV2MinCapacity` is 0 (auto-pause floor).
|
|
66
|
+
*/
|
|
67
|
+
engineVersion?: string;
|
|
68
|
+
/** Physical cluster identifier. Lower-cased; falls back to a derived name. */
|
|
69
|
+
clusterIdentifier?: string;
|
|
70
|
+
/** Physical name of the generated master-credentials secret. */
|
|
71
|
+
credentialsSecretName?: string;
|
|
72
|
+
/** Serverless-v2 floor in ACU. 0 enables scale-to-zero (auto-pause). */
|
|
73
|
+
serverlessV2MinCapacity?: number;
|
|
74
|
+
/** Serverless-v2 ceiling in ACU. */
|
|
75
|
+
serverlessV2MaxCapacity?: number;
|
|
76
|
+
/** Idle duration before an idle serverless-v2 cluster auto-pauses to 0 ACU. */
|
|
77
|
+
serverlessV2AutoPauseDuration?: Duration;
|
|
78
|
+
/** Enables the RDS Data API (HTTP endpoint) on the cluster. */
|
|
79
|
+
enableDataApi?: boolean;
|
|
62
80
|
writer?: AuroraWriterConfig;
|
|
63
81
|
readers?: AuroraReadersConfig | false;
|
|
64
82
|
proxy?: ProxyConfig | false;
|
|
@@ -57,8 +57,19 @@ const INSTANCE_ENGINE_FACTORIES = {
|
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
|
-
export function getAuroraClusterEngine(engine) {
|
|
61
|
-
|
|
60
|
+
export function getAuroraClusterEngine(engine, engineVersion) {
|
|
61
|
+
if (engineVersion === undefined) {
|
|
62
|
+
return AURORA_ENGINE_FACTORIES[engine]();
|
|
63
|
+
}
|
|
64
|
+
// The auto-pause version floor is enforced in RdsAurora, alongside the
|
|
65
|
+
// min-capacity knob that requires it — not here.
|
|
66
|
+
if (engine !== "postgresql") {
|
|
67
|
+
throw new Error(`engineVersion override is only supported for postgresql Aurora clusters (received "${engine}")`);
|
|
68
|
+
}
|
|
69
|
+
const majorVersion = engineVersion.split(".")[0] ?? "16";
|
|
70
|
+
return DatabaseClusterEngine.auroraPostgres({
|
|
71
|
+
version: AuroraPostgresEngineVersion.of(engineVersion, majorVersion)
|
|
72
|
+
});
|
|
62
73
|
}
|
|
63
74
|
export function getInstanceEngine(engine) {
|
|
64
75
|
return INSTANCE_ENGINE_FACTORIES[engine]();
|
|
@@ -346,7 +357,8 @@ export class RelationalDatabase extends Construct {
|
|
|
346
357
|
}
|
|
347
358
|
addAurora(props) {
|
|
348
359
|
const resolvedDatabaseEngine = props.databaseEngine ?? "postgresql";
|
|
349
|
-
const resolvedEngine = props.engine ??
|
|
360
|
+
const resolvedEngine = props.engine ??
|
|
361
|
+
getAuroraClusterEngine(resolvedDatabaseEngine, props.engineVersion);
|
|
350
362
|
const engineConfig = getEngineConfig(resolvedDatabaseEngine);
|
|
351
363
|
if (props.publiclyAccessible) {
|
|
352
364
|
FjallLogger.warn(`Aurora database '${props.databaseName}' is configured with public accessibility. ` +
|
|
@@ -356,7 +368,14 @@ export class RelationalDatabase extends Construct {
|
|
|
356
368
|
vpc: props.vpc,
|
|
357
369
|
databaseName: props.databaseName,
|
|
358
370
|
engine: resolvedEngine,
|
|
371
|
+
engineVersion: props.engineVersion,
|
|
359
372
|
engineConfig,
|
|
373
|
+
clusterIdentifier: props.clusterIdentifier,
|
|
374
|
+
credentialsSecretName: props.credentialsSecretName,
|
|
375
|
+
serverlessV2MinCapacity: props.serverlessV2MinCapacity,
|
|
376
|
+
serverlessV2MaxCapacity: props.serverlessV2MaxCapacity,
|
|
377
|
+
serverlessV2AutoPauseDuration: props.serverlessV2AutoPauseDuration,
|
|
378
|
+
enableDataApi: props.enableDataApi,
|
|
360
379
|
writer: props.writer,
|
|
361
380
|
readers: props.readers,
|
|
362
381
|
proxy: props.proxy,
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Construct } from "constructs";
|
|
2
|
+
import type App from "../../app.js";
|
|
3
|
+
/**
|
|
4
|
+
* Props for the internal `DevSubstrate` construct.
|
|
5
|
+
*
|
|
6
|
+
* Deliberately standalone — NOT a member of the `IPatternProps` union and NOT
|
|
7
|
+
* registered in `PATTERN_TYPE_VALUES` / the pattern registry / `PatternFactory`.
|
|
8
|
+
* The substrate is Fjall-managed dev infrastructure, never offered on the
|
|
9
|
+
* customer create/scaffold surface (design R5). Increments A2–A7 extend this
|
|
10
|
+
* interface (S3→SQS, compute/network, domain, delegation, `phase`) as each lands.
|
|
11
|
+
*/
|
|
12
|
+
export interface IDevSubstrateProps {
|
|
13
|
+
/**
|
|
14
|
+
* Real customer application identifier, surfaced as the `fjall:app` reaper
|
|
15
|
+
* tag. Distinct from the `fjall-dev-<app>` App identity that drives the
|
|
16
|
+
* substrate's stack names.
|
|
17
|
+
*/
|
|
18
|
+
readonly appId: string;
|
|
19
|
+
/**
|
|
20
|
+
* Kebab-cased customer app name used to pin the substrate's physical resource
|
|
21
|
+
* names inside the `fjall-dev-*` fence (cluster identifier, master secret) so
|
|
22
|
+
* the dev-tier IAM grants match. Single-sourced with the `fjall-dev-<app>` App
|
|
23
|
+
* identity (design VERDICT-3).
|
|
24
|
+
*/
|
|
25
|
+
readonly appKebab: string;
|
|
26
|
+
/**
|
|
27
|
+
* Aurora PostgreSQL engine version override (default `DEV_AURORA_DEFAULTS`).
|
|
28
|
+
* Must be `>= 16.3` — the shared cluster runs `serverlessV2MinCapacity` 0,
|
|
29
|
+
* which needs an auto-pause-capable engine (RdsAurora rejects lower at synth).
|
|
30
|
+
*/
|
|
31
|
+
readonly engineVersion?: string;
|
|
32
|
+
/**
|
|
33
|
+
* When `true`, adopt an already-existing slot image ECR repository
|
|
34
|
+
* (`fjall-dev-<appKebab>-slots`) by reference instead of creating one — an
|
|
35
|
+
* import only, emitting no CloudFormation resource (and therefore untaggable).
|
|
36
|
+
* Defaults to `false`: create and fence-tag the repo. Set on a redeploy into an
|
|
37
|
+
* account where the repo was provisioned out-of-band.
|
|
38
|
+
*/
|
|
39
|
+
readonly adoptSlotEcr?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Deploy phase for the R2 two-step cert-hang guard. `"zone"` synthesises the
|
|
42
|
+
* `dev.<appDomain>` child zone + cross-account NS delegation only; `"full"`
|
|
43
|
+
* additionally builds the wildcard cert + :443 listener (A6) — deploy that
|
|
44
|
+
* only after the delegated NS has propagated, else ACM DNS-validation hangs.
|
|
45
|
+
* Defaults to `"full"`. Inert unless `domain` is set.
|
|
46
|
+
*/
|
|
47
|
+
readonly phase?: "zone" | "full";
|
|
48
|
+
/**
|
|
49
|
+
* Public domain the substrate hangs a `dev.<appDomain>` child zone under. When
|
|
50
|
+
* omitted, the substrate stands up no zone/cert (early milestone — G2 reaches
|
|
51
|
+
* slots via `curl --resolve`).
|
|
52
|
+
*
|
|
53
|
+
* `parentDelegationRoleArn`, when present, wires the same-org **Case-1** in-stack
|
|
54
|
+
* NS delegation (design VD2-a): the child stack's `CrossAccountZoneDelegationRecord`
|
|
55
|
+
* assumes the parent account's `DelegationRole` by LITERAL ARN and UPSERTs the
|
|
56
|
+
* child NS into the parent zone. Omit it for a plain externally-owned parent
|
|
57
|
+
* (Case 3 — manual one-off delegation) or a connected different-org parent
|
|
58
|
+
* (Case 2 — worker UPSERT, B3b, deferred): the substrate then emits only the
|
|
59
|
+
* zone + its NS export for out-of-band delegation.
|
|
60
|
+
*/
|
|
61
|
+
readonly domain?: {
|
|
62
|
+
readonly appDomain: string;
|
|
63
|
+
readonly parentDelegationRoleArn?: string;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Shared per-app substrate for ephemeral dev/preview slots (fast dev-envs
|
|
68
|
+
* Phase 3). Stands up the long-lived infrastructure a customer dev team's slots
|
|
69
|
+
* share — Aurora (A1), an S3→SQS drop (A2), an ECS cluster + slot SG (A2.5), an
|
|
70
|
+
* ALB with host-header routing (A3) fronted by a Lambda waker (A4), a delegated
|
|
71
|
+
* child zone (A5) and a wildcard cert (A6) — fenced to the development account.
|
|
72
|
+
*
|
|
73
|
+
* Instantiated ONLY via the internal `App.addDevSubstrate(props)`, which scopes
|
|
74
|
+
* it under the default compute stack so it actually deploys (design VF2). Every
|
|
75
|
+
* resource it creates carries `fjall:dev = "true"` (the IAM fence tag) and
|
|
76
|
+
* `fjall:app = <appId>` (the reaper tag) — including resources created through
|
|
77
|
+
* the app factories in sibling stacks, which are tagged explicitly since the
|
|
78
|
+
* `Tags.of(this)` aspect only reaches this construct's own scope subtree.
|
|
79
|
+
*/
|
|
80
|
+
export declare class DevSubstrate extends Construct {
|
|
81
|
+
#private;
|
|
82
|
+
private readonly app;
|
|
83
|
+
private readonly appId;
|
|
84
|
+
constructor(scope: Construct, id: string, app: App, props: IDevSubstrateProps);
|
|
85
|
+
}
|