@@ -356,14 +356,23 @@ export class CfnParser {
356
356
const cfnOptions = resource . cfnOptions ;
357
357
this . stack = Stack . of ( resource ) ;
358
358
359
- cfnOptions . creationPolicy = this . parseCreationPolicy ( resourceAttributes . CreationPolicy , logicalId ) ;
360
- cfnOptions . updatePolicy = this . parseUpdatePolicy ( resourceAttributes . UpdatePolicy , logicalId ) ;
359
+ const creationPolicy = this . parseCreationPolicy ( resourceAttributes . CreationPolicy , logicalId ) ;
360
+ const updatePolicy = this . parseUpdatePolicy ( resourceAttributes . UpdatePolicy , logicalId ) ;
361
+ cfnOptions . creationPolicy = creationPolicy . value ;
362
+ cfnOptions . updatePolicy = updatePolicy . value ;
361
363
cfnOptions . deletionPolicy = this . parseDeletionPolicy ( resourceAttributes . DeletionPolicy ) ;
362
364
cfnOptions . updateReplacePolicy = this . parseDeletionPolicy ( resourceAttributes . UpdateReplacePolicy ) ;
363
365
cfnOptions . version = this . parseValue ( resourceAttributes . Version ) ;
364
366
cfnOptions . description = this . parseValue ( resourceAttributes . Description ) ;
365
367
cfnOptions . metadata = this . parseValue ( resourceAttributes . Metadata ) ;
366
368
369
+ for ( const [ key , value ] of Object . entries ( creationPolicy . extraProperties ) ) {
370
+ resource . addOverride ( `CreationPolicy.${ key } ` , value ) ;
371
+ }
372
+ for ( const [ key , value ] of Object . entries ( updatePolicy . extraProperties ) ) {
373
+ resource . addOverride ( `UpdatePolicy.${ key } ` , value ) ;
374
+ }
375
+
367
376
// handle Condition
368
377
if ( resourceAttributes . Condition ) {
369
378
const condition = this . finder . findCondition ( resourceAttributes . Condition ) ;
@@ -386,98 +395,93 @@ export class CfnParser {
386
395
}
387
396
}
388
397
389
- private parseCreationPolicy ( policy : any , logicalId : string ) : CfnCreationPolicy | undefined {
390
- if ( typeof policy !== 'object' ) { return undefined ; }
398
+ private parseCreationPolicy ( policy : any , logicalId : string ) : FromCloudFormationResult < CfnCreationPolicy | undefined > {
399
+ if ( typeof policy !== 'object' ) { return new FromCloudFormationResult ( undefined ) ; }
391
400
this . throwIfIsIntrinsic ( policy , logicalId ) ;
392
401
const self = this ;
393
402
394
- // change simple JS values to their CDK equivalents
395
- policy = this . parseValue ( policy ) ;
396
-
397
- return undefinedIfAllValuesAreEmpty ( {
398
- autoScalingCreationPolicy : parseAutoScalingCreationPolicy ( policy . AutoScalingCreationPolicy ) ,
399
- resourceSignal : parseResourceSignal ( policy . ResourceSignal ) ,
400
- } ) ;
403
+ const creaPol = new ObjectParser < CfnCreationPolicy > ( this . parseValue ( policy ) ) ;
404
+ creaPol . parseCase ( 'autoScalingCreationPolicy' , parseAutoScalingCreationPolicy ) ;
405
+ creaPol . parseCase ( 'resourceSignal' , parseResourceSignal ) ;
406
+ return creaPol . toResult ( ) ;
401
407
402
- function parseAutoScalingCreationPolicy ( p : any ) : CfnResourceAutoScalingCreationPolicy | undefined {
408
+ function parseAutoScalingCreationPolicy ( p : any ) : FromCloudFormationResult < CfnResourceAutoScalingCreationPolicy | undefined > {
403
409
self . throwIfIsIntrinsic ( p , logicalId ) ;
404
- if ( typeof p !== 'object' ) { return undefined ; }
410
+ if ( typeof p !== 'object' ) { return new FromCloudFormationResult ( undefined ) ; }
405
411
406
- return undefinedIfAllValuesAreEmpty ( {
407
- minSuccessfulInstancesPercent : FromCloudFormation . getNumber ( p . MinSuccessfulInstancesPercent ) . value ,
408
- } ) ;
412
+ const autoPol = new ObjectParser < CfnResourceAutoScalingCreationPolicy > ( p ) ;
413
+ autoPol . parseCase ( ' minSuccessfulInstancesPercent' , FromCloudFormation . getNumber ) ;
414
+ return autoPol . toResult ( ) ;
409
415
}
410
416
411
- function parseResourceSignal ( p : any ) : CfnResourceSignal | undefined {
412
- if ( typeof p !== 'object' ) { return undefined ; }
417
+ function parseResourceSignal ( p : any ) : FromCloudFormationResult < CfnResourceSignal | undefined > {
418
+ if ( typeof p !== 'object' ) { return new FromCloudFormationResult ( undefined ) ; }
413
419
self . throwIfIsIntrinsic ( p , logicalId ) ;
414
420
415
- return undefinedIfAllValuesAreEmpty ( {
416
- count : FromCloudFormation . getNumber ( p . Count ) . value ,
417
- timeout : FromCloudFormation . getString ( p . Timeout ) . value ,
418
- } ) ;
421
+ const sig = new ObjectParser < CfnResourceSignal > ( p ) ;
422
+ sig . parseCase ( ' count' , FromCloudFormation . getNumber ) ;
423
+ sig . parseCase ( ' timeout' , FromCloudFormation . getString ) ;
424
+ return sig . toResult ( ) ;
419
425
}
420
426
}
421
427
422
- private parseUpdatePolicy ( policy : any , logicalId : string ) : CfnUpdatePolicy | undefined {
423
- if ( typeof policy !== 'object' ) { return undefined ; }
428
+ private parseUpdatePolicy ( policy : any , logicalId : string ) : FromCloudFormationResult < CfnUpdatePolicy | undefined > {
429
+ if ( typeof policy !== 'object' ) { return new FromCloudFormationResult ( undefined ) ; }
424
430
this . throwIfIsIntrinsic ( policy , logicalId ) ;
425
431
const self = this ;
426
432
427
433
// change simple JS values to their CDK equivalents
428
- policy = this . parseValue ( policy ) ;
429
-
430
- return undefinedIfAllValuesAreEmpty ( {
431
- autoScalingReplacingUpdate : parseAutoScalingReplacingUpdate ( policy . AutoScalingReplacingUpdate ) ,
432
- autoScalingRollingUpdate : parseAutoScalingRollingUpdate ( policy . AutoScalingRollingUpdate ) ,
433
- autoScalingScheduledAction : parseAutoScalingScheduledAction ( policy . AutoScalingScheduledAction ) ,
434
- codeDeployLambdaAliasUpdate : parseCodeDeployLambdaAliasUpdate ( policy . CodeDeployLambdaAliasUpdate ) ,
435
- enableVersionUpgrade : FromCloudFormation . getBoolean ( policy . EnableVersionUpgrade ) . value ,
436
- useOnlineResharding : FromCloudFormation . getBoolean ( policy . UseOnlineResharding ) . value ,
437
- } ) ;
438
-
439
- function parseAutoScalingReplacingUpdate ( p : any ) : CfnAutoScalingReplacingUpdate | undefined {
440
- if ( typeof p !== 'object' ) { return undefined ; }
434
+ const uppol = new ObjectParser < CfnUpdatePolicy > ( this . parseValue ( policy ) ) ;
435
+ uppol . parseCase ( 'autoScalingReplacingUpdate' , parseAutoScalingReplacingUpdate ) ;
436
+ uppol . parseCase ( 'autoScalingRollingUpdate' , parseAutoScalingRollingUpdate ) ;
437
+ uppol . parseCase ( 'autoScalingScheduledAction' , parseAutoScalingScheduledAction ) ;
438
+ uppol . parseCase ( 'codeDeployLambdaAliasUpdate' , parseCodeDeployLambdaAliasUpdate ) ;
439
+ uppol . parseCase ( 'enableVersionUpgrade' , ( x ) => FromCloudFormation . getBoolean ( x ) as any ) ;
440
+ uppol . parseCase ( 'useOnlineResharding' , ( x ) => FromCloudFormation . getBoolean ( x ) as any ) ;
441
+ return uppol . toResult ( ) ;
442
+
443
+ function parseAutoScalingReplacingUpdate ( p : any ) : FromCloudFormationResult < CfnAutoScalingReplacingUpdate | undefined > {
444
+ if ( typeof p !== 'object' ) { return new FromCloudFormationResult ( undefined ) ; }
441
445
self . throwIfIsIntrinsic ( p , logicalId ) ;
442
446
443
- return undefinedIfAllValuesAreEmpty ( {
444
- willReplace : p . WillReplace ,
445
- } ) ;
447
+ const repUp = new ObjectParser < CfnAutoScalingReplacingUpdate > ( p ) ;
448
+ repUp . parseCase ( 'willReplace' , ( x ) => x ) ;
449
+ return repUp . toResult ( ) ;
446
450
}
447
451
448
- function parseAutoScalingRollingUpdate ( p : any ) : CfnAutoScalingRollingUpdate | undefined {
449
- if ( typeof p !== 'object' ) { return undefined ; }
452
+ function parseAutoScalingRollingUpdate ( p : any ) : FromCloudFormationResult < CfnAutoScalingRollingUpdate | undefined > {
453
+ if ( typeof p !== 'object' ) { return new FromCloudFormationResult ( undefined ) ; }
450
454
self . throwIfIsIntrinsic ( p , logicalId ) ;
451
455
452
- return undefinedIfAllValuesAreEmpty ( {
453
- maxBatchSize : FromCloudFormation . getNumber ( p . MaxBatchSize ) . value ,
454
- minInstancesInService : FromCloudFormation . getNumber ( p . MinInstancesInService ) . value ,
455
- minSuccessfulInstancesPercent : FromCloudFormation . getNumber ( p . MinSuccessfulInstancesPercent ) . value ,
456
- pauseTime : FromCloudFormation . getString ( p . PauseTime ) . value ,
457
- suspendProcesses : FromCloudFormation . getStringArray ( p . SuspendProcesses ) . value ,
458
- waitOnResourceSignals : FromCloudFormation . getBoolean ( p . WaitOnResourceSignals ) . value ,
459
- } ) ;
456
+ const rollUp = new ObjectParser < CfnAutoScalingRollingUpdate > ( p ) ;
457
+ rollUp . parseCase ( ' maxBatchSize' , FromCloudFormation . getNumber ) ;
458
+ rollUp . parseCase ( ' minInstancesInService' , FromCloudFormation . getNumber ) ;
459
+ rollUp . parseCase ( ' minSuccessfulInstancesPercent' , FromCloudFormation . getNumber ) ;
460
+ rollUp . parseCase ( ' pauseTime' , FromCloudFormation . getString ) ;
461
+ rollUp . parseCase ( ' suspendProcesses' , FromCloudFormation . getStringArray ) ;
462
+ rollUp . parseCase ( ' waitOnResourceSignals' , FromCloudFormation . getBoolean ) ;
463
+ return rollUp . toResult ( ) ;
460
464
}
461
465
462
- function parseCodeDeployLambdaAliasUpdate ( p : any ) : CfnCodeDeployLambdaAliasUpdate | undefined {
466
+ function parseCodeDeployLambdaAliasUpdate ( p : any ) : FromCloudFormationResult < CfnCodeDeployLambdaAliasUpdate | undefined > {
467
+ if ( typeof p !== 'object' ) { return new FromCloudFormationResult ( undefined ) ; }
463
468
self . throwIfIsIntrinsic ( p , logicalId ) ;
464
- if ( typeof p !== 'object' ) { return undefined ; }
465
469
466
- return {
467
- beforeAllowTrafficHook : FromCloudFormation . getString ( p . BeforeAllowTrafficHook ) . value ,
468
- afterAllowTrafficHook : FromCloudFormation . getString ( p . AfterAllowTrafficHook ) . value ,
469
- applicationName : FromCloudFormation . getString ( p . ApplicationName ) . value ,
470
- deploymentGroupName : FromCloudFormation . getString ( p . DeploymentGroupName ) . value ,
471
- } ;
470
+ const cdUp = new ObjectParser < CfnCodeDeployLambdaAliasUpdate > ( p ) ;
471
+ cdUp . parseCase ( ' beforeAllowTrafficHook' , FromCloudFormation . getString ) ;
472
+ cdUp . parseCase ( ' afterAllowTrafficHook' , FromCloudFormation . getString ) ;
473
+ cdUp . parseCase ( ' applicationName' , FromCloudFormation . getString ) ;
474
+ cdUp . parseCase ( ' deploymentGroupName' , FromCloudFormation . getString ) ;
475
+ return cdUp . toResult ( ) ;
472
476
}
473
477
474
- function parseAutoScalingScheduledAction ( p : any ) : CfnAutoScalingScheduledAction | undefined {
478
+ function parseAutoScalingScheduledAction ( p : any ) : FromCloudFormationResult < CfnAutoScalingScheduledAction | undefined > {
479
+ if ( typeof p !== 'object' ) { return new FromCloudFormationResult ( undefined ) ; }
475
480
self . throwIfIsIntrinsic ( p , logicalId ) ;
476
- if ( typeof p !== 'object' ) { return undefined ; }
477
481
478
- return undefinedIfAllValuesAreEmpty ( {
479
- ignoreUnmodifiedGroupSizeProperties : FromCloudFormation . getBoolean ( p . IgnoreUnmodifiedGroupSizeProperties ) . value ,
480
- } ) ;
482
+ const schedUp = new ObjectParser < CfnAutoScalingScheduledAction > ( p ) ;
483
+ schedUp . parseCase ( ' ignoreUnmodifiedGroupSizeProperties' , FromCloudFormation . getBoolean ) ;
484
+ return schedUp . toResult ( ) ;
481
485
}
482
486
}
483
487
@@ -853,3 +857,70 @@ export class CfnParser {
853
857
return this . options . parameters || { } ;
854
858
}
855
859
}
860
+
861
+ class ObjectParser < T extends object > {
862
+ private readonly parsed : Record < string , unknown > = { } ;
863
+ private readonly unparsed : Record < string , unknown > = { } ;
864
+
865
+ constructor ( input : Record < string , unknown > ) {
866
+ this . unparsed = { ...input } ;
867
+ }
868
+
869
+ /**
870
+ * Parse a single field from the object into the target object
871
+ *
872
+ * The source key will be assumed to be the exact same as the
873
+ * target key, but with an uppercase first letter.
874
+ */
875
+ public parseCase < K extends keyof T > ( targetKey : K , parser : ( x : any ) => T [ K ] | FromCloudFormationResult < T [ K ] | IResolvable > ) {
876
+ const sourceKey = ucfirst ( String ( targetKey ) ) ;
877
+ this . parse ( targetKey , sourceKey , parser ) ;
878
+ }
879
+
880
+ public parse < K extends keyof T > ( targetKey : K , sourceKey : string , parser : ( x : any ) => T [ K ] | FromCloudFormationResult < T [ K ] | IResolvable > ) {
881
+ if ( ! ( sourceKey in this . unparsed ) ) {
882
+ return ;
883
+ }
884
+
885
+ const value = parser ( this . unparsed [ sourceKey ] ) ;
886
+ delete this . unparsed [ sourceKey ] ;
887
+
888
+ if ( value instanceof FromCloudFormationResult ) {
889
+ for ( const [ k , v ] of Object . entries ( value . extraProperties ?? { } ) ) {
890
+ this . unparsed [ `${ sourceKey } .${ k } ` ] = v ;
891
+ }
892
+ this . parsed [ targetKey as any ] = value . value ;
893
+ } else {
894
+ this . parsed [ targetKey as any ] = value ;
895
+ }
896
+ }
897
+
898
+ public toResult ( ) : FromCloudFormationResult < T | undefined > {
899
+ const ret = new FromCloudFormationResult ( undefinedIfAllValuesAreEmpty ( this . parsed as any ) ) ;
900
+ for ( const [ k , v ] of Object . entries ( this . unparsedKeys ) ) {
901
+ ret . extraProperties [ k ] = v ;
902
+ }
903
+ return ret ;
904
+ }
905
+
906
+ private get unparsedKeys ( ) : Record < string , unknown > {
907
+ const unparsed = { ...this . unparsed } ;
908
+
909
+ for ( const [ k , v ] of Object . entries ( this . unparsed ) ) {
910
+ if ( v instanceof FromCloudFormationResult ) {
911
+ for ( const [ k2 , v2 ] of Object . entries ( v . extraProperties ?? { } ) ) {
912
+ unparsed [ `${ k } .${ k2 } ` ] = v2 ;
913
+ }
914
+ } else {
915
+ unparsed [ k ] = v ;
916
+ }
917
+ }
918
+
919
+ return unparsed ;
920
+ }
921
+ }
922
+
923
+ function ucfirst ( x : string ) {
924
+ return x . slice ( 0 , 1 ) . toUpperCase ( ) + x . slice ( 1 ) ;
925
+ }
926
+
0 commit comments