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

feat(toolkit): introduce the concept of auto-deployed Stacks #2046

Merged
merged 1 commit into from
Mar 20, 2019
Merged
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
26 changes: 25 additions & 1 deletion packages/@aws-cdk/cdk/lib/stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ export interface StackProps {
* Optional. If not supplied, the HashedNamingScheme will be used.
*/
namingScheme?: IAddressingScheme;

/**
* Should the Stack be deployed when running `cdk deploy` without arguments
* (and listed when running `cdk synth` without arguments).
* Setting this to `false` is useful when you have a Stack in your CDK app
* that you don't want to deploy using the CDK toolkit -
* for example, because you're planning on deploying it through CodePipeline.
*
* @default true
*/
autoDeploy?: boolean;
}

/**
Expand Down Expand Up @@ -90,6 +101,17 @@ export class Stack extends Construct {
*/
public readonly name: string;

/**
* Should the Stack be deployed when running `cdk deploy` without arguments
* (and listed when running `cdk synth` without arguments).
* Setting this to `false` is useful when you have a Stack in your CDK app
* that you don't want to deploy using the CDK toolkit -
* for example, because you're planning on deploying it through CodePipeline.
*
* By default, this is `true`.
*/
public readonly autoDeploy: boolean;

/*
* Used to determine if this construct is a stack.
*/
Expand Down Expand Up @@ -132,6 +154,7 @@ export class Stack extends Construct {

this.logicalIds = new LogicalIDs(props && props.namingScheme ? props.namingScheme : new HashedAddressingScheme());
this.name = props.stackName !== undefined ? props.stackName : this.calculateStackName();
this.autoDeploy = props && props.autoDeploy === false ? false : true;
}

/**
Expand Down Expand Up @@ -474,7 +497,8 @@ export class Stack extends Construct {
environment: this.environment,
properties: {
templateFile: template,
}
},
autoDeploy: this.autoDeploy ? undefined : false,
};

if (Object.keys(this.parameterValues).length > 0) {
Expand Down
3 changes: 2 additions & 1 deletion packages/@aws-cdk/cdk/lib/synthesis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ function renderLegacyStacks(artifacts: { [id: string]: cxapi.Artifact }, store:
environment: { name: artifact.environment.substr('aws://'.length), account: match[1], region: match[2] },
template,
metadata: artifact.metadata || {},
autoDeploy: artifact.autoDeploy,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should also rendered in the non-legacy artifact or we will lose this feature once we deprecate this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does the code for that live? That's the only place I could find this logic...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answered by Elad offline... https://github.com/awslabs/aws-cdk/blob/master/packages/%40aws-cdk/cdk/lib/stack.ts#L472 .

The PR already includes a change in that method.

};

if (artifact.dependencies && artifact.dependencies.length > 0) {
Expand All @@ -369,4 +370,4 @@ function renderLegacyStacks(artifacts: { [id: string]: cxapi.Artifact }, store:
}

return stacks;
}
}
3 changes: 2 additions & 1 deletion packages/@aws-cdk/cdk/test/test.synthesis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ export = {
'one-stack': {
type: 'aws:cloudformation:stack',
environment: 'aws://unknown-account/unknown-region',
properties: { templateFile: 'one-stack.template.json' }
properties: { templateFile: 'one-stack.template.json' },
autoDeploy: undefined,
}
},
});
Expand Down
3 changes: 2 additions & 1 deletion packages/@aws-cdk/cx-api/lib/artifacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ export interface Artifact {
dependencies?: string[];
missing?: { [key: string]: any };
properties?: { [name: string]: any };
autoDeploy?: boolean;
}

export function validateArtifact(artifcat: Artifact) {
if (!AWS_ENV_REGEX.test(artifcat.environment)) {
throw new Error(`Artifact "environment" must conform to ${AWS_ENV_REGEX}: ${artifcat.environment}`);
}
}
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/cx-api/lib/cxapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export interface SynthesizedStack {
missing?: { [key: string]: MissingContext };
metadata: StackMetadata;
template: any;
autoDeploy?: boolean;

/**
* Other stacks this stack depends on
Expand Down
6 changes: 4 additions & 2 deletions packages/aws-cdk/lib/api/cxapp/stacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ export class AppStacks {
}

if (selectors.length === 0) {
debug('Stack name not specified, so defaulting to all available stacks: ' + listStackNames(stacks));
return this.applyRenames(stacks);
// remove non-auto deployed Stacks
const autoDeployedStacks = stacks.filter(s => s.autoDeploy !== false);
debug('Stack name not specified, so defaulting to all available stacks: ' + listStackNames(autoDeployedStacks));
return this.applyRenames(autoDeployedStacks);
}

const allStacks = new Map<string, cxapi.SynthesizedStack>();
Expand Down
84 changes: 83 additions & 1 deletion packages/aws-cdk/test/api/test.stacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,86 @@ export = {

test.done();
},
};

async 'does not return non-autoDeployed Stacks when called without any selectors'(test: Test) {
// GIVEN
const stacks = appStacksWith([
{
name: 'NotAutoDeployedStack',
template: { resource: 'Resource' },
environment: { name: 'dev', account: '12345', region: 'here' },
metadata: {},
autoDeploy: false,
},
]);

// WHEN
const synthed = await stacks.selectStacks([], ExtendedStackSelection.None);

// THEN
test.equal(synthed.length, 0);

test.done();
},

async 'does return non-autoDeployed Stacks when called with selectors matching it'(test: Test) {
// GIVEN
const stacks = appStacksWith([
{
name: 'NotAutoDeployedStack',
template: { resource: 'Resource' },
environment: { name: 'dev', account: '12345', region: 'here' },
metadata: {},
autoDeploy: false,
},
]);

// WHEN
const synthed = await stacks.selectStacks(['NotAutoDeployedStack'], ExtendedStackSelection.None);

// THEN
test.equal(synthed.length, 1);

test.done();
},

async "does return an non-autoDeployed Stack when it's a dependency of a selected Stack"(test: Test) {
// GIVEN
const stacks = appStacksWith([
{
name: 'NotAutoDeployedStack',
template: { resource: 'Resource' },
environment: { name: 'dev', account: '12345', region: 'here' },
metadata: {},
autoDeploy: false,
},
{
name: 'AutoDeployedStack',
template: { resource: 'Resource' },
environment: { name: 'dev', account: '12345', region: 'here' },
metadata: {},
dependsOn: ['NotAutoDeployedStack'],
},
]);

// WHEN
const synthed = await stacks.selectStacks(['AutoDeployedStack'], ExtendedStackSelection.Upstream);

// THEN
test.equal(synthed.length, 2);

test.done();
},
};

function appStacksWith(stacks: cxapi.SynthesizedStack[]): AppStacks {
const response: cxapi.SynthesizeResponse = {
version: '1',
stacks,
};
return new AppStacks({
configuration: new Configuration(),
aws: new SDK(),
synthesizer: async () => response,
});
}