diff --git a/packages/@aws-cdk/core/lib/cfn-resource.ts b/packages/@aws-cdk/core/lib/cfn-resource.ts index 94ae9c506e5e0..9777268a7b328 100644 --- a/packages/@aws-cdk/core/lib/cfn-resource.ts +++ b/packages/@aws-cdk/core/lib/cfn-resource.ts @@ -609,6 +609,35 @@ function deepMerge(target: any, ...sources: any[]) { } } + /** + * There might also be the case where the source is an intrinsic + * + * target: { + * Type: 'MyResourceType', + * Properties: { + * prop1: { subprop: { name: { 'Fn::GetAtt': 'abc' } } } + * } + * } + * sources: [ { + * Properties: { + * prop1: { subprop: { 'Fn::If': ['SomeCondition', {...}, {...}] }} + * } + * } ] + * + * We end up in a place that is the reverse of the above check, the source + * becomes an intrinsic before the target + * + * target: { subprop: { name: { 'Fn::GetAtt': 'abc' } } } + * sources: [{ + * 'Fn::If': [ 'MyCondition', {...}, {...} ] + * }] + */ + if (Object.keys(value).length === 1) { + if (MERGE_EXCLUDE_KEYS.includes(Object.keys(value)[0])) { + target[key] = {}; + } + } + deepMerge(target[key], value); // if the result of the merge is an empty object, it's because the diff --git a/packages/@aws-cdk/core/test/resource.test.ts b/packages/@aws-cdk/core/test/resource.test.ts index 32a273f76a663..fe247827bb3d6 100644 --- a/packages/@aws-cdk/core/test/resource.test.ts +++ b/packages/@aws-cdk/core/test/resource.test.ts @@ -726,6 +726,59 @@ describe('resource', () => { }); }); + test('Can override a an object with an intrinsic', () => { + // GIVEN + const stack = new Stack(); + + const condition = new CfnCondition(stack, 'MyCondition', { + expression: Fn.conditionEquals('us-east-1', 'us-east-1'), + }); + const resource = new CfnResource(stack, 'MyResource', { + type: 'MyResourceType', + properties: { + prop1: { + subprop: { + name: Fn.getAtt('resource', 'abc'), + }, + }, + }, + }); + const isEnabled = Fn.conditionIf(condition.logicalId, { + Ref: 'AWS::NoValue', + }, { + name: Fn.getAtt('resource', 'abc'), + }); + + // WHEN + resource.addPropertyOverride('prop1.subprop', isEnabled); + const cfn = toCloudFormation(stack); + + // THEN + expect(cfn.Resources.MyResource).toEqual({ + Type: 'MyResourceType', + Properties: { + prop1: { + subprop: { + 'Fn::If': [ + 'MyCondition', + { + Ref: 'AWS::NoValue', + }, + { + name: { + 'Fn::GetAtt': [ + 'resource', + 'abc', + ], + }, + }, + ], + }, + }, + }, + }); + }); + test('overrides allow overriding a nested intrinsic', () => { // GIVEN const stack = new Stack();