@aws-blocks/core 0.2.0 → 0.4.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/README.md +13 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +32 -0
- package/dist/api.test.js +22 -0
- package/dist/bb-utils.d.ts +1 -0
- package/dist/bb-utils.d.ts.map +1 -1
- package/dist/bb-utils.js +3 -0
- package/dist/cdk/apigateway-account.d.ts +33 -0
- package/dist/cdk/apigateway-account.d.ts.map +1 -0
- package/dist/cdk/apigateway-account.js +60 -0
- package/dist/cdk/blocks-backend.d.ts +43 -9
- package/dist/cdk/blocks-backend.d.ts.map +1 -1
- package/dist/cdk/blocks-backend.js +69 -73
- package/dist/cdk/blocks-backend.test.js +78 -69
- package/dist/cdk/blocks-defaults.d.ts +92 -2
- package/dist/cdk/blocks-defaults.d.ts.map +1 -1
- package/dist/cdk/blocks-defaults.js +22 -2
- package/dist/cdk/blocks-defaults.test.js +21 -2
- package/dist/cdk/blocks-stack.test.js +94 -37
- package/dist/cdk/compute/compute-registry.d.ts +19 -0
- package/dist/cdk/compute/compute-registry.d.ts.map +1 -0
- package/dist/cdk/compute/compute-registry.js +38 -0
- package/dist/cdk/compute/compute.d.ts +2 -0
- package/dist/cdk/compute/compute.d.ts.map +1 -1
- package/dist/cdk/compute/compute.js +8 -0
- package/dist/cdk/compute/default-compute-factory.d.ts +34 -0
- package/dist/cdk/compute/default-compute-factory.d.ts.map +1 -0
- package/dist/cdk/compute/default-compute-factory.js +3 -0
- package/dist/cdk/config-registry.d.ts +34 -4
- package/dist/cdk/config-registry.d.ts.map +1 -1
- package/dist/cdk/config-registry.js +83 -25
- package/dist/cdk/config-registry.test.d.ts +2 -0
- package/dist/cdk/config-registry.test.d.ts.map +1 -0
- package/dist/cdk/config-registry.test.js +115 -0
- package/dist/cdk/index.d.ts +76 -7
- package/dist/cdk/index.d.ts.map +1 -1
- package/dist/cdk/index.js +99 -9
- package/dist/cdk/internal.d.ts +1 -0
- package/dist/cdk/internal.d.ts.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/common/config.d.ts +34 -0
- package/dist/common/config.d.ts.map +1 -1
- package/dist/common/config.js +45 -3
- package/dist/common/config.test.js +19 -0
- package/dist/common/index.d.ts +8 -0
- package/dist/common/index.d.ts.map +1 -1
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +20 -0
- package/dist/hosting-secrets.d.ts +48 -0
- package/dist/hosting-secrets.d.ts.map +1 -0
- package/dist/hosting-secrets.js +57 -0
- package/dist/hosting-secrets.test.d.ts +2 -0
- package/dist/hosting-secrets.test.d.ts.map +1 -0
- package/dist/hosting-secrets.test.js +81 -0
- package/dist/hosting.d.ts +97 -6
- package/dist/hosting.d.ts.map +1 -1
- package/dist/hosting.js +91 -23
- package/dist/hosting.test.js +182 -10
- package/dist/index.cdk.d.ts +13 -12
- package/dist/index.cdk.d.ts.map +1 -1
- package/dist/index.cdk.js +13 -9
- package/dist/index.d.ts +8 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -5
- package/dist/lambda-handler.d.ts +17 -0
- package/dist/lambda-handler.d.ts.map +1 -1
- package/dist/lambda-handler.js +52 -3
- package/dist/lambda-handler.test.js +196 -1
- package/dist/pipeline/index.d.ts +24 -2
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +41 -1
- package/dist/pipeline.test.d.ts +2 -0
- package/dist/pipeline.test.d.ts.map +1 -0
- package/dist/pipeline.test.js +47 -0
- package/dist/rpc.d.ts +21 -0
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +34 -0
- package/dist/rpc.test.js +38 -1
- package/dist/scripts/config.d.ts +15 -0
- package/dist/scripts/config.d.ts.map +1 -0
- package/dist/scripts/config.js +29 -0
- package/dist/scripts/deploy.d.ts.map +1 -1
- package/dist/scripts/deploy.js +4 -0
- package/dist/scripts/dev-server.d.ts +8 -0
- package/dist/scripts/dev-server.d.ts.map +1 -1
- package/dist/scripts/dev-server.js +31 -0
- package/dist/scripts/generate-client.d.ts.map +1 -1
- package/dist/scripts/generate-client.js +9 -4
- package/dist/scripts/generate-client.test.js +19 -4
- package/dist/scripts/index.d.ts +13 -10
- package/dist/scripts/index.d.ts.map +1 -1
- package/dist/scripts/index.js +11 -8
- package/dist/scripts/preflight-credentials.d.ts +30 -0
- package/dist/scripts/preflight-credentials.d.ts.map +1 -0
- package/dist/scripts/preflight-credentials.js +108 -0
- package/dist/scripts/preflight-credentials.test.d.ts +2 -0
- package/dist/scripts/preflight-credentials.test.d.ts.map +1 -0
- package/dist/scripts/preflight-credentials.test.js +77 -0
- package/dist/scripts/sandbox-args.test.d.ts +2 -0
- package/dist/scripts/sandbox-args.test.d.ts.map +1 -0
- package/dist/scripts/sandbox-args.test.js +77 -0
- package/dist/scripts/sandbox-empty-buckets.test.d.ts +2 -0
- package/dist/scripts/sandbox-empty-buckets.test.d.ts.map +1 -0
- package/dist/scripts/sandbox-empty-buckets.test.js +171 -0
- package/dist/scripts/sandbox.d.ts +106 -0
- package/dist/scripts/sandbox.d.ts.map +1 -1
- package/dist/scripts/sandbox.js +255 -40
- package/dist/scripts/secret.d.ts +15 -0
- package/dist/scripts/secret.d.ts.map +1 -0
- package/dist/scripts/secret.js +29 -0
- package/dist/scripts/secret.test.d.ts +2 -0
- package/dist/scripts/secret.test.d.ts.map +1 -0
- package/dist/scripts/secret.test.js +28 -0
- package/dist/scripts/typegen.d.ts +15 -0
- package/dist/scripts/typegen.d.ts.map +1 -0
- package/dist/scripts/typegen.js +16 -0
- package/dist/secret-naming.d.ts +58 -0
- package/dist/secret-naming.d.ts.map +1 -0
- package/dist/secret-naming.js +67 -0
- package/dist/secret-naming.test.d.ts +2 -0
- package/dist/secret-naming.test.d.ts.map +1 -0
- package/dist/secret-naming.test.js +40 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -1
- package/src/api.test.ts +25 -0
- package/src/api.ts +39 -0
- package/src/bb-utils.ts +3 -0
- package/src/cdk/apigateway-account.ts +66 -0
- package/src/cdk/blocks-backend.test.ts +291 -272
- package/src/cdk/blocks-backend.ts +88 -83
- package/src/cdk/blocks-defaults.test.ts +25 -2
- package/src/cdk/blocks-defaults.ts +94 -2
- package/src/cdk/blocks-stack.test.ts +186 -118
- package/src/cdk/compute/compute-registry.ts +45 -0
- package/src/cdk/compute/compute.ts +10 -0
- package/src/cdk/compute/default-compute-factory.ts +38 -0
- package/src/cdk/config-registry.test.ts +135 -0
- package/src/cdk/config-registry.ts +92 -34
- package/src/cdk/index.ts +129 -10
- package/src/cdk/internal.ts +1 -0
- package/src/client/index.ts +1 -1
- package/src/common/config.test.ts +21 -0
- package/src/common/config.ts +47 -3
- package/src/common/index.ts +8 -0
- package/src/errors.ts +21 -0
- package/src/hosting-secrets.test.ts +106 -0
- package/src/hosting-secrets.ts +106 -0
- package/src/hosting.test.ts +272 -63
- package/src/hosting.ts +200 -68
- package/src/index.cdk.ts +80 -38
- package/src/index.ts +35 -16
- package/src/lambda-handler.test.ts +215 -1
- package/src/lambda-handler.ts +54 -2
- package/src/pipeline/index.ts +64 -11
- package/src/pipeline.test.ts +55 -0
- package/src/rpc.test.ts +44 -1
- package/src/rpc.ts +41 -0
- package/src/scripts/config.ts +35 -0
- package/src/scripts/deploy.ts +5 -0
- package/src/scripts/dev-server.ts +40 -0
- package/src/scripts/generate-client.test.ts +43 -8
- package/src/scripts/generate-client.ts +70 -65
- package/src/scripts/index.ts +20 -17
- package/src/scripts/preflight-credentials.test.ts +110 -0
- package/src/scripts/preflight-credentials.ts +131 -0
- package/src/scripts/sandbox-args.test.ts +92 -0
- package/src/scripts/sandbox-empty-buckets.test.ts +191 -0
- package/src/scripts/sandbox.ts +287 -39
- package/src/scripts/secret.test.ts +35 -0
- package/src/scripts/secret.ts +35 -0
- package/src/scripts/typegen.ts +18 -0
- package/src/secret-naming.test.ts +59 -0
- package/src/secret-naming.ts +99 -0
- package/src/version.ts +1 -1
|
@@ -1,12 +1,55 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { test, describe, before } from 'node:test';
|
|
4
3
|
import assert from 'node:assert';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
4
|
import { dirname, join } from 'node:path';
|
|
5
|
+
import { before, describe, test } from 'node:test';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
7
|
import * as cdk from 'aws-cdk-lib';
|
|
8
|
+
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
|
|
9
|
+
import * as lambda from 'aws-cdk-lib/aws-lambda-nodejs';
|
|
10
|
+
import { BLOCKS_RPC_PREFIX } from '../constants.js';
|
|
8
11
|
import { BlocksBackend } from './blocks-backend.js';
|
|
12
|
+
import { Compute } from './compute/compute.js';
|
|
13
|
+
import { getComputes } from './compute/compute-registry.js';
|
|
9
14
|
import { BlocksStack, BlocksPresets, Scope } from './index.js';
|
|
15
|
+
// A real app gets its default compute from @aws-blocks/bb-lambda-compute (via
|
|
16
|
+
// @aws-blocks/blocks), which core's own tests can't depend on. Use an
|
|
17
|
+
// equivalent inline stub: a Compute that owns a NodejsFunction + API Gateway,
|
|
18
|
+
// so create() can build the default and the handler/gateway/apiUrl accessors
|
|
19
|
+
// and synth-shape assertions have something real to resolve to. It is passed to
|
|
20
|
+
// each create() via the internal `defaultComputeFactory` option (see makeStack /
|
|
21
|
+
// makeBackend), exactly as @aws-blocks/blocks injects LambdaCompute.
|
|
22
|
+
class StubLambdaCompute extends Compute {
|
|
23
|
+
fn;
|
|
24
|
+
apiGateway;
|
|
25
|
+
apiUrl;
|
|
26
|
+
logGroup;
|
|
27
|
+
constructor(scope, id) {
|
|
28
|
+
super(id, { parent: scope });
|
|
29
|
+
this.logGroup = new cdk.aws_logs.LogGroup(this, 'HandlerLogGroup', {
|
|
30
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
31
|
+
});
|
|
32
|
+
this.fn = new lambda.NodejsFunction(this, 'Handler', {
|
|
33
|
+
entry: this.backendHandlerPath,
|
|
34
|
+
runtime: cdk.aws_lambda.Runtime.NODEJS_22_X,
|
|
35
|
+
handler: 'handler',
|
|
36
|
+
role: this.executionRole,
|
|
37
|
+
logGroup: this.logGroup,
|
|
38
|
+
environment: { BLOCKS_STACK_NAME: this.backendStackName },
|
|
39
|
+
bundling: { minify: true, esbuildArgs: { '--conditions': 'aws-runtime' } },
|
|
40
|
+
});
|
|
41
|
+
this.apiGateway = new apigateway.RestApi(this, 'API', { restApiName: 'Blocks API' });
|
|
42
|
+
this.apiGateway.root.addProxy({
|
|
43
|
+
defaultIntegration: new apigateway.LambdaIntegration(this.fn),
|
|
44
|
+
anyMethod: true,
|
|
45
|
+
});
|
|
46
|
+
this.apiUrl = `${this.apiGateway.url}${BLOCKS_RPC_PREFIX.slice(1)}`;
|
|
47
|
+
}
|
|
48
|
+
setEnv(key, value) {
|
|
49
|
+
this.fn.addEnvironment(key, value);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const stubComputeFactory = (root) => new StubLambdaCompute(root, 'DefaultCompute');
|
|
10
53
|
// Simulate the CDK condition being active (tests import CDK files directly)
|
|
11
54
|
before(() => {
|
|
12
55
|
process.env.NODE_OPTIONS = (process.env.NODE_OPTIONS ?? '') + ' --conditions=cdk';
|
|
@@ -15,19 +58,15 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
15
58
|
const handlerPath = join(__dirname, '__fixtures__', 'handler.js');
|
|
16
59
|
const sideEffectBackendPath = join(__dirname, '__fixtures__', 'side-effect-backend.js');
|
|
17
60
|
const factoryBackendPath = join(__dirname, '__fixtures__', 'factory-backend.js');
|
|
61
|
+
// Wrap create(), injecting the stub default-compute factory the way
|
|
62
|
+
// @aws-blocks/blocks injects LambdaCompute — so tests don't repeat it.
|
|
63
|
+
const makeStack = (scope, id, backendCDKPath) => BlocksStack.create(scope, id, { backendHandlerPath: handlerPath, backendCDKPath, defaults: BlocksPresets.production, defaultComputeFactory: stubComputeFactory });
|
|
64
|
+
const makeBackend = (scope, id, backendCDKPath) => BlocksBackend.create(scope, id, { backendHandlerPath: handlerPath, backendCDKPath, defaults: BlocksPresets.production, defaultComputeFactory: stubComputeFactory });
|
|
18
65
|
describe('ESM cache-busting (multi-stage)', () => {
|
|
19
66
|
test('BlocksStack.create() with same backendCDKPath but different IDs produces constructs in each', async () => {
|
|
20
67
|
const app = new cdk.App();
|
|
21
|
-
const stack1 = await
|
|
22
|
-
|
|
23
|
-
backendCDKPath: sideEffectBackendPath,
|
|
24
|
-
defaults: BlocksPresets.production,
|
|
25
|
-
});
|
|
26
|
-
const stack2 = await BlocksStack.create(app, 'PipelineStage2', {
|
|
27
|
-
backendHandlerPath: handlerPath,
|
|
28
|
-
backendCDKPath: sideEffectBackendPath,
|
|
29
|
-
defaults: BlocksPresets.production,
|
|
30
|
-
});
|
|
68
|
+
const stack1 = await makeStack(app, 'PipelineStage1', sideEffectBackendPath);
|
|
69
|
+
const stack2 = await makeStack(app, 'PipelineStage2', sideEffectBackendPath);
|
|
31
70
|
const findMarker = (scope) => scope.node.tryFindChild('SideEffectMarker');
|
|
32
71
|
assert.ok(findMarker(stack1), 'First stack should have SideEffectMarker from module side effect');
|
|
33
72
|
assert.ok(findMarker(stack2), 'Second stack should have SideEffectMarker from re-executed module (cache busted)');
|
|
@@ -36,11 +75,7 @@ describe('ESM cache-busting (multi-stage)', () => {
|
|
|
36
75
|
describe('factory function support', () => {
|
|
37
76
|
test('BlocksStack.create() calls default export function with the stack instance', async () => {
|
|
38
77
|
const app = new cdk.App();
|
|
39
|
-
const stack = await
|
|
40
|
-
backendHandlerPath: handlerPath,
|
|
41
|
-
backendCDKPath: factoryBackendPath,
|
|
42
|
-
defaults: BlocksPresets.production,
|
|
43
|
-
});
|
|
78
|
+
const stack = await makeStack(app, 'FactoryBlocksStack', factoryBackendPath);
|
|
44
79
|
const marker = stack.node.tryFindChild('FactoryMarker');
|
|
45
80
|
assert.ok(marker, 'Factory function should have created FactoryMarker on the stack');
|
|
46
81
|
});
|
|
@@ -49,11 +84,7 @@ describe('legacy side-effect mode (no default export)', () => {
|
|
|
49
84
|
test('module with only side effects still registers constructs via globalThis', async () => {
|
|
50
85
|
const app = new cdk.App();
|
|
51
86
|
const stack = new cdk.Stack(app, 'LegacyTestStack');
|
|
52
|
-
const backend = await
|
|
53
|
-
backendHandlerPath: handlerPath,
|
|
54
|
-
backendCDKPath: sideEffectBackendPath,
|
|
55
|
-
defaults: BlocksPresets.production,
|
|
56
|
-
});
|
|
87
|
+
const backend = await makeBackend(stack, 'LegacyStage', sideEffectBackendPath);
|
|
57
88
|
const marker = backend.node.tryFindChild('SideEffectMarker');
|
|
58
89
|
assert.ok(marker, 'Side-effect-only module should register construct via globalThis.CURRENT_BLOCKS_STACK');
|
|
59
90
|
});
|
|
@@ -65,22 +96,14 @@ describe('shared execution role (BlocksStack)', () => {
|
|
|
65
96
|
// executionRole — a separate code path from BlocksBackend's constructor.
|
|
66
97
|
test('BlocksStack wires executionRole via its constructor', async () => {
|
|
67
98
|
const app = new cdk.App();
|
|
68
|
-
const stack = await
|
|
69
|
-
backendHandlerPath: handlerPath,
|
|
70
|
-
backendCDKPath: sideEffectBackendPath,
|
|
71
|
-
defaults: BlocksPresets.production,
|
|
72
|
-
});
|
|
99
|
+
const stack = await makeStack(app, 'StackRoleStack', sideEffectBackendPath);
|
|
73
100
|
assert.ok(stack.executionRole, 'BlocksStack should expose a populated .executionRole');
|
|
74
101
|
});
|
|
75
102
|
});
|
|
76
103
|
describe('executionRole globalThis fallback', () => {
|
|
77
104
|
test('resolves via globalThis.CURRENT_BLOCKS_STACK when no owner is in the tree', async () => {
|
|
78
105
|
const app = new cdk.App();
|
|
79
|
-
const stack = await
|
|
80
|
-
backendHandlerPath: handlerPath,
|
|
81
|
-
backendCDKPath: sideEffectBackendPath,
|
|
82
|
-
defaults: BlocksPresets.production,
|
|
83
|
-
});
|
|
106
|
+
const stack = await makeStack(app, 'FallbackStack', sideEffectBackendPath);
|
|
84
107
|
// A Scope whose construct-tree ancestry has no BlocksStack/BlocksBackend
|
|
85
108
|
// (parented under a plain cdk.Stack) exhausts the tree-walk and falls back
|
|
86
109
|
// to globalThis.CURRENT_BLOCKS_STACK. The `as any` is test plumbing — a
|
|
@@ -91,6 +114,44 @@ describe('executionRole globalThis fallback', () => {
|
|
|
91
114
|
assert.strictEqual(orphan.executionRole, stack.executionRole, 'fallback resolves to the ambient stack role');
|
|
92
115
|
});
|
|
93
116
|
});
|
|
117
|
+
describe('root is bound to the owning stack (multi-stack synth)', () => {
|
|
118
|
+
test('a block under each of two stacks resolves its OWN stack, not the last globalThis', async () => {
|
|
119
|
+
// `root` is resolved once at Scope construction (not re-walked per getter),
|
|
120
|
+
// and `create()` mutates globalThis.CURRENT_BLOCKS_STACK for each stack it
|
|
121
|
+
// builds. With two stacks in one synth, a block constructed under the first
|
|
122
|
+
// must stay bound to the first even after the second stack is created and
|
|
123
|
+
// overwrites globalThis — otherwise its root-derived accessors (handler,
|
|
124
|
+
// executionRole, backendStackName) would silently point at the wrong stack.
|
|
125
|
+
const app = new cdk.App();
|
|
126
|
+
const stackA = await makeStack(app, 'RootBindingA', sideEffectBackendPath);
|
|
127
|
+
// A block explicitly parented under stackA (construct-tree walk resolves
|
|
128
|
+
// stackA regardless of the ambient globalThis).
|
|
129
|
+
const blockA = new Scope('blockA', { parent: stackA });
|
|
130
|
+
// Building the second stack overwrites globalThis.CURRENT_BLOCKS_STACK.
|
|
131
|
+
const stackB = await makeStack(app, 'RootBindingB', sideEffectBackendPath);
|
|
132
|
+
const blockB = new Scope('blockB', { parent: stackB });
|
|
133
|
+
assert.strictEqual(blockA.executionRole, stackA.executionRole, 'blockA stays bound to stackA');
|
|
134
|
+
assert.strictEqual(blockB.executionRole, stackB.executionRole, 'blockB binds to stackB');
|
|
135
|
+
assert.notStrictEqual(stackA.executionRole, stackB.executionRole, 'the two stacks have distinct roles');
|
|
136
|
+
assert.strictEqual(blockA.backendStackName, 'RootBindingA', 'blockA derives its own stack name');
|
|
137
|
+
assert.strictEqual(blockB.backendStackName, 'RootBindingB', 'blockB derives its own stack name');
|
|
138
|
+
});
|
|
139
|
+
test('each stack owns an isolated compute registry (no cross-stack bleed)', async () => {
|
|
140
|
+
// Computes self-register on their owning stack (keyed per stack, not a
|
|
141
|
+
// process-global list), so a multi-stack synth keeps each stack's computes
|
|
142
|
+
// separate — finalize steps for one stack never see another's compute.
|
|
143
|
+
const app = new cdk.App();
|
|
144
|
+
const stackA = await makeStack(app, 'ComputeRegistryA', sideEffectBackendPath);
|
|
145
|
+
const stackB = await makeStack(app, 'ComputeRegistryB', sideEffectBackendPath);
|
|
146
|
+
const computesA = getComputes(stackA);
|
|
147
|
+
const computesB = getComputes(stackB);
|
|
148
|
+
assert.strictEqual(computesA.length, 1, 'stackA registered exactly its default compute');
|
|
149
|
+
assert.strictEqual(computesB.length, 1, 'stackB registered exactly its default compute');
|
|
150
|
+
assert.strictEqual(computesA[0], stackA._defaultCompute, 'stackA lists its own default');
|
|
151
|
+
assert.strictEqual(computesB[0], stackB._defaultCompute, 'stackB lists its own default');
|
|
152
|
+
assert.notStrictEqual(computesA[0], computesB[0], 'the two stacks hold distinct computes');
|
|
153
|
+
});
|
|
154
|
+
});
|
|
94
155
|
describe('assertCdkConditionActive', () => {
|
|
95
156
|
test('BlocksStack.create() throws when --conditions=cdk is missing', async () => {
|
|
96
157
|
const origNodeOptions = process.env.NODE_OPTIONS;
|
|
@@ -99,11 +160,7 @@ describe('assertCdkConditionActive', () => {
|
|
|
99
160
|
process.execArgv = [];
|
|
100
161
|
try {
|
|
101
162
|
const app = new cdk.App();
|
|
102
|
-
await assert.rejects(
|
|
103
|
-
backendHandlerPath: handlerPath,
|
|
104
|
-
backendCDKPath: sideEffectBackendPath,
|
|
105
|
-
defaults: BlocksPresets.production,
|
|
106
|
-
}), (err) => {
|
|
163
|
+
await assert.rejects(makeStack(app, 'MissingConditionStack', sideEffectBackendPath), (err) => {
|
|
107
164
|
assert.ok(err.message.includes('Missing --conditions=cdk'), `Expected condition error, got: ${err.message}`);
|
|
108
165
|
return true;
|
|
109
166
|
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Construct } from 'constructs';
|
|
2
|
+
import type { Compute } from './compute.js';
|
|
3
|
+
/**
|
|
4
|
+
* Register a compute on its owning stack. Called from the {@link Compute} base
|
|
5
|
+
* constructor, so every compute self-registers the moment it is constructed —
|
|
6
|
+
* the finalize steps then enumerate them without a separate discovery pass
|
|
7
|
+
* (mirrors how `registerConfig` accumulates config during the backend import).
|
|
8
|
+
*
|
|
9
|
+
* @param compute - The compute to register (used to locate its stack).
|
|
10
|
+
*/
|
|
11
|
+
export declare function registerCompute(compute: Compute): void;
|
|
12
|
+
/**
|
|
13
|
+
* The computes registered on the stack that owns `scope`, in construction
|
|
14
|
+
* order. Returns an empty array before any compute is constructed.
|
|
15
|
+
*
|
|
16
|
+
* @param scope - Any construct in the stack (used to locate the stack).
|
|
17
|
+
*/
|
|
18
|
+
export declare function getComputes(scope: Construct): readonly Compute[];
|
|
19
|
+
//# sourceMappingURL=compute-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute-registry.d.ts","sourceRoot":"","sources":["../../../src/cdk/compute/compute-registry.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAmB5C;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,OAAO,EAAE,CAEhE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import * as cdk from 'aws-cdk-lib';
|
|
4
|
+
const REGISTRY_KEY = Symbol.for('BLOCKS_COMPUTE_REGISTRY');
|
|
5
|
+
/**
|
|
6
|
+
* Get or create the compute list for a given stack. The list is stored on the
|
|
7
|
+
* stack object (keyed by a Symbol), so each stack in a multi-stack synth gets
|
|
8
|
+
* its own — a compute never leaks into another stack's list. Mirrors the config
|
|
9
|
+
* registry (`config-registry.ts`), which scopes its state the same way.
|
|
10
|
+
*/
|
|
11
|
+
function getRegistry(stack) {
|
|
12
|
+
let list = stack[REGISTRY_KEY];
|
|
13
|
+
if (!list) {
|
|
14
|
+
list = [];
|
|
15
|
+
stack[REGISTRY_KEY] = list;
|
|
16
|
+
}
|
|
17
|
+
return list;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Register a compute on its owning stack. Called from the {@link Compute} base
|
|
21
|
+
* constructor, so every compute self-registers the moment it is constructed —
|
|
22
|
+
* the finalize steps then enumerate them without a separate discovery pass
|
|
23
|
+
* (mirrors how `registerConfig` accumulates config during the backend import).
|
|
24
|
+
*
|
|
25
|
+
* @param compute - The compute to register (used to locate its stack).
|
|
26
|
+
*/
|
|
27
|
+
export function registerCompute(compute) {
|
|
28
|
+
getRegistry(cdk.Stack.of(compute)).push(compute);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The computes registered on the stack that owns `scope`, in construction
|
|
32
|
+
* order. Returns an empty array before any compute is constructed.
|
|
33
|
+
*
|
|
34
|
+
* @param scope - Any construct in the stack (used to locate the stack).
|
|
35
|
+
*/
|
|
36
|
+
export function getComputes(scope) {
|
|
37
|
+
return getRegistry(cdk.Stack.of(scope));
|
|
38
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ScopeOptions } from '../../common/index.js';
|
|
1
2
|
import { Scope } from '../index.js';
|
|
2
3
|
/**
|
|
3
4
|
* Base class for a Blocks *compute* — a runtime that executes handler code
|
|
@@ -23,6 +24,7 @@ export declare abstract class Compute extends Scope {
|
|
|
23
24
|
* unpopulated (no compute assignment surface yet).
|
|
24
25
|
*/
|
|
25
26
|
readonly namespaces: string[];
|
|
27
|
+
constructor(id: string, options?: ScopeOptions);
|
|
26
28
|
/**
|
|
27
29
|
* Inject a runtime configuration value (an environment variable) into this
|
|
28
30
|
* compute. The framework calls this instead of `handler.addEnvironment()`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compute.d.ts","sourceRoot":"","sources":["../../../src/cdk/compute/compute.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"compute.d.ts","sourceRoot":"","sources":["../../../src/cdk/compute/compute.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC;;;;;;;;;;;;;;;;GAgBG;AACH,8BAAsB,OAAQ,SAAQ,KAAK;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAM;gBAEvB,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;IAQ9C;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;CACjD"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { Scope } from '../index.js';
|
|
4
|
+
import { registerCompute } from './compute-registry.js';
|
|
4
5
|
/**
|
|
5
6
|
* Base class for a Blocks *compute* — a runtime that executes handler code
|
|
6
7
|
* (Lambda today; containers later). A compute owns the physical function/service
|
|
@@ -25,4 +26,11 @@ export class Compute extends Scope {
|
|
|
25
26
|
* unpopulated (no compute assignment surface yet).
|
|
26
27
|
*/
|
|
27
28
|
namespaces = [];
|
|
29
|
+
constructor(id, options) {
|
|
30
|
+
super(id, options);
|
|
31
|
+
// Self-register on the owning stack so finalize steps (config, routing,
|
|
32
|
+
// dashboards) can enumerate every compute without a separate discovery
|
|
33
|
+
// pass. Scoped per stack, so a multi-stack synth keeps lists isolated.
|
|
34
|
+
registerCompute(this);
|
|
35
|
+
}
|
|
28
36
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type * as cdk from 'aws-cdk-lib';
|
|
2
|
+
import type { Compute } from './compute.js';
|
|
3
|
+
import type { BlocksStack } from '../index.js';
|
|
4
|
+
import type { BlocksBackend } from '../blocks-backend.js';
|
|
5
|
+
/**
|
|
6
|
+
* Lambda-shaped surface of the default compute that the legacy
|
|
7
|
+
* `handler` / `gateway` / `apiUrl` accessors on BlocksStack/BlocksBackend read.
|
|
8
|
+
* The default compute (`LambdaCompute` from `@aws-blocks/bb-lambda-compute`)
|
|
9
|
+
* satisfies this structurally, so core exposes those accessors without
|
|
10
|
+
* importing the concrete class. To be removed with those accessors once
|
|
11
|
+
* consumers move to the multi-compute model.
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export interface LambdaShapedCompute extends Compute {
|
|
16
|
+
readonly fn: cdk.aws_lambda_nodejs.NodejsFunction;
|
|
17
|
+
readonly apiGateway: cdk.aws_apigateway.RestApi;
|
|
18
|
+
readonly apiUrl: string;
|
|
19
|
+
readonly logGroup: cdk.aws_logs.ILogGroup;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Builds the default {@link Compute} for a stack/backend. `create()` reads it
|
|
23
|
+
* from its props (`CoreBlocksStackProps.defaultComputeFactory`) and calls it to
|
|
24
|
+
* build the default without importing a concrete compute class — the factory is
|
|
25
|
+
* supplied by whoever owns both core and a concrete compute package (the
|
|
26
|
+
* umbrella `@aws-blocks/blocks`, which injects `LambdaCompute`). It lives on
|
|
27
|
+
* `CoreBlocksStackProps`/`CoreBlocksBackendProps`, which the umbrella derives
|
|
28
|
+
* from the customer-facing props, so it is absent from `BlocksStackProps` and
|
|
29
|
+
* customers cannot set it.
|
|
30
|
+
*
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
export type DefaultComputeFactory = (root: BlocksStack | BlocksBackend) => Compute;
|
|
34
|
+
//# sourceMappingURL=default-compute-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-compute-factory.d.ts","sourceRoot":"","sources":["../../../src/cdk/compute/default-compute-factory.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,GAAG,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAoB,SAAQ,OAAO;IACnD,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,iBAAiB,CAAC,cAAc,CAAC;IAClD,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;CAC1C;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,WAAW,GAAG,aAAa,KAAK,OAAO,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as cdk from 'aws-cdk-lib';
|
|
2
2
|
import type { Construct } from 'constructs';
|
|
3
|
+
import type { Compute } from './compute/compute.js';
|
|
3
4
|
/**
|
|
4
5
|
* Register a config entry for a Building Block. This replaces
|
|
5
6
|
* `handler.addEnvironment(key, value)` for BB resource mappings.
|
|
@@ -12,15 +13,44 @@ import type { Construct } from 'constructs';
|
|
|
12
13
|
* @param value - The config value (can be a CDK token that resolves at deploy time)
|
|
13
14
|
*/
|
|
14
15
|
export declare function registerConfig(scope: Construct, key: string, value: unknown): void;
|
|
16
|
+
/**
|
|
17
|
+
* Ensure the shared config bucket exists and return where the config JSON lives
|
|
18
|
+
* (`{ bucketName, key }`). The bucket is created **once per stack** (memoized on
|
|
19
|
+
* the registry) and this is idempotent — the first caller creates it, later
|
|
20
|
+
* callers get the same bucket regardless of order.
|
|
21
|
+
*
|
|
22
|
+
* Any compute that loads config at runtime (`loadConfigToProcessEnv()`) injects
|
|
23
|
+
* these two values as `BLOCKS_CONFIG_BUCKET` / `BLOCKS_CONFIG_KEY`. The Lambda
|
|
24
|
+
* handler gets them from {@link finalizeConfigRegistry}; other compute that runs
|
|
25
|
+
* as the shared execution role (e.g. the Agent BB's AgentCore Runtime) calls this
|
|
26
|
+
* at construction to inject them too, so it loads the same app config the handler
|
|
27
|
+
* does. IAM is not granted here — `finalizeConfigRegistry` grants read on the config
|
|
28
|
+
* object to the shared execution role, which such compute inherits.
|
|
29
|
+
*
|
|
30
|
+
* @param scope - Any construct in the stack; the bucket is created under the stack.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getConfigLocation(scope: Construct): {
|
|
33
|
+
bucketName: string;
|
|
34
|
+
key: string;
|
|
35
|
+
};
|
|
15
36
|
/**
|
|
16
37
|
* Finalize the config registry: create an S3 bucket, upload the config JSON,
|
|
17
|
-
*
|
|
38
|
+
* grant read to the shared execution role, and stamp the config coordinates
|
|
39
|
+
* (`BLOCKS_CONFIG_BUCKET` / `BLOCKS_CONFIG_KEY`) onto every compute.
|
|
40
|
+
*
|
|
41
|
+
* Read access is granted once to the shared role (`root.executionRole`) rather
|
|
42
|
+
* than to a single function, so every compute that assumes the role can read
|
|
43
|
+
* the object. The bucket/key coordinates can't live on a role (env vars are
|
|
44
|
+
* per-compute), so they are set on each compute via `setEnv`.
|
|
18
45
|
*
|
|
19
46
|
* Must be called after all BBs are constructed (i.e., after the backendCDKPath
|
|
20
47
|
* import completes in BlocksStack.create() / BlocksBackend.create()).
|
|
21
48
|
*
|
|
22
|
-
* @param
|
|
23
|
-
*
|
|
49
|
+
* @param root - The construct to create the config resources under (also used
|
|
50
|
+
* to locate the owning stack).
|
|
51
|
+
* @param executionRole - The shared role every compute assumes; config read is
|
|
52
|
+
* granted to it once.
|
|
53
|
+
* @param computes - The computes to stamp `BLOCKS_CONFIG_BUCKET` / `BLOCKS_CONFIG_KEY` on.
|
|
24
54
|
*/
|
|
25
|
-
export declare function finalizeConfigRegistry(
|
|
55
|
+
export declare function finalizeConfigRegistry(root: Construct, executionRole: cdk.aws_iam.IRole, computes: readonly Compute[]): void;
|
|
26
56
|
//# sourceMappingURL=config-registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-registry.d.ts","sourceRoot":"","sources":["../../src/cdk/config-registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"config-registry.d.ts","sourceRoot":"","sources":["../../src/cdk/config-registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AAGnC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AA4BpD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAIlF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAEvF;AA6BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,SAAS,EACf,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,EAChC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAC1B,IAAI,CAyCN"}
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
import * as cdk from 'aws-cdk-lib';
|
|
4
4
|
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
5
5
|
import * as s3deploy from 'aws-cdk-lib/aws-s3-deployment';
|
|
6
|
-
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
7
6
|
const REGISTRY_KEY = Symbol.for('BLOCKS_CONFIG_REGISTRY');
|
|
7
|
+
/** The object key of the config JSON under {@link getConfigLocation}'s bucket. */
|
|
8
|
+
const CONFIG_KEY = 'blocks-config.json';
|
|
8
9
|
/**
|
|
9
10
|
* Get or create the config registry for a given stack.
|
|
10
11
|
* The registry collects BB config entries (env var key → CDK token value)
|
|
@@ -34,47 +35,104 @@ export function registerConfig(scope, key, value) {
|
|
|
34
35
|
const registry = getRegistry(stack);
|
|
35
36
|
registry.entries.set(key, value);
|
|
36
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Ensure the shared config bucket exists and return where the config JSON lives
|
|
40
|
+
* (`{ bucketName, key }`). The bucket is created **once per stack** (memoized on
|
|
41
|
+
* the registry) and this is idempotent — the first caller creates it, later
|
|
42
|
+
* callers get the same bucket regardless of order.
|
|
43
|
+
*
|
|
44
|
+
* Any compute that loads config at runtime (`loadConfigToProcessEnv()`) injects
|
|
45
|
+
* these two values as `BLOCKS_CONFIG_BUCKET` / `BLOCKS_CONFIG_KEY`. The Lambda
|
|
46
|
+
* handler gets them from {@link finalizeConfigRegistry}; other compute that runs
|
|
47
|
+
* as the shared execution role (e.g. the Agent BB's AgentCore Runtime) calls this
|
|
48
|
+
* at construction to inject them too, so it loads the same app config the handler
|
|
49
|
+
* does. IAM is not granted here — `finalizeConfigRegistry` grants read on the config
|
|
50
|
+
* object to the shared execution role, which such compute inherits.
|
|
51
|
+
*
|
|
52
|
+
* @param scope - Any construct in the stack; the bucket is created under the stack.
|
|
53
|
+
*/
|
|
54
|
+
export function getConfigLocation(scope) {
|
|
55
|
+
return { bucketName: ensureConfigBucket(scope).bucketName, key: CONFIG_KEY };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create-or-return the shared config bucket (memoized on the per-stack registry). Created under the
|
|
59
|
+
* owning `BlocksStack`/`BlocksBackend` (`globalThis.CURRENT_BLOCKS_STACK` — the construct finalize
|
|
60
|
+
* historically used), so its logical ID is stable regardless of which caller creates it first: a
|
|
61
|
+
* co-located BB (e.g. the AgentCore Runtime, a deep construct) may be the first to call it, and a
|
|
62
|
+
* `BlocksBackend` embedded in a customer stack must keep `Blocks/BlocksConfigBucket` (no replacement).
|
|
63
|
+
* Falls back to the stack when no owner is registered (isolated unit tests). Returns a concrete
|
|
64
|
+
* `s3.Bucket` so callers don't need a non-null assertion.
|
|
65
|
+
*/
|
|
66
|
+
function ensureConfigBucket(scope) {
|
|
67
|
+
const stack = cdk.Stack.of(scope);
|
|
68
|
+
const registry = getRegistry(stack);
|
|
69
|
+
if (!registry.bucket) {
|
|
70
|
+
const owner = globalThis.CURRENT_BLOCKS_STACK ?? stack;
|
|
71
|
+
registry.bucket = new s3.Bucket(owner, 'BlocksConfigBucket', {
|
|
72
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
73
|
+
autoDeleteObjects: true,
|
|
74
|
+
encryption: s3.BucketEncryption.S3_MANAGED,
|
|
75
|
+
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
|
|
76
|
+
lifecycleRules: [
|
|
77
|
+
{ noncurrentVersionExpiration: cdk.Duration.days(1) },
|
|
78
|
+
],
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return registry.bucket;
|
|
82
|
+
}
|
|
37
83
|
/**
|
|
38
84
|
* Finalize the config registry: create an S3 bucket, upload the config JSON,
|
|
39
|
-
*
|
|
85
|
+
* grant read to the shared execution role, and stamp the config coordinates
|
|
86
|
+
* (`BLOCKS_CONFIG_BUCKET` / `BLOCKS_CONFIG_KEY`) onto every compute.
|
|
87
|
+
*
|
|
88
|
+
* Read access is granted once to the shared role (`root.executionRole`) rather
|
|
89
|
+
* than to a single function, so every compute that assumes the role can read
|
|
90
|
+
* the object. The bucket/key coordinates can't live on a role (env vars are
|
|
91
|
+
* per-compute), so they are set on each compute via `setEnv`.
|
|
40
92
|
*
|
|
41
93
|
* Must be called after all BBs are constructed (i.e., after the backendCDKPath
|
|
42
94
|
* import completes in BlocksStack.create() / BlocksBackend.create()).
|
|
43
95
|
*
|
|
44
|
-
* @param
|
|
45
|
-
*
|
|
96
|
+
* @param root - The construct to create the config resources under (also used
|
|
97
|
+
* to locate the owning stack).
|
|
98
|
+
* @param executionRole - The shared role every compute assumes; config read is
|
|
99
|
+
* granted to it once.
|
|
100
|
+
* @param computes - The computes to stamp `BLOCKS_CONFIG_BUCKET` / `BLOCKS_CONFIG_KEY` on.
|
|
46
101
|
*/
|
|
47
|
-
export function finalizeConfigRegistry(
|
|
48
|
-
const stack = cdk.Stack.of(
|
|
102
|
+
export function finalizeConfigRegistry(root, executionRole, computes) {
|
|
103
|
+
const stack = cdk.Stack.of(root);
|
|
49
104
|
const registry = getRegistry(stack);
|
|
50
105
|
if (registry.finalized)
|
|
51
106
|
return;
|
|
52
107
|
registry.finalized = true;
|
|
53
|
-
if
|
|
108
|
+
// Nothing to do only if no config was registered AND no bucket was created (via
|
|
109
|
+
// getConfigLocation). If a co-located BB created the bucket, still upload (even an empty {}) and
|
|
110
|
+
// wire the handler so that compute's loadConfigToProcessEnv() resolves instead of 404-ing forever.
|
|
111
|
+
if (registry.entries.size === 0 && !registry.bucket)
|
|
54
112
|
return;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
encryption: s3.BucketEncryption.S3_MANAGED,
|
|
59
|
-
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
|
|
60
|
-
lifecycleRules: [
|
|
61
|
-
{ noncurrentVersionExpiration: cdk.Duration.days(1) },
|
|
62
|
-
],
|
|
63
|
-
});
|
|
64
|
-
const configKey = 'blocks-config.json';
|
|
113
|
+
// Ensure the bucket exists (a co-located BB may already have created it via getConfigLocation).
|
|
114
|
+
const configBucket = ensureConfigBucket(root);
|
|
115
|
+
const configKey = CONFIG_KEY;
|
|
65
116
|
const configObject = cdk.Lazy.any({
|
|
66
117
|
produce: () => Object.fromEntries(registry.entries),
|
|
67
118
|
});
|
|
68
|
-
|
|
119
|
+
new s3deploy.BucketDeployment(root, 'BlocksConfigDeployment', {
|
|
69
120
|
sources: [s3deploy.Source.jsonData(configKey, configObject)],
|
|
70
121
|
destinationBucket: configBucket,
|
|
71
122
|
prune: false,
|
|
72
123
|
});
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
124
|
+
// Grant read once to the shared role (scoped to the config key), so every
|
|
125
|
+
// compute assuming the role can read it. We intentionally use `grantRead`
|
|
126
|
+
// (which also adds s3:GetBucket*/s3:List* alongside s3:GetObject*) rather
|
|
127
|
+
// than a hand-rolled GetObject-only statement: this is a dedicated,
|
|
128
|
+
// block-all-public, config-only bucket, so the broader action set carries
|
|
129
|
+
// negligible exposure, and grantRead stays correct automatically if the
|
|
130
|
+
// bucket ever moves to KMS encryption (it would add kms:Decrypt).
|
|
131
|
+
configBucket.grantRead(executionRole, configKey);
|
|
132
|
+
// Stamp the config coordinates on every compute — env vars can't live on a
|
|
133
|
+
// role, so each compute needs them to locate the object at runtime.
|
|
134
|
+
for (const compute of computes) {
|
|
135
|
+
compute.setEnv('BLOCKS_CONFIG_BUCKET', configBucket.bucketName);
|
|
136
|
+
compute.setEnv('BLOCKS_CONFIG_KEY', configKey);
|
|
137
|
+
}
|
|
80
138
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-registry.test.d.ts","sourceRoot":"","sources":["../../src/cdk/config-registry.test.ts"],"names":[],"mappings":""}
|