Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 2 additions & 1 deletion packages/@aws-cdk/toolkit-lib/docs/message-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ Please let us know by [opening an issue](https://github.com/aws/aws-cdk-cli/issu
| `CDK_TOOLKIT_I3110` | Additional information is needed to identify a resource | `info` | {@link ResourceIdentificationRequest} |
| `CDK_TOOLKIT_E3900` | Resource import failed | `error` | {@link ErrorPayload} |
| `CDK_TOOLKIT_I4000` | Diff stacks is starting | `trace` | {@link StackSelectionDetails} |
| `CDK_TOOLKIT_I4001` | Output of the diff command | `info` | {@link DiffResult} |
| `CDK_TOOLKIT_I4001` | Output of the diff command | `result` | {@link DiffResult} |
| `CDK_TOOLKIT_I4002` | The diff for a single stack | `result` | {@link StackDiff} |
| `CDK_TOOLKIT_I4590` | Results of the drift command | `result` | {@link DriftResultPayload} |
| `CDK_TOOLKIT_I4591` | Missing drift result fort a stack. | `warn` | {@link SingleStack} |
| `CDK_TOOLKIT_I5000` | Provides deployment times | `info` | {@link Duration} |
Expand Down
11 changes: 1 addition & 10 deletions packages/@aws-cdk/toolkit-lib/lib/actions/diff/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export class DiffMethod {
}

/**
* Optins for the diff method
* Options for the diff method
*/
export interface DiffOptions {
/**
Expand Down Expand Up @@ -129,13 +129,4 @@ export interface DiffOptions {
* @default 3
*/
readonly contextLines?: number;

/**
* Only include broadened security changes in the diff
*
* @default false
*
* @deprecated implement in IoHost
*/
readonly securityOnly?: boolean;
}
14 changes: 7 additions & 7 deletions packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ interface FormatStackDiffOptions {
*
* @default 3
*/
readonly context?: number;
readonly contextLines?: number;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This just makes the calling a little nicer.


/**
* silences \'There were no differences\' messages
Expand Down Expand Up @@ -130,7 +130,7 @@ export interface TemplateInfo {
export class DiffFormatter {
private readonly oldTemplate: any;
private readonly newTemplate: cxapi.CloudFormationStackArtifact;
private readonly stackName: string;
public readonly stackName: string;
private readonly changeSet?: any;
private readonly nestedStacks: { [nestedStackLogicalId: string]: NestedStackTemplates } | undefined;
private readonly isImport: boolean;
Expand All @@ -157,7 +157,7 @@ export class DiffFormatter {
/**
* Get or creates the diff of a stack.
* If it creates the diff, it stores the result in a map for
* easier retreval later.
* easier retrieval later.
*/
private diff(stackName?: string, oldTemplate?: any) {
const realStackName = stackName ?? this.stackName;
Expand All @@ -178,8 +178,8 @@ export class DiffFormatter {
*
* If no stackName is given, then the root stack name is used.
*/
private permissionType(stackName?: string): PermissionChangeType {
const diff = this.diff(stackName);
private permissionType(): PermissionChangeType {
const diff = this.diff();
Comment on lines +181 to +182
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cleanup. permissionType is never called with a stackName. Let's not pretend it should.


if (diff.permissionsBroadened) {
return PermissionChangeType.BROADENING;
Expand Down Expand Up @@ -211,7 +211,7 @@ export class DiffFormatter {
let diff = this.diff(stackName, oldTemplate);

// The stack diff is formatted via `Formatter`, which takes in a stream
// and sends its output directly to that stream. To faciliate use of the
// and sends its output directly to that stream. To facilitate use of the
// global CliIoHost, we create our own stream to capture the output of
// `Formatter` and return the output as a string for the consumer of
// `formatStackDiff` to decide what to do with it.
Expand Down Expand Up @@ -253,7 +253,7 @@ export class DiffFormatter {
formatDifferences(stream, diff, {
...logicalIdMapFromTemplate(this.oldTemplate),
...buildLogicalToPathMap(this.newTemplate),
}, options.context);
}, options.contextLines);
} else if (!options.quiet) {
stream.write(chalk.green('There were no differences\n'));
}
Expand Down
9 changes: 7 additions & 2 deletions packages/@aws-cdk/toolkit-lib/lib/api/io/private/messages.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type * as cxapi from '@aws-cdk/cx-api';
import * as make from './message-maker';
import type { SpanDefinition } from './span';
import type { DiffResult } from '../../../payloads';
import type { StackDiff, DiffResult } from '../../../payloads';
import type { BootstrapEnvironmentProgress } from '../../../payloads/bootstrap-environment-progress';
import type { MissingContext, UpdatedContext } from '../../../payloads/context';
import type { BuildAsset, DeployConfirmationRequest, PublishAsset, StackDeployProgress, SuccessfulDeployStackResult } from '../../../payloads/deploy';
Expand Down Expand Up @@ -85,11 +85,16 @@ export const IO = {
description: 'Diff stacks is starting',
interface: 'StackSelectionDetails',
}),
CDK_TOOLKIT_I4001: make.info<DiffResult>({
CDK_TOOLKIT_I4001: make.result<DiffResult>({
code: 'CDK_TOOLKIT_I4001',
description: 'Output of the diff command',
interface: 'DiffResult',
}),
CDK_TOOLKIT_I4002: make.result<StackDiff>({
code: 'CDK_TOOLKIT_I4002',
description: 'The diff for a single stack',
interface: 'StackDiff',
}),

// 4: Drift (45xx - 49xx)
CDK_TOOLKIT_I4590: make.result<DriftResultPayload>({
Expand Down
53 changes: 47 additions & 6 deletions packages/@aws-cdk/toolkit-lib/lib/payloads/diff.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Duration } from './types';
import type { ITemplateDiff } from '@aws-cdk/cloudformation-diff';
import type { Duration, SingleStack } from './types';

/**
* Different types of permission related changes in a diff
Expand All @@ -20,17 +21,57 @@ export enum PermissionChangeType {
NON_BROADENING = 'non-broadening',
}

/**
* The diff formatted as different types of output
*/
export interface FormattedDiff {
/**
* The stack diff formatted as a string
*/
readonly diff: string;
/**
* The security diff formatted as a string, if any
*/
readonly security?: string;
}

/**
* Diff information for a single stack
*/
export interface StackDiff extends SingleStack {
/**
* Total number of stacks that have changes
* Can be higher than `1` if the stack has nested stacks.
*/
readonly numStacksWithChanges: number;

/**
* Structural diff of the stack
* Can include more than a single diff if the stack has nested stacks.
*/
readonly diffs: { [name: string]: ITemplateDiff };

/**
* The formatted diff
*/
readonly formattedDiff: FormattedDiff;

/**
* Does the diff contain changes to permissions and what kind
*/
readonly permissionChanges: PermissionChangeType;
}

/**
* Output of the diff command
*/
export interface DiffResult extends Duration {
/**
* Stack diff formatted as a string
* Total number of stacks that have changes
*/
readonly formattedStackDiff: string;

readonly numStacksWithChanges: number;
/**
* Security diff formatted as a string
* Structural diff of all selected stacks
*/
readonly formattedSecurityDiff: string;
readonly diffs: { [name: string]: ITemplateDiff };
}
48 changes: 25 additions & 23 deletions packages/@aws-cdk/toolkit-lib/lib/toolkit/toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,39 +339,41 @@ export class Toolkit extends CloudAssemblySourceBuilder {
const contextLines = options.contextLines || 3;

let diffs = 0;
let formattedSecurityDiff = '';
let formattedStackDiff = '';

const templateInfos = await prepareDiff(ioHelper, stacks, deployments, await this.sdkProvider('diff'), options);
const templateDiffs: { [name: string]: TemplateDiff } = {};
for (const templateInfo of templateInfos) {
const formatter = new DiffFormatter({
templateInfo,
});
const formatter = new DiffFormatter({ templateInfo });
const stackDiff = formatter.formatStackDiff({ strict, contextLines });

if (options.securityOnly) {
const securityDiff = formatter.formatSecurityDiff();
// In Diff, we only care about BROADENING security diffs
if (securityDiff.permissionChangeType == PermissionChangeType.BROADENING) {
const warningMessage = 'This deployment will make potentially sensitive changes according to your current security approval level.\nPlease confirm you intend to make the following modifications:\n';
await ioHelper.defaults.warn(warningMessage);
formattedSecurityDiff = securityDiff.formattedDiff;
diffs = securityDiff.formattedDiff ? diffs + 1 : diffs;
}
} else {
const diff = formatter.formatStackDiff({
strict,
context: contextLines,
});
formattedStackDiff = diff.formattedDiff;
diffs = diff.numStacksWithChanges;
// Security Diff
const securityDiff = formatter.formatSecurityDiff();
const formattedSecurityDiff = securityDiff.permissionChangeType !== PermissionChangeType.NONE ? stackDiff.formattedDiff : undefined;
// We only warn about BROADENING changes
if (securityDiff.permissionChangeType == PermissionChangeType.BROADENING) {
const warningMessage = 'This deployment will make potentially sensitive changes according to your current security approval level.\nPlease confirm you intend to make the following modifications:\n';
await diffSpan.notifyDefault('warn', warningMessage);
await diffSpan.notifyDefault('info', securityDiff.formattedDiff);
}

// Stack Diff
diffs += stackDiff.numStacksWithChanges;
appendObject(templateDiffs, formatter.diffs);
await diffSpan.notify(IO.CDK_TOOLKIT_I4002.msg(stackDiff.formattedDiff, {
stack: templateInfo.newTemplate,
diffs: formatter.diffs,
numStacksWithChanges: stackDiff.numStacksWithChanges,
permissionChanges: securityDiff.permissionChangeType,
formattedDiff: {
diff: stackDiff.formattedDiff,
security: formattedSecurityDiff,
},
}));
}

await diffSpan.end(`✨ Number of stacks with differences: ${diffs}`, {
formattedSecurityDiff,
formattedStackDiff,
numStacksWithChanges: diffs,
diffs: templateDiffs,
});

return templateDiffs;
Expand Down
38 changes: 17 additions & 21 deletions packages/@aws-cdk/toolkit-lib/test/actions/diff.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,14 @@ describe('diff', () => {
// THEN
expect(ioHost.notifySpy).toHaveBeenCalledWith(expect.objectContaining({
action: 'diff',
level: 'info',
level: 'result',
code: 'CDK_TOOLKIT_I4001',
message: expect.stringContaining('✨ Number of stacks with differences: 1'),
data: expect.objectContaining({
formattedStackDiff: expect.stringContaining((chalk.bold('Stack1'))),
numStacksWithChanges: 1,
diffs: expect.objectContaining({
Stack1: expect.anything(),
}),
}),
}));
});
Expand Down Expand Up @@ -131,12 +134,11 @@ describe('diff', () => {
}));
});

test('only security diff', async () => {
test('security diff', async () => {
// WHEN
const cx = await builderFixture(toolkit, 'stack-with-role');
const result = await toolkit.diff(cx, {
stacks: { strategy: StackSelectionStrategy.PATTERN_MUST_MATCH_SINGLE, patterns: ['Stack1'] },
securityOnly: true,
method: DiffMethod.TemplateOnly({ compareAgainstProcessedTemplate: true }),
});

Expand All @@ -148,11 +150,12 @@ describe('diff', () => {
}));
expect(ioHost.notifySpy).toHaveBeenCalledWith(expect.objectContaining({
action: 'diff',
level: 'info',
code: 'CDK_TOOLKIT_I4001',
message: expect.stringContaining('✨ Number of stacks with differences: 1'),
level: 'result',
code: 'CDK_TOOLKIT_I4002',
data: expect.objectContaining({
formattedSecurityDiff: expect.stringContaining((chalk.underline(chalk.bold('IAM Statement Changes')))),
formattedDiff: expect.objectContaining({
security: expect.stringContaining((chalk.underline(chalk.bold('IAM Statement Changes')))),
}),
}),
}));

Expand Down Expand Up @@ -182,17 +185,17 @@ describe('diff', () => {
const cx = await builderFixture(toolkit, 'two-empty-stacks');
await toolkit.diff(cx, {
stacks: { strategy: StackSelectionStrategy.ALL_STACKS },
securityOnly: true,
});

// THEN
expect(ioHost.notifySpy).toHaveBeenCalledWith(expect.objectContaining({
action: 'diff',
level: 'info',
code: 'CDK_TOOLKIT_I4001',
message: expect.stringContaining('✨ Number of stacks with differences: 0'),
level: 'result',
code: 'CDK_TOOLKIT_I4002',
data: expect.objectContaining({
formattedSecurityDiff: '',
formattedDiff: expect.objectContaining({
security: undefined,
}),
}),
}));
});
Expand All @@ -207,19 +210,13 @@ describe('diff', () => {

// THEN
expect(ioHost.notifySpy).not.toHaveBeenCalledWith(expect.objectContaining({
action: 'diff',
level: 'info',
code: 'CDK_TOOLKIT_I0000',
message: expect.stringContaining('Could not create a change set'),
}));
expect(ioHost.notifySpy).toHaveBeenCalledWith(expect.objectContaining({
action: 'diff',
level: 'info',
level: 'result',
code: 'CDK_TOOLKIT_I4001',
message: expect.stringContaining('✨ Number of stacks with differences: 1'),
data: expect.objectContaining({
formattedStackDiff: expect.stringContaining(chalk.bold('Stack1')),
}),
}));
});

Expand Down Expand Up @@ -344,7 +341,6 @@ describe('diff', () => {
const cx = await builderFixture(toolkit, 'stack-with-role');
const result = await toolkit.diff(cx, {
stacks: { strategy: StackSelectionStrategy.ALL_STACKS },
securityOnly: true,
method: DiffMethod.LocalFile(path.join(__dirname, '..', '_fixtures', 'two-empty-stacks', 'cdk.out', 'Stack1.template.json')),
});

Expand Down
4 changes: 2 additions & 2 deletions packages/aws-cdk/lib/cli/cdk-toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ export class CdkToolkit {
} else {
const diff = formatter.formatStackDiff({
strict,
context: contextLines,
contextLines,
quiet,
});
diffs = diff.numStacksWithChanges;
Expand Down Expand Up @@ -325,7 +325,7 @@ export class CdkToolkit {
} else {
const diff = formatter.formatStackDiff({
strict,
context: contextLines,
contextLines,
quiet,
});
info(diff.formattedDiff);
Expand Down
Loading