diff --git a/packages/@aws-cdk/core/test/stage.test.ts b/packages/@aws-cdk/core/test/stage.test.ts index 8a4b27a4d412a..897b3513d6163 100644 --- a/packages/@aws-cdk/core/test/stage.test.ts +++ b/packages/@aws-cdk/core/test/stage.test.ts @@ -1,3 +1,4 @@ +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import { nodeunitShim, Test } from 'nodeunit-shim'; import { App, CfnResource, Construct, IAspect, IConstruct, Stack, Stage, Aspects } from '../lib'; @@ -311,6 +312,40 @@ nodeunitShim({ }, }); +test('missing context in Stages is propagated up to root assembly', () => { + // GIVEN + const app = new App(); + const stage = new Stage(app, 'Stage', { + env: { account: 'account', region: 'region' }, + }); + const stack = new Stack(stage, 'Stack'); + new CfnResource(stack, 'Resource', { type: 'Something' }); + + // WHEN + stack.reportMissingContext({ + key: 'missing-context-key', + provider: cxschema.ContextProvider.AVAILABILITY_ZONE_PROVIDER, + props: { + account: 'account', + region: 'region', + }, + }); + + // THEN + const assembly = app.synth(); + + expect(assembly.manifest.missing).toEqual([ + { + key: 'missing-context-key', + provider: cxschema.ContextProvider.AVAILABILITY_ZONE_PROVIDER, + props: { + account: 'account', + region: 'region', + }, + }, + ]); +}); + class TouchingAspect implements IAspect { public readonly visits = new Array(); public visit(node: IConstruct): void { diff --git a/packages/@aws-cdk/cx-api/lib/cloud-assembly.ts b/packages/@aws-cdk/cx-api/lib/cloud-assembly.ts index df947f379ab46..53fafe3d37049 100644 --- a/packages/@aws-cdk/cx-api/lib/cloud-assembly.ts +++ b/packages/@aws-cdk/cx-api/lib/cloud-assembly.ts @@ -219,6 +219,13 @@ export interface CloudAssemblyBuilderProps { * @default - Same as the manifest outdir */ readonly assetOutdir?: string; + + /** + * If this builder is for a nested assembly, the parent assembly builder + * + * @default - This is a root assembly + */ + readonly parentBuilder?: CloudAssemblyBuilder; } /** @@ -237,6 +244,7 @@ export class CloudAssemblyBuilder { private readonly artifacts: { [id: string]: cxschema.ArtifactManifest } = { }; private readonly missing = new Array(); + private readonly parentBuilder?: CloudAssemblyBuilder; /** * Initializes a cloud assembly builder. @@ -245,6 +253,7 @@ export class CloudAssemblyBuilder { constructor(outdir?: string, props: CloudAssemblyBuilderProps = {}) { this.outdir = determineOutputDirectory(outdir); this.assetOutdir = props.assetOutdir ?? this.outdir; + this.parentBuilder = props.parentBuilder; // we leverage the fact that outdir is long-lived to avoid staging assets into it // that were already staged (copying can be expensive). this is achieved by the fact @@ -270,6 +279,8 @@ export class CloudAssemblyBuilder { if (this.missing.every(m => m.key !== missing.key)) { this.missing.push(missing); } + // Also report in parent + this.parentBuilder?.addMissing(missing); } /** @@ -320,6 +331,7 @@ export class CloudAssemblyBuilder { return new CloudAssemblyBuilder(innerAsmDir, { // Reuse the same asset output directory as the current Casm builder assetOutdir: this.assetOutdir, + parentBuilder: this, }); } } diff --git a/packages/@aws-cdk/cx-api/test/cloud-assembly-builder.test.ts b/packages/@aws-cdk/cx-api/test/cloud-assembly-builder.test.ts index fb7ad4d71a407..13b81c572a126 100644 --- a/packages/@aws-cdk/cx-api/test/cloud-assembly-builder.test.ts +++ b/packages/@aws-cdk/cx-api/test/cloud-assembly-builder.test.ts @@ -174,6 +174,28 @@ test('write and read nested cloud assembly artifact', () => { expect(nested?.artifacts.length).toEqual(0); }); +test('missing values are reported to top-level asm', () => { + // GIVEN + const outdir = fs.mkdtempSync(path.join(os.tmpdir(), 'cloud-assembly-builder-tests')); + const session = new cxapi.CloudAssemblyBuilder(outdir); + + const innerAsm = session.createNestedAssembly('hello', 'hello'); + + // WHEN + const props: cxschema.ContextQueryProperties = { + account: '1234', + region: 'asdf', + filter: { a: 'a' }, + }; + + innerAsm.addMissing({ key: 'foo', provider: cxschema.ContextProvider.VPC_PROVIDER, props }); + + // THEN + const assembly = session.buildAssembly(); + + expect(assembly.manifest.missing?.length).toEqual(1); +}); + test('artifcats are written in topological order', () => { // GIVEN const outdir = fs.mkdtempSync(path.join(os.tmpdir(), 'cloud-assembly-builder-tests'));