@@ -17,12 +17,10 @@ import {
17
17
resourceMappings ,
18
18
resourceMovements ,
19
19
} from '../../../lib/api/refactoring' ;
20
- import type {
21
- ResourceLocation ,
22
- ResourceMapping ,
23
- CloudFormationStack ,
24
- } from '../../../lib/api/refactoring/cloudformation' ;
20
+ import type { CloudFormationStack } from '../../../lib/api/refactoring/cloudformation' ;
21
+ import { ResourceLocation , ResourceMapping } from '../../../lib/api/refactoring/cloudformation' ;
25
22
import { computeResourceDigests } from '../../../lib/api/refactoring/digest' ;
23
+ import { generateStackDefinitions } from '../../../lib/api/refactoring/execution' ;
26
24
import { mockCloudFormationClient , MockSdkProvider } from '../../_helpers/mock-sdk' ;
27
25
28
26
const cloudFormationClient = mockCloudFormationClient ;
@@ -1380,6 +1378,316 @@ describe('environment grouping', () => {
1380
1378
} ) ;
1381
1379
} ) ;
1382
1380
1381
+ describe ( generateStackDefinitions , ( ) => {
1382
+ const environment = {
1383
+ name : 'test' ,
1384
+ account : '333333333333' ,
1385
+ region : 'us-east-1' ,
1386
+ } ;
1387
+
1388
+ test ( 'renames a resource within the same stack' , ( ) => {
1389
+ const stack : CloudFormationStack = {
1390
+ environment : environment ,
1391
+ stackName : 'Foo' ,
1392
+ template : {
1393
+ Resources : {
1394
+ Bucket1 : {
1395
+ Type : 'AWS::S3::Bucket' ,
1396
+ } ,
1397
+ NotInvolved : {
1398
+ Type : 'AWS::X::Y' ,
1399
+ } ,
1400
+ } ,
1401
+ } ,
1402
+ } ;
1403
+
1404
+ const mappings : ResourceMapping [ ] = [
1405
+ new ResourceMapping ( new ResourceLocation ( stack , 'Bucket1' ) , new ResourceLocation ( stack , 'Bucket2' ) ) ,
1406
+ ] ;
1407
+
1408
+ const result = generateStackDefinitions ( mappings , [ stack ] ) ;
1409
+ expect ( result ) . toEqual ( [
1410
+ {
1411
+ StackName : 'Foo' ,
1412
+ TemplateBody : JSON . stringify ( {
1413
+ Resources : {
1414
+ // Not involved in the refactor, but still part of the
1415
+ // original template. Should be included.
1416
+ NotInvolved : {
1417
+ Type : 'AWS::X::Y' ,
1418
+ } ,
1419
+ Bucket2 : {
1420
+ Type : 'AWS::S3::Bucket' ,
1421
+ } ,
1422
+ } ,
1423
+ } ) ,
1424
+ } ,
1425
+ ] ) ;
1426
+ } ) ;
1427
+
1428
+ test ( 'moves a resource to another stack that has already been deployed' , ( ) => {
1429
+ const stack1 : CloudFormationStack = {
1430
+ environment,
1431
+ stackName : 'Stack1' ,
1432
+ template : {
1433
+ Resources : {
1434
+ Bucket1 : {
1435
+ Type : 'AWS::S3::Bucket' ,
1436
+ } ,
1437
+ A : {
1438
+ Type : 'AWS::A::A' ,
1439
+ } ,
1440
+ } ,
1441
+ } ,
1442
+ } ;
1443
+
1444
+ const stack2 : CloudFormationStack = {
1445
+ environment,
1446
+ stackName : 'Stack2' ,
1447
+ template : {
1448
+ Resources : {
1449
+ B : {
1450
+ Type : 'AWS::B::B' ,
1451
+ } ,
1452
+ } ,
1453
+ } ,
1454
+ } ;
1455
+
1456
+ const mappings : ResourceMapping [ ] = [
1457
+ new ResourceMapping ( new ResourceLocation ( stack1 , 'Bucket1' ) , new ResourceLocation ( stack2 , 'Bucket2' ) ) ,
1458
+ ] ;
1459
+
1460
+ const result = generateStackDefinitions ( mappings , [ stack1 , stack2 ] ) ;
1461
+ expect ( result ) . toEqual ( [
1462
+ {
1463
+ StackName : 'Stack1' ,
1464
+ TemplateBody : JSON . stringify ( {
1465
+ Resources : {
1466
+ // Wasn't touched by the refactor
1467
+ A : {
1468
+ Type : 'AWS::A::A' ,
1469
+ } ,
1470
+
1471
+ // Bucket1 doesn't exist anymore
1472
+ } ,
1473
+ } ) ,
1474
+ } ,
1475
+ {
1476
+ StackName : 'Stack2' ,
1477
+ TemplateBody : JSON . stringify ( {
1478
+ Resources : {
1479
+ // Wasn't touched by the refactor
1480
+ B : {
1481
+ Type : 'AWS::B::B' ,
1482
+ } ,
1483
+
1484
+ // Old Bucket1 is now Bucket2 here
1485
+ Bucket2 : {
1486
+ Type : 'AWS::S3::Bucket' ,
1487
+ } ,
1488
+ } ,
1489
+ } ) ,
1490
+ } ,
1491
+ ] ) ;
1492
+ } ) ;
1493
+
1494
+ test ( 'moves a resource to another stack that has not been deployed' , ( ) => {
1495
+ const stack1 : CloudFormationStack = {
1496
+ environment,
1497
+ stackName : 'Stack1' ,
1498
+ template : {
1499
+ Resources : {
1500
+ Bucket1 : {
1501
+ Type : 'AWS::S3::Bucket' ,
1502
+ } ,
1503
+ A : {
1504
+ Type : 'AWS::A::A' ,
1505
+ } ,
1506
+ } ,
1507
+ } ,
1508
+ } ;
1509
+
1510
+ const stack2 : CloudFormationStack = {
1511
+ environment,
1512
+ stackName : 'Stack2' ,
1513
+ template : {
1514
+ Resources : {
1515
+ B : {
1516
+ Type : 'AWS::B::B' ,
1517
+ } ,
1518
+ } ,
1519
+ } ,
1520
+ } ;
1521
+
1522
+ const mappings : ResourceMapping [ ] = [
1523
+ new ResourceMapping ( new ResourceLocation ( stack1 , 'Bucket1' ) , new ResourceLocation ( stack2 , 'Bucket2' ) ) ,
1524
+ ] ;
1525
+
1526
+ const result = generateStackDefinitions ( mappings , [ stack1 ] ) ;
1527
+ expect ( result ) . toEqual ( [
1528
+ {
1529
+ StackName : 'Stack1' ,
1530
+ TemplateBody : JSON . stringify ( {
1531
+ Resources : {
1532
+ // Wasn't touched by the refactor
1533
+ A : {
1534
+ Type : 'AWS::A::A' ,
1535
+ } ,
1536
+
1537
+ // Bucket1 doesn't exist anymore
1538
+ } ,
1539
+ } ) ,
1540
+ } ,
1541
+ {
1542
+ StackName : 'Stack2' ,
1543
+ TemplateBody : JSON . stringify ( {
1544
+ Resources : {
1545
+ // Old Bucket1 is now Bucket2 here
1546
+ Bucket2 : {
1547
+ Type : 'AWS::S3::Bucket' ,
1548
+ } ,
1549
+ } ,
1550
+ } ) ,
1551
+ } ,
1552
+ ] ) ;
1553
+ } ) ;
1554
+
1555
+ test ( 'multiple mappings' , ( ) => {
1556
+ const stack1 : CloudFormationStack = {
1557
+ environment,
1558
+ stackName : 'Stack1' ,
1559
+ template : {
1560
+ Resources : {
1561
+ Bucket1 : {
1562
+ Type : 'AWS::S3::Bucket' ,
1563
+ } ,
1564
+ Bucket2 : {
1565
+ Type : 'AWS::S3::Bucket' ,
1566
+ } ,
1567
+ } ,
1568
+ } ,
1569
+ } ;
1570
+
1571
+ const stack2 : CloudFormationStack = {
1572
+ environment,
1573
+ stackName : 'Stack2' ,
1574
+ template : {
1575
+ Resources : {
1576
+ Bucket3 : {
1577
+ Type : 'AWS::S3::Bucket' ,
1578
+ } ,
1579
+ } ,
1580
+ } ,
1581
+ } ;
1582
+
1583
+ const mappings : ResourceMapping [ ] = [
1584
+ new ResourceMapping ( new ResourceLocation ( stack1 , 'Bucket1' ) , new ResourceLocation ( stack2 , 'Bucket4' ) ) ,
1585
+ new ResourceMapping ( new ResourceLocation ( stack1 , 'Bucket2' ) , new ResourceLocation ( stack2 , 'Bucket5' ) ) ,
1586
+ new ResourceMapping ( new ResourceLocation ( stack2 , 'Bucket3' ) , new ResourceLocation ( stack1 , 'Bucket6' ) ) ,
1587
+ ] ;
1588
+
1589
+ const result = generateStackDefinitions ( mappings , [ stack1 , stack2 ] ) ;
1590
+ expect ( result ) . toEqual ( [
1591
+ {
1592
+ StackName : 'Stack1' ,
1593
+ TemplateBody : JSON . stringify ( {
1594
+ Resources : {
1595
+ Bucket6 : {
1596
+ Type : 'AWS::S3::Bucket' ,
1597
+ } ,
1598
+ } ,
1599
+ } ) ,
1600
+ } ,
1601
+ {
1602
+ StackName : 'Stack2' ,
1603
+ TemplateBody : JSON . stringify ( {
1604
+ Resources : {
1605
+ Bucket4 : {
1606
+ Type : 'AWS::S3::Bucket' ,
1607
+ } ,
1608
+ Bucket5 : {
1609
+ Type : 'AWS::S3::Bucket' ,
1610
+ } ,
1611
+ } ,
1612
+ } ) ,
1613
+ } ,
1614
+ ] ) ;
1615
+ } ) ;
1616
+
1617
+ test ( 'deployed stacks that are not in any mapping' , ( ) => {
1618
+ const stack1 : CloudFormationStack = {
1619
+ environment,
1620
+ stackName : 'Stack1' ,
1621
+ template : {
1622
+ Resources : {
1623
+ Bucket1 : {
1624
+ Type : 'AWS::S3::Bucket' ,
1625
+ } ,
1626
+ } ,
1627
+ } ,
1628
+ } ;
1629
+
1630
+ const stack2 : CloudFormationStack = {
1631
+ environment,
1632
+ stackName : 'Stack2' ,
1633
+ template : {
1634
+ Resources : {
1635
+ Bucket2 : {
1636
+ Type : 'AWS::S3::Bucket' ,
1637
+ } ,
1638
+ } ,
1639
+ } ,
1640
+ } ;
1641
+
1642
+ const mappings : ResourceMapping [ ] = [
1643
+ new ResourceMapping ( new ResourceLocation ( stack1 , 'Bucket1' ) , new ResourceLocation ( stack1 , 'Bucket3' ) ) ,
1644
+ ] ;
1645
+
1646
+ const result = generateStackDefinitions ( mappings , [ stack1 , stack2 ] ) ;
1647
+ expect ( result ) . toEqual ( [
1648
+ {
1649
+ StackName : 'Stack1' ,
1650
+ TemplateBody : JSON . stringify ( {
1651
+ Resources : {
1652
+ Bucket3 : {
1653
+ Type : 'AWS::S3::Bucket' ,
1654
+ } ,
1655
+ } ,
1656
+ } ) ,
1657
+ } ,
1658
+ ] ) ;
1659
+ } ) ;
1660
+
1661
+ test ( 'refactor should not create empty templates' , ( ) => {
1662
+ const stack1 : CloudFormationStack = {
1663
+ environment,
1664
+ stackName : 'Stack1' ,
1665
+ template : {
1666
+ Resources : {
1667
+ Bucket1 : {
1668
+ Type : 'AWS::S3::Bucket' ,
1669
+ } ,
1670
+ } ,
1671
+ } ,
1672
+ } ;
1673
+
1674
+ const stack2 : CloudFormationStack = {
1675
+ environment,
1676
+ stackName : 'Stack2' ,
1677
+ template : {
1678
+ Resources : { } ,
1679
+ } ,
1680
+ } ;
1681
+
1682
+ const mappings : ResourceMapping [ ] = [
1683
+ new ResourceMapping ( new ResourceLocation ( stack1 , 'Bucket1' ) , new ResourceLocation ( stack2 , 'Bucket2' ) ) ,
1684
+ ] ;
1685
+
1686
+ expect ( ( ) => generateStackDefinitions ( mappings , [ stack1 , stack2 ] ) )
1687
+ . toThrow ( / S t a c k S t a c k 1 h a s n o r e s o u r c e s a f t e r r e f a c t o r / ) ;
1688
+ } ) ;
1689
+ } ) ;
1690
+
1383
1691
function toCfnMapping ( m : ResourceMapping ) : CfnResourceMapping {
1384
1692
return {
1385
1693
Source : toCfnLocation ( m . source ) ,
0 commit comments