1- import { promises as fs } from 'fs' ;
2- import * as path from 'path' ;
31import { DescribeStacksCommand , GetTemplateCommand } from '@aws-sdk/client-cloudformation' ;
2+ import { DynamoDBClient , PutItemCommand , GetItemCommand , DeleteTableCommand } from '@aws-sdk/client-dynamodb' ;
43import * as yaml from 'yaml' ;
54import { integTest , withDefaultFixture } from '../../../lib' ;
65
@@ -18,61 +17,70 @@ integTest(
1817 ) ;
1918 const outputs = describeResponse . Stacks ?. [ 0 ] ?. Outputs ?? [ ] ;
2019 const tableName = outputs . find ( ( o ) => o . OutputKey === 'TableName' ) ?. OutputValue ;
21- const functionName = outputs . find ( ( o ) => o . OutputKey === 'FunctionName' ) ?. OutputValue ;
2220 expect ( tableName ) . toBeDefined ( ) ;
23- expect ( functionName ) . toBeDefined ( ) ;
2421
25- // Put an item in the table before orphan
26- const itemFile = path . join ( fixture . integTestDir , 'test-item.json' ) ;
27- await fs . writeFile ( itemFile , JSON . stringify ( { PK : { S : 'before-orphan' } } ) ) ;
28- await fixture . shell ( [
29- 'aws' , 'dynamodb' , 'put-item' ,
30- '--table-name' , tableName ! ,
31- '--item' , `file://${ itemFile } ` ,
32- '--region' , fixture . aws . region ,
33- ] ) ;
22+ const dynamodb = new DynamoDBClient ( { region : fixture . aws . region } ) ;
3423
35- // Orphan the table
36- const orphanOutput = await fixture . cdk ( [
37- 'orphan' ,
38- '--path' , ` ${ stackName } /MyTable` ,
39- '--unstable=orphan' ,
40- '--force' ,
41- ] ) ;
24+ try {
25+ // Verify the table resource exists in the template before orphaning
26+ const templateBefore = await fixture . aws . cloudFormation . send (
27+ new GetTemplateCommand ( { StackName : stackName } ) ,
28+ ) ;
29+ const templateBodyBefore = yaml . parse ( templateBefore . TemplateBody ! ) ;
30+ expect ( templateBodyBefore . Resources ) . toHaveProperty ( 'MyTable794EDED1' ) ;
4231
43- // Verify the output contains a resource mapping for import
44- expect ( orphanOutput ) . toContain ( 'resource-mapping-inline' ) ;
45- expect ( orphanOutput ) . toContain ( 'TableName' ) ;
32+ // Put an item in the table before orphan
33+ await dynamodb . send ( new PutItemCommand ( {
34+ TableName : tableName ! ,
35+ Item : { PK : { S : 'before-orphan' } } ,
36+ } ) ) ;
4637
47- // Verify the table is no longer in the stack template
48- const templateAfter = await fixture . aws . cloudFormation . send (
49- new GetTemplateCommand ( { StackName : stackName } ) ,
50- ) ;
51- const templateBody = yaml . parse ( templateAfter . TemplateBody ! ) ;
52- expect ( templateBody . Resources ) . not . toHaveProperty ( 'MyTable794EDED1' ) ;
38+ // Orphan the table
39+ const orphanOutput = await fixture . cdk ( [
40+ 'orphan' ,
41+ '--path' , `${ stackName } /MyTable` ,
42+ '--unstable=orphan' ,
43+ '--force' ,
44+ ] ) ;
45+
46+ // Verify the output contains a resource mapping for import
47+ expect ( orphanOutput ) . toContain ( 'resource-mapping-inline' ) ;
48+ expect ( orphanOutput ) . toContain ( 'TableName' ) ;
49+
50+ // Verify the template after orphan: table gone, Lambda env vars replaced with literals
51+ const templateAfter = await fixture . aws . cloudFormation . send (
52+ new GetTemplateCommand ( { StackName : stackName } ) ,
53+ ) ;
54+ const templateBody = yaml . parse ( templateAfter . TemplateBody ! ) ;
5355
54- // Verify the Lambda still exists and its env vars have been replaced with literals
55- // (Ref -> physical table name, GetAtt -> physical ARN)
56- const lambdaResource = Object . values ( templateBody . Resources ) . find (
57- ( r : any ) => r . Type === 'AWS::Lambda::Function' ,
58- ) as any ;
59- expect ( lambdaResource ) . toBeDefined ( ) ;
60- const envVars = lambdaResource . Properties ?. Environment ?. Variables ?? { } ;
61- // TABLE_NAME should be a literal string (not a {Ref})
62- expect ( typeof envVars . TABLE_NAME ) . toBe ( 'string' ) ;
63- expect ( envVars . TABLE_NAME ) . toContain ( 'MyTable' ) ;
64- // TABLE_ARN should be a literal string (not a {Fn::GetAtt})
65- expect ( typeof envVars . TABLE_ARN ) . toBe ( 'string' ) ;
66- expect ( envVars . TABLE_ARN ) . toContain ( 'arn:aws:dynamodb' ) ;
56+ expect ( templateBody . Resources ) . not . toHaveProperty ( 'MyTable794EDED1' ) ;
57+ expect ( templateBody ) . toMatchObject ( {
58+ Resources : expect . objectContaining ( {
59+ Consumer8D6BE417 : expect . objectContaining ( {
60+ Type : 'AWS::Lambda::Function' ,
61+ Properties : expect . objectContaining ( {
62+ Environment : {
63+ Variables : {
64+ TABLE_NAME : expect . stringContaining ( 'MyTable' ) ,
65+ TABLE_ARN : expect . stringContaining ( 'arn:aws:dynamodb' ) ,
66+ } ,
67+ } ,
68+ } ) ,
69+ } ) ,
70+ } ) ,
71+ } ) ;
6772
68- // Verify the table still exists and data is intact
69- const getItemOutput = await fixture . shell ( [
70- 'aws' , 'dynamodb' , 'get-item' ,
71- '--table-name' , tableName ! ,
72- '--key' , `file://${ itemFile } ` ,
73- '--region' , fixture . aws . region ,
74- '--output' , 'json' ,
75- ] ) ;
76- expect ( getItemOutput ) . toContain ( 'before-orphan' ) ;
73+ // Verify the table still exists and data is intact (strongly consistent read)
74+ const getItemResult = await dynamodb . send ( new GetItemCommand ( {
75+ TableName : tableName ! ,
76+ Key : { PK : { S : 'before-orphan' } } ,
77+ ConsistentRead : true ,
78+ } ) ) ;
79+ expect ( getItemResult . Item ?. PK ?. S ) . toBe ( 'before-orphan' ) ;
80+ } finally {
81+ // Clean up the retained table to avoid leaking resources
82+ await dynamodb . send ( new DeleteTableCommand ( { TableName : tableName ! } ) ) . catch ( ( ) => {
83+ } ) ;
84+ }
7785 } ) ,
7886) ;
0 commit comments