diff --git a/packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts b/packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts index 4bf1d29f57570..76f7f161f892d 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts @@ -46,6 +46,7 @@ export function fullDiff( currentTemplate: { [key: string]: any }, newTemplate: { [key: string]: any }, changeSet?: CloudFormation.DescribeChangeSetOutput, + isImport?: boolean, ): types.TemplateDiff { normalize(currentTemplate); @@ -54,6 +55,8 @@ export function fullDiff( if (changeSet) { filterFalsePositives(theDiff, changeSet); addImportInformation(theDiff, changeSet); + } else if (isImport) { + makeAllResourceChangesImports(theDiff); } return theDiff; @@ -218,6 +221,12 @@ function addImportInformation(diff: types.TemplateDiff, changeSet: CloudFormatio }); } +function makeAllResourceChangesImports(diff: types.TemplateDiff) { + diff.resources.forEachDifference((_logicalId: string, change: types.ResourceDifference) => { + change.isImport = true; + }); +} + function filterFalsePositives(diff: types.TemplateDiff, changeSet: CloudFormation.DescribeChangeSetOutput) { const replacements = findResourceReplacements(changeSet); diff.resources.forEachDifference((logicalId: string, change: types.ResourceDifference) => { diff --git a/packages/aws-cdk/lib/api/util/cloudformation.ts b/packages/aws-cdk/lib/api/util/cloudformation.ts index b61991bf51699..3176b88ab621b 100644 --- a/packages/aws-cdk/lib/api/util/cloudformation.ts +++ b/packages/aws-cdk/lib/api/util/cloudformation.ts @@ -364,7 +364,7 @@ async function uploadBodyParameterAndCreateChangeSet(options: PrepareChangeSetOp } async function createChangeSet(options: CreateChangeSetOptions): Promise { - await cleanupOldChangeset(options.exists, options.changeSetName, options.stack.stackName, options.cfn); + await cleanupOldChangeset(options.changeSetName, options.stack.stackName, options.cfn); debug(`Attempting to create ChangeSet with name ${options.changeSetName} for stack ${options.stack.stackName}`); @@ -388,23 +388,16 @@ async function createChangeSet(options: CreateChangeSetOptions): Promise { fs.rmSync('migrate.json'); }); - test('imports', async () => { + test('imports render correctly for a nonexistant stack without creating a changeset', async () => { // GIVEN const buffer = new StringWritable(); + cloudFormation.stackExists = jest.fn().mockReturnValue(Promise.resolve(false)); // WHEN const exitCode = await toolkit.diff({ @@ -107,6 +108,34 @@ describe('imports', () => { // THEN const plainTextOutput = buffer.data.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, ''); + expect(cfn.createDiffChangeSet).not.toHaveBeenCalled(); + expect(plainTextOutput).toContain(`Stack A +Parameters and rules created during migration do not affect resource configuration. +Resources +[←] AWS::SQS::Queue Queue import +[←] AWS::SQS::Queue Queue2 import +[←] AWS::S3::Bucket Bucket import +`); + + expect(buffer.data.trim()).toContain('✨ Number of stacks with differences: 1'); + expect(exitCode).toBe(0); + }); + + test('imports render correctly for an existing stack and diff creates a changeset', async () => { + // GIVEN + const buffer = new StringWritable(); + cloudFormation.stackExists = jest.fn().mockReturnValue(Promise.resolve(true)); + + // WHEN + const exitCode = await toolkit.diff({ + stackNames: ['A'], + stream: buffer, + changeSet: true, + }); + + // THEN + const plainTextOutput = buffer.data.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, ''); + expect(cfn.createDiffChangeSet).toHaveBeenCalled(); expect(plainTextOutput).toContain(`Stack A Parameters and rules created during migration do not affect resource configuration. Resources @@ -306,6 +335,24 @@ describe('non-nested stacks', () => { expect(buffer.data.trim()).not.toContain('There were no differences'); expect(exitCode).toBe(0); }); + + test('diff does not check for stack existence when --no-changeset is passed', async () => { + // GIVEN + const buffer = new StringWritable(); + + // WHEN + const exitCode = await toolkit.diff({ + stackNames: ['A', 'A'], + stream: buffer, + fail: false, + quiet: true, + changeSet: false, + }); + + // THEN + expect(exitCode).toBe(0); + expect(cloudFormation.stackExists).not.toHaveBeenCalled(); + }); }); describe('nested stacks', () => {