Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): fix asset bundling for nested stack with exclusive flag #30983

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/aws-cdk-lib/core/lib/nested-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ export class NestedStack extends Stack {
resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_PATH_KEY] = this.templateFile;
resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_PROPERTY_KEY] = resourceProperty;
}

public get bundlingRequired() {
return this._parentStack.bundlingRequired;
}
}

/**
Expand Down
25 changes: 25 additions & 0 deletions packages/aws-cdk-lib/core/test/nested-stack.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as path from 'path';
import { Construct } from 'constructs';
import { readFileSync } from 'fs-extra';
import { toCloudFormation } from './util';
import * as cxapi from '../../cx-api';
import {
Stack, NestedStack, CfnStack, Resource, CfnResource, App, CfnOutput,
} from '../lib';
Expand Down Expand Up @@ -168,6 +169,30 @@ describe('nested-stack', () => {
expect(() => toCloudFormation(stack2)).toThrow(
/Cannot use resource 'Stack1\/MyNestedStack\/MyResource' in a cross-environment fashion/);
});

test('requires bundling when root stack has exact match in BUNDLING_STACKS', () => {
const app = new App();
const stack = new Stack(app, 'Stack');
stack.node.setContext(cxapi.BUNDLING_STACKS, ['Stack']);

const child = new NestedStack(stack, 'Child');
const child_2 = new NestedStack(child, 'Child2');

expect(child.bundlingRequired).toBe(true);
expect(child_2.bundlingRequired).toBe(true);
});

test('not requires bundling when root stack has no match in BUNDLING_STACKS', () => {
const app = new App();
const stack = new Stack(app, 'Stack');
stack.node.setContext(cxapi.BUNDLING_STACKS, ['Stack2']);

const child = new NestedStack(stack, 'Child');
const child_2 = new NestedStack(child, 'Child2');

expect(child.bundlingRequired).toBe(false);
expect(child_2.bundlingRequired).toBe(false);
});
});

class MyResource extends Resource {
Expand Down
44 changes: 43 additions & 1 deletion packages/aws-cdk-lib/core/test/staging.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as fs from 'fs-extra';
import * as sinon from 'sinon';
import { FileAssetPackaging } from '../../cloud-assembly-schema';
import * as cxapi from '../../cx-api';
import { App, AssetHashType, AssetStaging, DockerImage, BundlingOptions, BundlingOutput, FileSystem, Stack, Stage, BundlingFileAccess } from '../lib';
import { App, AssetHashType, AssetStaging, DockerImage, BundlingOptions, BundlingOutput, FileSystem, Stack, NestedStack, Stage, BundlingFileAccess } from '../lib';

const STUB_INPUT_FILE = '/tmp/docker-stub.input';
const STUB_INPUT_CONCAT_FILE = '/tmp/docker-stub.input.concat';
Expand Down Expand Up @@ -1106,6 +1106,48 @@ describe('staging', () => {
expect(dockerStubInput).not.toMatch(DockerStubCommand.MULTIPLE_FILES);
});

test('correctly skips bundling with stack under stage and nested stack', () => {
// GIVEN
const app = new App();

const stage = new Stage(app, 'Stage');
stage.node.setContext(cxapi.BUNDLING_STACKS, ['Stage/Stack1']);

const stack1 = new Stack(stage, 'Stack1', { stackName: 'unrelated-stack1-name' });
const stack1_nested = new NestedStack(stack1, "Stack1Nest");

const stack2 = new Stack(stage, 'Stack2', { stackName: 'unrelated-stack2-name' });
const stack2_nested = new NestedStack(stack2, "Stack2Nest");

const directory = path.join(__dirname, 'fs', 'fixtures', 'test1');

// WHEN
new AssetStaging(stack1_nested, 'Asset', {
sourcePath: directory,
assetHashType: AssetHashType.OUTPUT,
bundling: {
image: DockerImage.fromRegistry('alpine'),
command: [DockerStubCommand.SUCCESS],
},
});

new AssetStaging(stack2_nested, 'Asset', {
sourcePath: directory,
assetHashType: AssetHashType.OUTPUT,
bundling: {
image: DockerImage.fromRegistry('alpine'),
command: [DockerStubCommand.MULTIPLE_FILES],
},
});

// THEN
const dockerStubInput = readDockerStubInputConcat();
// Docker ran for the asset in Stack1
expect(dockerStubInput).toMatch(DockerStubCommand.SUCCESS);
// Docker did not run for the asset in Stack2
expect(dockerStubInput).not.toMatch(DockerStubCommand.MULTIPLE_FILES);
});

test('correctly bundles with stack under stage and the default stack pattern', () => {
// GIVEN
const app = new App();
Expand Down
Loading