|
1 | 1 | import { promises as fs, existsSync } from 'fs'; |
2 | 2 | import * as os from 'os'; |
3 | 3 | import * as path from 'path'; |
4 | | -import { integTest, cloneDirectory, shell, withDefaultFixture, retry, sleep, randomInteger, withSamIntegrationFixture, RESOURCES_DIR, withCDKMigrateFixture, withExtendedTimeoutFixture } from '../../lib'; |
| 4 | +import { integTest, cloneDirectory, shell, withDefaultFixture, retry, sleep, randomInteger, withSamIntegrationFixture, RESOURCES_DIR, withCDKMigrateFixture, withExtendedTimeoutFixture, randomString } from '../../lib'; |
5 | 5 |
|
6 | 6 | jest.setTimeout(2 * 60 * 60_000); // Includes the time to acquire locks, worst-case single-threaded runtime |
7 | 7 |
|
@@ -1575,37 +1575,60 @@ integTest('skips notice refresh', withDefaultFixture(async (fixture) => { |
1575 | 1575 | })); |
1576 | 1576 |
|
1577 | 1577 | /** |
1578 | | - * Create a queue with a fresh name, redeploy orphaning the queue, then import it again |
| 1578 | + * Create a queue, orphan that queue, then import the queue. |
| 1579 | + * |
| 1580 | + * We want to test with a large template to make sure large templates can work with import. |
1579 | 1581 | */ |
1580 | 1582 | integTest('test resource import', withDefaultFixture(async (fixture) => { |
1581 | | - const outputsFile = path.join(fixture.integTestDir, 'outputs', 'outputs.json'); |
| 1583 | + // GIVEN |
| 1584 | + const randomPrefix = randomString(); |
| 1585 | + const uniqueOutputsFileName = `${randomPrefix}Outputs.json`; // other tests use the outputs file. Make sure we don't collide. |
| 1586 | + const outputsFile = path.join(fixture.integTestDir, 'outputs', uniqueOutputsFileName); |
1582 | 1587 | await fs.mkdir(path.dirname(outputsFile), { recursive: true }); |
1583 | 1588 |
|
1584 | | - // Initial deploy |
| 1589 | + // First, create a stack that includes many queues, and one queue that will be removed from the stack but NOT deleted from AWS. |
1585 | 1590 | await fixture.cdkDeploy('importable-stack', { |
1586 | | - modEnv: { ORPHAN_TOPIC: '1' }, |
| 1591 | + modEnv: { LARGE_TEMPLATE: '1', INCLUDE_SINGLE_QUEUE: '1', RETAIN_SINGLE_QUEUE: '1' }, |
1587 | 1592 | options: ['--outputs-file', outputsFile], |
1588 | 1593 | }); |
1589 | 1594 |
|
1590 | | - const outputs = JSON.parse((await fs.readFile(outputsFile, { encoding: 'utf-8' })).toString()); |
1591 | | - const queueName = outputs.QueueName; |
1592 | | - const queueLogicalId = outputs.QueueLogicalId; |
1593 | | - fixture.log(`Setup complete, created queue ${queueName}`); |
1594 | 1595 | try { |
1595 | | - // Deploy again, orphaning the queue |
| 1596 | + |
| 1597 | + // Second, now the queue we will remove is in the stack and has a logicalId. We can now make the resource mapping file. |
| 1598 | + // This resource mapping file will be used to tell the import operation what queue to bring into the stack. |
| 1599 | + const fullStackName = fixture.fullStackName('importable-stack'); |
| 1600 | + const outputs = JSON.parse((await fs.readFile(outputsFile, { encoding: 'utf-8' })).toString()); |
| 1601 | + const queueLogicalId = outputs[fullStackName].QueueLogicalId; |
| 1602 | + const queueResourceMap = { |
| 1603 | + [queueLogicalId]: { QueueUrl: outputs[fullStackName].QueueUrl }, |
| 1604 | + }; |
| 1605 | + const mappingFile = path.join(fixture.integTestDir, 'outputs', `${randomPrefix}Mapping.json`); |
| 1606 | + await fs.writeFile( |
| 1607 | + mappingFile, |
| 1608 | + JSON.stringify(queueResourceMap), |
| 1609 | + { encoding: 'utf-8' }, |
| 1610 | + ); |
| 1611 | + |
| 1612 | + // Third, remove the queue from the stack, but don't delete the queue from AWS. |
1596 | 1613 | await fixture.cdkDeploy('importable-stack', { |
1597 | | - modEnv: { OMIT_TOPIC: '1' }, |
| 1614 | + modEnv: { LARGE_TEMPLATE: '1', INCLUDE_SINGLE_QUEUE: '0', RETAIN_SINGLE_QUEUE: '0' }, |
1598 | 1615 | }); |
| 1616 | + const cfnTemplateBeforeImport = await fixture.aws.cloudFormation('getTemplate', { StackName: fullStackName }); |
| 1617 | + expect(cfnTemplateBeforeImport.TemplateBody).not.toContain(queueLogicalId); |
1599 | 1618 |
|
1600 | | - // Write a resource mapping file based on the ID from step one, then run an import |
1601 | | - const mappingFile = path.join(fixture.integTestDir, 'outputs', 'mapping.json'); |
1602 | | - await fs.writeFile(mappingFile, JSON.stringify({ [queueLogicalId]: { QueueName: queueName } }), { encoding: 'utf-8' }); |
| 1619 | + // WHEN |
| 1620 | + await fixture.cdk( |
| 1621 | + ['import', '--resource-mapping', mappingFile, fixture.fullStackName('importable-stack')], |
| 1622 | + { modEnv: { LARGE_TEMPLATE: '1', INCLUDE_SINGLE_QUEUE: '1', RETAIN_SINGLE_QUEUE: '0' } }, |
| 1623 | + ); |
1603 | 1624 |
|
1604 | | - await fixture.cdk(['import', |
1605 | | - '--resource-mapping', mappingFile, |
1606 | | - fixture.fullStackName('importable-stack')]); |
| 1625 | + // THEN |
| 1626 | + const describeStacksResponse = await fixture.aws.cloudFormation('describeStacks', { StackName: fullStackName }); |
| 1627 | + const cfnTemplateAfterImport = await fixture.aws.cloudFormation('getTemplate', { StackName: fullStackName }); |
| 1628 | + expect(describeStacksResponse.Stacks![0].StackStatus).toEqual('IMPORT_COMPLETE'); |
| 1629 | + expect(cfnTemplateAfterImport.TemplateBody).toContain(queueLogicalId); |
1607 | 1630 | } finally { |
1608 | | - // Cleanup |
| 1631 | + // Clean up |
1609 | 1632 | await fixture.cdkDestroy('importable-stack'); |
1610 | 1633 | } |
1611 | 1634 | })); |
|
0 commit comments