Skip to content

Commit

Permalink
feat(cdk): cdk diff --quiet suppresses progress messages (#26652)
Browse files Browse the repository at this point in the history
Hello maintainers

This is my first PR, so all feedback is welcome. This change adds support for the `--quiet` flag within cdk diff command, for users that would not like the following messages 'Stack <name>' and 'There were no differences' to be silenced for stacks which do not have *any* identified differences. The request was made by @nomike in the #26526, I simply followed the very well detailed description.

The change follows similar structure to existing command and how they are passed, I have also added to the README as per the contributing guidelines.

Before submitting I have.
- Built the packages & linted them
- Ran unit tests for the entire module
- Ran all integration tests in the suite from `@aws-cdk-testing/cli-integ/bin/run-suite -a cli-integ-tests` 
- E2E tested by launching my small stack in account and executing diffs on it from my build.

Closes #26526

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
MatasNed authored Aug 10, 2023
1 parent cc52e2d commit 5777c88
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,18 @@ integTest('cdk diff --security-only --fail exits when security changes are prese
await expect(fixture.cdk(['diff', '--security-only', '--fail', fixture.fullStackName(stackName)])).rejects.toThrow('exited with error');
}));

integTest('cdk diff --quiet does not print \'There were no differences\' message for stacks which have no differences', withDefaultFixture(async (fixture) => {
// GIVEN
await fixture.cdkDeploy('test-1');

// WHEN
const diff = await fixture.cdk(['diff', '--quiet', fixture.fullStackName('test-1')]);

// THEN
expect(diff).not.toContain('Stack test-1');
expect(diff).not.toContain('There were no differences');
}));

integTest('deploy stack with docker asset', withDefaultFixture(async (fixture) => {
await fixture.cdkDeploy('docker');
}));
Expand Down
7 changes: 7 additions & 0 deletions packages/aws-cdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,13 @@ $ # Diff against a specific template document
$ cdk diff --app='node bin/main.js' MyStackName --template=path/to/template.yml
```

The `quiet` flag can also be passed to the `cdk diff` command. Assuming there are no differences detected the output to the console will **not** contain strings such as the *Stack* `MyStackName` and `There were no differences`.

```console
$ # Diff against the currently deployed stack with quiet parameter enabled
$ cdk diff --quiet --app='node bin/main.js' MyStackName
```

### `cdk deploy`

Deploys a stack of your CDK app to its environment. During the deployment, the toolkit will output progress
Expand Down
17 changes: 14 additions & 3 deletions packages/aws-cdk/lib/cdk-toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ export class CdkToolkit {
const strict = !!options.strict;
const contextLines = options.contextLines || 3;
const stream = options.stream || process.stderr;
const quiet = options.quiet || false;

let diffs = 0;
if (options.templatePath !== undefined) {
Expand All @@ -131,15 +132,18 @@ export class CdkToolkit {
const template = deserializeStructure(await fs.readFile(options.templatePath, { encoding: 'UTF-8' }));
diffs = options.securityOnly
? numberFromBool(printSecurityDiff(template, stacks.firstStack, RequireApproval.Broadening))
: printStackDiff(template, stacks.firstStack, strict, contextLines, stream);
: printStackDiff(template, stacks.firstStack, strict, contextLines, quiet, stream);
} else {
// Compare N stacks against deployed templates
for (const stack of stacks.stackArtifacts) {
stream.write(format('Stack %s\n', chalk.bold(stack.displayName)));
if (!quiet) {
stream.write(format('Stack %s\n', chalk.bold(stack.displayName)));
}

const currentTemplate = await this.props.deployments.readCurrentTemplateWithNestedStacks(stack, options.compareAgainstProcessedTemplate);
diffs += options.securityOnly
? numberFromBool(printSecurityDiff(currentTemplate, stack, RequireApproval.Broadening))
: printStackDiff(currentTemplate, stack, strict, contextLines, stream);
: printStackDiff(currentTemplate, stack, strict, contextLines, quiet, stream);
}
}

Expand Down Expand Up @@ -890,6 +894,13 @@ export interface DiffOptions {
* @default false
*/
compareAgainstProcessedTemplate?: boolean;

/*
* Run diff in quiet mode without printing the diff statuses
*
* @default false
*/
quiet?: boolean;
}

interface CfnDeployOptions {
Expand Down
4 changes: 3 additions & 1 deletion packages/aws-cdk/lib/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ async function parseCommandLineArguments(args: string[]) {
.option('strict', { type: 'boolean', desc: 'Do not filter out AWS::CDK::Metadata resources or mangled non-ASCII characters', default: false })
.option('security-only', { type: 'boolean', desc: 'Only diff for broadened security changes', default: false })
.option('fail', { type: 'boolean', desc: 'Fail with exit code 1 in case of diff' })
.option('processed', { type: 'boolean', desc: 'Whether to compare against the template with Transforms already processed', default: false }))
.option('processed', { type: 'boolean', desc: 'Whether to compare against the template with Transforms already processed', default: false })
.option('quiet', { type: 'boolean', alias: 'q', desc: 'Do not print stack name and default message when there is no diff to stdout', default: false }))
.command('metadata [STACK]', 'Returns all metadata associated with this stack')
.command(['acknowledge [ID]', 'ack [ID]'], 'Acknowledge a notice so that it does not show up anymore')
.command('notices', 'Returns a list of relevant notices')
Expand Down Expand Up @@ -489,6 +490,7 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise<n
fail: args.fail != null ? args.fail : !enableDiffNoFail,
stream: args.ci ? process.stdout : undefined,
compareAgainstProcessedTemplate: args.processed,
quiet: args.quiet,
});

case 'bootstrap':
Expand Down
4 changes: 3 additions & 1 deletion packages/aws-cdk/lib/diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { print, warning } from './logging';
* @param newTemplate the new/target state of the stack.
* @param strict do not filter out AWS::CDK::Metadata
* @param context lines of context to use in arbitrary JSON diff
* @param quiet silences \'There were no differences\' messages
*
* @returns the count of differences that were rendered.
*/
Expand All @@ -19,6 +20,7 @@ export function printStackDiff(
newTemplate: cxapi.CloudFormationStackArtifact,
strict: boolean,
context: number,
quiet: boolean,
stream?: cfnDiff.FormatStream): number {

let diff = cfnDiff.diffTemplate(oldTemplate, newTemplate.template);
Expand Down Expand Up @@ -49,7 +51,7 @@ export function printStackDiff(
...logicalIdMapFromTemplate(oldTemplate),
...buildLogicalToPathMap(newTemplate),
}, context);
} else {
} else if (!quiet) {
print(chalk.green('There were no differences'));
}
if (filteredChangesCount > 0) {
Expand Down
18 changes: 18 additions & 0 deletions packages/aws-cdk/test/diff.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,24 @@ describe('non-nested stacks', () => {
stream: buffer,
})).rejects.toThrow(/Found errors/);
});

test('when quiet mode is enabled, stacks with no diffs should not print stack name & no differences to stdout', async () => {
// GIVEN
const buffer = new StringWritable();

// WHEN
const exitCode = await toolkit.diff({
stackNames: ['A', 'A'],
stream: buffer,
fail: false,
quiet: true,
});

// THEN
expect(buffer.data.trim()).not.toContain('Stack A');
expect(buffer.data.trim()).not.toContain('There were no differences');
expect(exitCode).toBe(0);
});
});

describe('nested stacks', () => {
Expand Down

0 comments on commit 5777c88

Please sign in to comment.