diff --git a/test-apps/extending-blocks-guide-blocksbackend/aws-blocks/index.cdk.ts b/test-apps/extending-blocks-guide-blocksbackend/aws-blocks/index.cdk.ts index 2443e5d34..05732c7ca 100644 --- a/test-apps/extending-blocks-guide-blocksbackend/aws-blocks/index.cdk.ts +++ b/test-apps/extending-blocks-guide-blocksbackend/aws-blocks/index.cdk.ts @@ -11,7 +11,7 @@ import * as cdk from 'aws-cdk-lib'; import { RemovalPolicies, Mixins } from 'aws-cdk-lib'; import * as sqs from 'aws-cdk-lib/aws-sqs'; -import { BlocksBackend, SandboxDisableDeletionProtection } from '@aws-blocks/blocks/cdk'; +import { BlocksBackend, SandboxDisableDeletionProtection, registerConfig } from '@aws-blocks/blocks/cdk'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; import { getSandboxId } from './scripts/sandbox-id.js'; @@ -53,9 +53,9 @@ class MyExistingStack extends cdk.Stack { backendCDKPath: join(__dirname, 'index.ts'), }); - // Wire IAM + env on the BlocksBackend's handler — same surface as BlocksStack. + // Wire IAM and runtime configuration on the BlocksBackend — same surface as BlocksStack. stack.externalQueue.grantSendMessages(stack.blocks.handler); - stack.blocks.handler.addEnvironment('EXTERNAL_QUEUE_URL', stack.externalQueue.queueUrl); + registerConfig(stack.blocks, 'EXTERNAL_QUEUE_URL', stack.externalQueue.queueUrl); new cdk.CfnOutput(stack, 'ApiUrl', { value: stack.blocks.apiUrl }); new cdk.CfnOutput(stack, 'ExternalQueueUrl', { value: stack.externalQueue.queueUrl }); diff --git a/test-apps/extending-blocks-guide-blocksbackend/test/synth.test.ts b/test-apps/extending-blocks-guide-blocksbackend/test/synth.test.ts index 94d703ff7..add8b4c7f 100644 --- a/test-apps/extending-blocks-guide-blocksbackend/test/synth.test.ts +++ b/test-apps/extending-blocks-guide-blocksbackend/test/synth.test.ts @@ -5,8 +5,8 @@ * Synth-time validation for the BlocksBackend harness. * * Asserts that BlocksBackend.create produces the expected resources INSIDE - * the user-owned outer stack (not in a separate stack), and that env vars - * + IAM are wired correctly to the BlocksBackend's handler. + * the user-owned outer stack (not in a separate stack), and that runtime + * configuration + IAM are wired correctly to the BlocksBackend's handler. */ import { test, describe, before } from 'node:test'; import assert from 'node:assert'; @@ -29,15 +29,13 @@ describe('extending-blocks-guide-blocksbackend synth', () => { template = JSON.parse(readFileSync(join(SYNTH_DIR, files[0]), 'utf-8')); }); - test('exactly one Lambda function (the BlocksBackend handler)', () => { - const lambdas = Object.values(template.Resources).filter( - (r: any) => r.Type === 'AWS::Lambda::Function' - ); - assert.strictEqual( - lambdas.length, - 1, - `expected 1 Lambda (BlocksBackend handler); got ${lambdas.length}.` + test('contains the BlocksBackend handler', () => { + const handler = Object.values(template.Resources).find( + (r: any) => + r.Type === 'AWS::Lambda::Function' && + r.Properties?.Environment?.Variables?.NODE_ENV === 'production' ); + assert.ok(handler, 'could not find BlocksBackend handler Lambda'); }); test('exactly one API Gateway (managed by BlocksBackend)', () => { @@ -54,7 +52,7 @@ describe('extending-blocks-guide-blocksbackend synth', () => { assert.strictEqual(queues.length, 1); }); - test('BlocksBackend handler has EXTERNAL_QUEUE_URL injected by the outer stack', () => { + test('registers EXTERNAL_QUEUE_URL in the runtime config', () => { const handler: any = Object.values(template.Resources).find( (r: any) => r.Type === 'AWS::Lambda::Function' && @@ -62,6 +60,15 @@ describe('extending-blocks-guide-blocksbackend synth', () => { ); assert.ok(handler, 'could not find Blocks handler Lambda'); const envVars = handler.Properties.Environment.Variables; - assert.ok('EXTERNAL_QUEUE_URL' in envVars, 'missing EXTERNAL_QUEUE_URL on BlocksBackend handler'); + assert.ok('BLOCKS_CONFIG_BUCKET' in envVars, 'missing BLOCKS_CONFIG_BUCKET on handler'); + assert.ok('BLOCKS_CONFIG_KEY' in envVars, 'missing BLOCKS_CONFIG_KEY on handler'); + assert.ok(!('EXTERNAL_QUEUE_URL' in envVars), 'EXTERNAL_QUEUE_URL must use runtime config'); + + const configDeployment: any = Object.values(template.Resources).find( + (r: any) => r.Type === 'Custom::CDKBucketDeployment' + ); + assert.ok(configDeployment, 'missing runtime config deployment'); + const config = JSON.stringify(configDeployment.Properties.SourceMarkers); + assert.ok(config.includes('EXTERNAL_QUEUE_URL'), 'missing EXTERNAL_QUEUE_URL in runtime config'); }); }); diff --git a/test-apps/extending-blocks-guide/aws-blocks/index.cdk.ts b/test-apps/extending-blocks-guide/aws-blocks/index.cdk.ts index 23d8adf6f..898215fa6 100644 --- a/test-apps/extending-blocks-guide/aws-blocks/index.cdk.ts +++ b/test-apps/extending-blocks-guide/aws-blocks/index.cdk.ts @@ -5,7 +5,7 @@ import * as cdk from 'aws-cdk-lib'; import { RemovalPolicies, Mixins } from 'aws-cdk-lib'; import * as sqs from 'aws-cdk-lib/aws-sqs'; import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; -import { BlocksStack, SandboxDisableDeletionProtection } from '@aws-blocks/blocks/cdk'; +import { BlocksStack, SandboxDisableDeletionProtection, registerConfig } from '@aws-blocks/blocks/cdk'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; import { getSandboxId } from './scripts/sandbox-id.js'; @@ -38,7 +38,7 @@ Mixins.of(blocksStack).apply(new SandboxDisableDeletionProtection()); // Pattern 1 fixture: an SQS queue we'll send to via raw SDK. const externalQueue = new sqs.Queue(blocksStack, 'external-queue'); externalQueue.grantSendMessages(blocksStack.handler); -blocksStack.handler.addEnvironment('EXTERNAL_QUEUE_URL', externalQueue.queueUrl); +registerConfig(blocksStack, 'EXTERNAL_QUEUE_URL', externalQueue.queueUrl); // Pattern 2 fixtures: two DynamoDB tables that pretend to predate Blocks. // We pre-pinned the physical names above so KVStore.fromExisting and @@ -67,7 +67,7 @@ new cdk.CfnOutput(blocksStack, 'StackNameOut', { value: stackName }); // Surface the table names to runtime — *.fromExisting on the runtime side // reads them from process.env. -blocksStack.handler.addEnvironment('BLOCKS_LEGACY_SESSIONS_TABLE', legacyTableName); -blocksStack.handler.addEnvironment('BLOCKS_LEGACY_USERS_TABLE', legacyUsersTableName); +registerConfig(blocksStack, 'BLOCKS_LEGACY_SESSIONS_TABLE', legacyTableName); +registerConfig(blocksStack, 'BLOCKS_LEGACY_USERS_TABLE', legacyUsersTableName); cdk.Tags.of(blocksStack).add('blocks:purpose', 'extending-guide-validation'); diff --git a/test-apps/extending-blocks-guide/packages/bb-queue/src/index.cdk.ts b/test-apps/extending-blocks-guide/packages/bb-queue/src/index.cdk.ts index 679df9f4a..23b944a06 100644 --- a/test-apps/extending-blocks-guide/packages/bb-queue/src/index.cdk.ts +++ b/test-apps/extending-blocks-guide/packages/bb-queue/src/index.cdk.ts @@ -3,7 +3,7 @@ import { Duration } from 'aws-cdk-lib'; import * as sqs from 'aws-cdk-lib/aws-sqs'; -import { Scope } from '@aws-blocks/core/cdk'; +import { Scope, registerConfig } from '@aws-blocks/core/cdk'; import type { ScopeParent } from '@aws-blocks/core'; export interface QueueOptions { @@ -21,7 +21,7 @@ export class Queue extends Scope { }); queue.grantSendMessages(this.handler); - this.handler.addEnvironment(`${envSafe(this.fullId)}_URL`, queue.queueUrl); + registerConfig(this, `${envSafe(this.fullId)}_URL`, queue.queueUrl); } } diff --git a/test-apps/extending-blocks-guide/test/synth.test.ts b/test-apps/extending-blocks-guide/test/synth.test.ts index 369f7ea3c..8027ddb36 100644 --- a/test-apps/extending-blocks-guide/test/synth.test.ts +++ b/test-apps/extending-blocks-guide/test/synth.test.ts @@ -6,10 +6,10 @@ * template to assert each pattern produced (or *didn't* produce) the * expected resources. * - * Pattern 1: external SQS queue + handler env var EXTERNAL_QUEUE_URL. + * Pattern 1: external SQS queue + runtime config EXTERNAL_QUEUE_URL. * Pattern 2: legacy DynamoDB table is created by us; KVStore.fromExisting * does NOT add a second table (this asserts the bb-kv-store fix). - * Pattern 3: bb-queue creates its own SQS queue, env var WORK_URL on handler. + * Pattern 3: bb-queue creates its own SQS queue, runtime config WORK_URL. */ import { test, describe, before } from 'node:test'; import assert from 'node:assert'; @@ -70,7 +70,7 @@ describe('extending-blocks-guide synth', () => { assert.strictEqual(queues.length, 2, `expected 2 SQS queues; got ${queues.length}`); }); - test('handler has EXTERNAL_QUEUE_URL and BLOCKS_LEGACY_SESSIONS_TABLE env vars', () => { + test('registers external resource identifiers in the runtime config', () => { const handler: any = Object.values(template.Resources).find( (r: any) => r.Type === 'AWS::Lambda::Function' && @@ -78,10 +78,17 @@ describe('extending-blocks-guide synth', () => { ); assert.ok(handler, 'could not find Blocks handler Lambda'); const envVars = handler.Properties.Environment.Variables; - assert.ok('EXTERNAL_QUEUE_URL' in envVars, 'missing EXTERNAL_QUEUE_URL on handler'); - assert.ok('BLOCKS_LEGACY_SESSIONS_TABLE' in envVars, 'missing BLOCKS_LEGACY_SESSIONS_TABLE on handler'); - // Pattern 3: bb-queue injects EXTENDING_GUIDE_WORK_URL. - const workKey = Object.keys(envVars).find(k => k.endsWith('_WORK_URL')); - assert.ok(workKey, 'missing *_WORK_URL on handler (Pattern 3 custom BB)'); + assert.ok('BLOCKS_CONFIG_BUCKET' in envVars, 'missing BLOCKS_CONFIG_BUCKET on handler'); + assert.ok('BLOCKS_CONFIG_KEY' in envVars, 'missing BLOCKS_CONFIG_KEY on handler'); + assert.ok(!('EXTERNAL_QUEUE_URL' in envVars), 'EXTERNAL_QUEUE_URL must use runtime config'); + + const configDeployment: any = Object.values(template.Resources).find( + (r: any) => r.Type === 'Custom::CDKBucketDeployment' + ); + assert.ok(configDeployment, 'missing runtime config deployment'); + const config = JSON.stringify(configDeployment.Properties.SourceMarkers); + assert.ok(config.includes('EXTERNAL_QUEUE_URL'), 'missing EXTERNAL_QUEUE_URL in runtime config'); + assert.ok(config.includes('BLOCKS_LEGACY_SESSIONS_TABLE'), 'missing legacy sessions table in runtime config'); + assert.ok(config.includes('WORK_URL'), 'missing custom BB queue URL in runtime config'); }); });