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(cli): write stack outputs to a file #7020

Merged
merged 24 commits into from
Apr 1, 2020
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2b7367a
Revert "chore(deps): bump fs-extra from 8.1.0 to 9.0.0 (#6820)"
shivlaks Mar 23, 2020
c0d089a
Merge branch 'master' of https://github.com/aws/aws-cdk
shivlaks Mar 24, 2020
84ea33d
Merge branch 'master' of https://github.com/aws/aws-cdk
shivlaks Mar 25, 2020
08efef2
Merge branch 'master' of https://github.com/aws/aws-cdk
shivlaks Mar 25, 2020
7358d0c
add flag to provide a file path where outputs will be written on a cd…
shivlaks Mar 26, 2020
5c238f9
update README
shivlaks Mar 26, 2020
c5ac842
adding integ test for single stack with outputs
shivlaks Mar 26, 2020
067cbb5
add a test for deploying multiple stacks with outputs
shivlaks Mar 26, 2020
ebfb61a
Merge branch 'master' into shivlaks/stack-outputs
shivlaks Mar 26, 2020
45b3eba
add outputs stack to ls test
shivlaks Mar 26, 2020
78da531
modify input parameter to be outputs-file
shivlaks Mar 26, 2020
9819275
update README
shivlaks Mar 26, 2020
acea982
simplify writing to file by writing once at the end of all deploys
shivlaks Mar 27, 2020
443a04f
add statement about outputs being keyed on logical id
shivlaks Apr 1, 2020
f6047af
address PR feedback
shivlaks Apr 1, 2020
13fae78
add outputs stacks to cleanup function
shivlaks Apr 1, 2020
057f210
Update packages/aws-cdk/README.md
shivlaks Apr 1, 2020
87d64a9
fix indentation in README
shivlaks Apr 1, 2020
2fab11d
Update packages/aws-cdk/README.md
shivlaks Apr 1, 2020
4ecde0e
Update packages/aws-cdk/lib/cdk-toolkit.ts
shivlaks Apr 1, 2020
9e792f7
Update packages/aws-cdk/README.md
shivlaks Apr 1, 2020
5e1d02b
wrap line length to 100
shivlaks Apr 1, 2020
0522a6f
wrap to 100
shivlaks Apr 1, 2020
350e289
Merge branch 'master' into shivlaks/stack-outputs
mergify[bot] Apr 1, 2020
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
54 changes: 54 additions & 0 deletions packages/aws-cdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,60 @@ $ cdk deploy --parameters "ParametersStack:TopicNameParam=blahagain" --force

⚠️ Parameters do not propagate to NestedStacks. These must be sent with the constructor. See Nested Stack [documentation](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-cloudformation.NestedStack.html)

##### Outputs

Write stack outputs from deployments into a file. When your stack finishes deploying, all stack outputs will be written to the output file as JSON.

Usage of output in a CDK stack
```typescript
const fn = new lambda.Function(this, "fn", {
handler: "index.handler",
shivlaks marked this conversation as resolved.
Show resolved Hide resolved
code: lambda.Code.fromInline(`exports.handler = \${handler.toString()}`),
runtime: lambda.Runtime.NODEJS_10_X
});

new cdk.CfnOutput(this, 'FunctionArn', {
value: fn.functionArn,
});
```

Specify an outputs file to write to by supplying the `--outputs-file` parameter

```console
$ cdk deploy --outputs-file "/Users/code/myproject/outputs.json"
shivlaks marked this conversation as resolved.
Show resolved Hide resolved
```

When the stack finishes deployment, `outputs.json` would look like.
shivlaks marked this conversation as resolved.
Show resolved Hide resolved
```json
{
"MyStack": {
"FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:MyStack-fn5FF616E3-G632ITHSP5HK"
shivlaks marked this conversation as resolved.
Show resolved Hide resolved
}
}
```

⚠️ The `key` of the outputs corresponds to the logical ID.
shivlaks marked this conversation as resolved.
Show resolved Hide resolved
Read more about identifiers in the CDK [here](https://docs.aws.amazon.com/cdk/latest/guide/identifiers.html)

If multiple stacks are being deployed or the wild card `*` is used to deploy all stacks, all outputs are written to the same output file where each stack artifact ID is a key in the JSON file
shivlaks marked this conversation as resolved.
Show resolved Hide resolved


```console
$ cdk deploy '*' --outputs-file "/Users/code/myproject/outputs.json"
```

Example `outputs.json` after deployment of multiple stacks
```json
{
"MyStack": {
"FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:MyStack-fn5FF616E3-G632ITHSP5HK"
},
"AnotherStack": {
"VPCId": "vpc-z0mg270fee16693f"
}
}
```

#### `cdk destroy`
Deletes a stack from it's environment. This will cause the resources in the stack to be destroyed (unless they were
configured with a `DeletionPolicy` of `Retain`). During the stack destruction, the command will output progress
Expand Down
4 changes: 3 additions & 1 deletion packages/aws-cdk/bin/cdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ async function parseCommandLineArguments() {
.option('execute', { type: 'boolean', desc: 'Whether to execute ChangeSet (--no-execute will NOT execute the ChangeSet)', default: true })
.option('force', { alias: 'f', type: 'boolean', desc: 'Always deploy stack even if templates are identical', default: false })
.option('parameters', { type: 'array', desc: 'Additional parameters passed to CloudFormation at deploy time (STACK:KEY=VALUE)', nargs: 1, requiresArg: true, default: {} })
shivlaks marked this conversation as resolved.
Show resolved Hide resolved
.option('outputs-file', { type: 'string', alias: 'O', desc: 'Path to file where stack outputs will be written as JSON', requiresArg: true })
)
.command('destroy [STACKS..]', 'Destroy the stack(s) named STACKS', yargs => yargs
.option('exclusively', { type: 'boolean', alias: 'e', desc: 'Only destroy requested stacks, don\'t include dependees' })
Expand Down Expand Up @@ -238,7 +239,8 @@ async function initCommandLine() {
sdk: aws,
execute: args.execute,
force: args.force,
parameters: parameterMap
parameters: parameterMap,
outputsFile: args.outputsFile
});

case 'destroy':
Expand Down
22 changes: 22 additions & 0 deletions packages/aws-cdk/lib/cdk-toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ export class CdkToolkit {
}
}

const stackOutputs: {[key: string]: any } = {};
shivlaks marked this conversation as resolved.
Show resolved Hide resolved
const outputsFile = options.outputsFile;

for (const stack of stacks) {
if (stacks.length !== 1) { highlight(stack.displayName); }
if (!stack.environment) {
Expand Down Expand Up @@ -170,6 +173,8 @@ export class CdkToolkit {

if (Object.keys(result.outputs).length > 0) {
print('\nOutputs:');

stackOutputs[stack.stackName] = result.outputs;
}

for (const name of Object.keys(result.outputs)) {
Expand All @@ -183,6 +188,17 @@ export class CdkToolkit {
} catch (e) {
error('\n ❌ %s failed: %s', colors.bold(stack.displayName), e);
throw e;
} finally {
// If an outputs file has been specified, create the file path and write stack outputs to it once.
// Outputs are written after all stacks have been deployed. If a stack deployment fails,
// all of the outputs from successfully deployed stacks before the failure will still be written.
if (outputsFile) {
fs.ensureFileSync(outputsFile);
shivlaks marked this conversation as resolved.
Show resolved Hide resolved
fs.writeJson(outputsFile, stackOutputs, {
spaces: 2,
encoding: 'utf8'
});
}
}
}
}
Expand Down Expand Up @@ -337,6 +353,12 @@ export interface DeployOptions {
* @default {}
*/
parameters?: { [name: string]: string | undefined };

/**
* Path to file where stack outputs will be written after a successful deploy as JSON
* @default - Outputs are not written to any file
*/
outputsFile?: string;
}

export interface DestroyOptions {
Expand Down
31 changes: 31 additions & 0 deletions packages/aws-cdk/test/integ/cli/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,34 @@ class OtherParameterStack extends cdk.Stack {
}
}

class OutputsStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

const topic = new sns.Topic(this, 'MyOutput', {
topicName: 'MyTopic'
});

new cdk.CfnOutput(this, 'TopicName', {
value: topic.topicName
})
}
}

class AnotherOutputsStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

const topic = new sns.Topic(this, 'MyOtherOutput', {
topicName: 'MyOtherTopic'
});

new cdk.CfnOutput(this, 'TopicName', {
value: topic.topicName
});
}
}

class IamStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);
Expand Down Expand Up @@ -208,6 +236,9 @@ new YourStack(app, `${stackPrefix}-test-2`);
// Deploy wildcard with parameters does ${stackPrefix}-param-test-*
new ParameterStack(app, `${stackPrefix}-param-test-1`);
new OtherParameterStack(app, `${stackPrefix}-param-test-2`);
// Deploy stack with outputs does ${stackPrefix}-outputs-test-*
new OutputsStack(app, `${stackPrefix}-outputs-test-1`);
new AnotherOutputsStack(app, `${stackPrefix}-outputs-test-2`);
// Not included in wildcard
new IamStack(app, `${stackPrefix}-iam-test`);
const providing = new ProvidingStack(app, `${stackPrefix}-order-providing`);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"cdk-toolkit-integration-outputs-test-1": {
"TopicName": "MyTopic"
},
"cdk-toolkit-integration-outputs-test-2": {
"TopicName": "MyOtherTopic"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"cdk-toolkit-integration-outputs-test-1": {
"TopicName": "MyTopic"
}
}
2 changes: 2 additions & 0 deletions packages/aws-cdk/test/integ/cli/common.bash
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ function cleanup() {
cleanup_stack ${STACK_NAME_PREFIX}-test-2
cleanup_stack ${STACK_NAME_PREFIX}-iam-test
cleanup_stack ${STACK_NAME_PREFIX}-with-nested-stack
cleanup_stack ${STACK_NAME_PREFIX}-outputs-test-1
cleanup_stack ${STACK_NAME_PREFIX}-outputs-test-2
}

function setup() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash
set -euo pipefail
scriptdir=$(cd $(dirname $0) && pwd)
source ${scriptdir}/common.bash
# ----------------------------------------------------------

setup

outputs_file=${integ_test_dir}/outputs/outputs.json
expected_outputs=${scriptdir}/cdk-deploy-wildcard-with-outputs-expected.json

# deploy all outputs stacks
cdk deploy ${STACK_NAME_PREFIX}-outputs-test-\* --outputs-file ${outputs_file}
echo "Stacks deployed successfully"

# verify generated outputs file
generated_outputs_file="$(cat ${outputs_file})"
expected_outputs_file="$(cat ${expected_outputs})"
if [[ "${generated_outputs_file}" != "${expected_outputs_file}" ]]; then
fail "unexpected outputs. Expected: ${expected_outputs_file} Actual: ${generated_outputs_file}"
fi

# destroy
rm ${outputs_file}
cdk destroy -f ${STACK_NAME_PREFIX}-outputs-test-1
cdk destroy -f ${STACK_NAME_PREFIX}-outputs-test-2

echo "✅ success"
26 changes: 26 additions & 0 deletions packages/aws-cdk/test/integ/cli/test-cdk-deploy-with-outputs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash
set -euo pipefail
scriptdir=$(cd $(dirname $0) && pwd)
source ${scriptdir}/common.bash
# ----------------------------------------------------------

setup

outputs_file=${integ_test_dir}/outputs/outputs.json
expected_outputs=${scriptdir}/cdk-deploy-with-outputs-expected.json

cdk deploy -v ${STACK_NAME_PREFIX}-outputs-test-1 --outputs-file ${outputs_file}
echo "Stack deployed successfully"

# verify generated outputs file
generated_outputs_file="$(cat ${outputs_file})"
expected_outputs_file="$(cat ${expected_outputs})"
if [[ "${generated_outputs_file}" != "${expected_outputs_file}" ]]; then
fail "unexpected outputs. Expected: ${expected_outputs_file} Actual: ${generated_outputs_file}"
fi

# destroy
rm ${outputs_file}
cdk destroy -f ${STACK_NAME_PREFIX}-outputs-test-1

echo "✅ success"
2 changes: 2 additions & 0 deletions packages/aws-cdk/test/integ/cli/test-cdk-ls.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ ${STACK_NAME_PREFIX}-iam-test
${STACK_NAME_PREFIX}-lambda
${STACK_NAME_PREFIX}-missing-ssm-parameter
${STACK_NAME_PREFIX}-order-providing
${STACK_NAME_PREFIX}-outputs-test-1
shivlaks marked this conversation as resolved.
Show resolved Hide resolved
${STACK_NAME_PREFIX}-outputs-test-2
${STACK_NAME_PREFIX}-param-test-1
${STACK_NAME_PREFIX}-param-test-2
${STACK_NAME_PREFIX}-test-1
Expand Down