Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
11 changes: 5 additions & 6 deletions packages/aws-cdk/lib/api/deployments/cloudformation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { AssetManifestBuilder } from './asset-manifest-builder';
import type { Deployments } from './deployments';
import { ToolkitError } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api';
import type { IoHelper } from '../../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private';
import { debug } from '../../cli/messages';
import { debug, info } from '../../cli/messages';
import { formatErrorMessage, deserializeStructure } from '../../util';
import type { ICloudFormationClient, SdkProvider } from '../aws-auth';
import { StackStatus } from '../stack-events';
Expand Down Expand Up @@ -330,7 +330,6 @@ export type PrepareChangeSetOptions = {
uuid: string;
willExecute: boolean;
sdkProvider: SdkProvider;
stream: NodeJS.WritableStream;
parameters: { [name: string]: string | undefined };
resourcesToImport?: ResourcesToImport;
}
Expand Down Expand Up @@ -413,9 +412,9 @@ async function uploadBodyParameterAndCreateChangeSet(
const exists = (await CloudFormationStack.lookup(cfn, options.stack.stackName, false)).exists;

const executionRoleArn = await env.replacePlaceholders(options.stack.cloudFormationExecutionRoleArn);
options.stream.write(
ioHelper.notify(info(
'Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)\n',
);
));

return await createChangeSet(ioHelper, {
cfn,
Expand All @@ -431,9 +430,9 @@ async function uploadBodyParameterAndCreateChangeSet(
});
} catch (e: any) {
await ioHelper.notify(debug(e));
options.stream.write(
ioHelper.notify(info(
'Could not create a change set, will base the diff on template differences (run again with -v to see the reason)\n',
);
));

return undefined;
}
Expand Down
39 changes: 18 additions & 21 deletions packages/aws-cdk/lib/cli/cdk-toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ 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;
Expand All @@ -196,9 +195,14 @@ export class CdkToolkit {
}

const template = deserializeStructure(await fs.readFile(options.templatePath, { encoding: 'UTF-8' }));
diffs = options.securityOnly
? numberFromBool(printSecurityDiff(template, stacks.firstStack, RequireApproval.Broadening, quiet))
: printStackDiff(template, stacks.firstStack, strict, contextLines, quiet, undefined, undefined, false, stream);

if (options.securityOnly) {
diffs = numberFromBool(printSecurityDiff(template, stacks.firstStack, RequireApproval.Broadening, quiet));
} else {
const { stackDiffCount, printableStackDiff } = printStackDiff(template, stacks.firstStack, strict, contextLines, quiet, undefined, undefined, false);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd strongly advise you rename these functions since they don't print anything anymore.

diffs = stackDiffCount;
info(printableStackDiff);
}
} else {
// Compare N stacks against deployed templates
for (const stack of stacks.stackArtifacts) {
Expand Down Expand Up @@ -231,7 +235,7 @@ export class CdkToolkit {
} catch (e: any) {
debug(formatErrorMessage(e));
if (!quiet) {
stream.write(
info(
`Checking if the stack ${stack.stackName} exists before creating the changeset has failed, will base the diff on template differences (run again with -v to see the reason)\n`,
);
}
Expand All @@ -247,7 +251,6 @@ export class CdkToolkit {
sdkProvider: this.props.sdkProvider,
parameters: Object.assign({}, parameterMap['*'], parameterMap[stack.stackName]),
resourcesToImport,
stream,
});
} else {
debug(
Expand All @@ -256,8 +259,8 @@ export class CdkToolkit {
}
}

const stackCount = options.securityOnly
? numberFromBool(
if (options.securityOnly) {
diffs += numberFromBool(
printSecurityDiff(
currentTemplate,
stack,
Expand All @@ -266,8 +269,9 @@ export class CdkToolkit {
stack.displayName,
changeSet,
),
)
: printStackDiff(
);
} else {
const { stackDiffCount, printableStackDiff } = printStackDiff(
currentTemplate,
stack,
strict,
Expand All @@ -276,15 +280,15 @@ export class CdkToolkit {
stack.displayName,
changeSet,
!!resourcesToImport,
stream,
nestedStacks,
);

diffs += stackCount;
info(printableStackDiff);
diffs += stackDiffCount;
}
}
}

stream.write(format('\n✨ Number of stacks with differences: %s\n', diffs));
info(format('\n✨ Number of stacks with differences: %s\n', diffs));

return diffs && options.fail ? 1 : 0;
}
Expand Down Expand Up @@ -1360,13 +1364,6 @@ export interface DiffOptions {
*/
contextLines?: number;

/**
* Where to write the default
*
* @default stderr
*/
stream?: NodeJS.WritableStream;

/**
* Whether to fail with exit code 1 in case of diff
*
Expand Down
1 change: 0 additions & 1 deletion packages/aws-cdk/lib/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,6 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise<n
contextLines: args.contextLines,
securityOnly: args.securityOnly,
fail: args.fail != null ? args.fail : !enableDiffNoFail,
stream: args.ci ? process.stdout : undefined,
compareAgainstProcessedTemplate: args.processed,
quiet: args.quiet,
changeSet: args['change-set'],
Expand Down
37 changes: 32 additions & 5 deletions packages/aws-cdk/lib/commands/diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,25 @@ import * as chalk from 'chalk';
import { ToolkitError } from '../../../@aws-cdk/tmp-toolkit-helpers/src/api';
import { type NestedStackTemplates } from '../api/deployments';
import { info, warning } from '../logging';
import { Writable } from 'stream';

// Custom writable stream that collects text into a string buffer
class StringWriteStream extends Writable {
private buffer: string[] = [];

constructor() {
super();
}

_write(chunk: any, _encoding: string, callback: (error?: Error | null) => void): void {
this.buffer.push(chunk.toString());
callback();
}

toString(): string {
return this.buffer.join('');
}
}

/**
* Pretty-prints the differences between two template states to the console.
Expand All @@ -35,10 +54,11 @@ export function printStackDiff(
stackName?: string,
changeSet?: DescribeChangeSetOutput,
isImport?: boolean,
stream: FormatStream = process.stderr,
nestedStackTemplates?: { [nestedStackLogicalId: string]: NestedStackTemplates }): number {
nestedStackTemplates?: { [nestedStackLogicalId: string]: NestedStackTemplates }): { stackDiffCount: number, printableStackDiff: string } {
let diff = fullDiff(oldTemplate, newTemplate.template, changeSet, isImport);

const stream = new StringWriteStream();

// must output the stack name if there are differences, even if quiet
if (stackName && (!quiet || !diff.isEmpty)) {
stream.write(format('Stack %s\n', chalk.bold(stackName)));
Expand Down Expand Up @@ -66,12 +86,18 @@ export function printStackDiff(
}

let stackDiffCount = 0;
let printableStackDiff = '';
if (!diff.isEmpty) {
stackDiffCount++;

// formatDifferences updates the stream with the formatted stack diff
formatDifferences(stream, diff, {
...logicalIdMapFromTemplate(oldTemplate),
...buildLogicalToPathMap(newTemplate),
}, context);

// store the stream containing a formatted stack diff
printableStackDiff = stream.toString();
} else if (!quiet) {
info(chalk.green('There were no differences'));
}
Expand All @@ -86,7 +112,7 @@ export function printStackDiff(
const nestedStack = nestedStackTemplates[nestedStackLogicalId];

(newTemplate as any)._template = nestedStack.generatedTemplate;
stackDiffCount += printStackDiff(
const { stackDiffCount: newSackDiffCount, printableStackDiff: newPrintableStackDiff } = printStackDiff(
nestedStack.deployedTemplate,
newTemplate,
strict,
Expand All @@ -95,12 +121,13 @@ export function printStackDiff(
nestedStack.physicalName ?? nestedStackLogicalId,
undefined,
isImport,
stream,
nestedStack.nestedStackTemplates,
);
stackDiffCount += newSackDiffCount;
printableStackDiff += newPrintableStackDiff;
}

return stackDiffCount;
return { stackDiffCount, printableStackDiff };
}

export enum RequireApproval {
Expand Down
Loading
Loading