CloudFormation didn't use to have support for AWS Shield Protection, so in order to use that I implemented a custom resource that would manage the shield protection. Now they have released an AWS::Shield:Protection resource that I would like to use instead.
If I in my template just replace the old custom resource with the new official resource, CloudFormation will first try to provision the new AWS::Shield::Protection resource before deleting the old custom resource. The creation will then fail because the resource will already have a protection in place. In essence, they both try to work with the same physical resource and thus conflict with each other.
If I was just managing a single stack manually, I could just remove the custom resource from the template, apply an update and then add the new AWS::Shield::Protection resource and do another update, but in reality I'm managing thousands of stacks and the templates are generated from code as part of a deployment platform, so manually mucking around with individual stacks isn't an option. Ideally I'd want to somehow express a relationship between the two resources such that the custom resource is deleted before the new resource is created, but I don't think this is possible.
Any ideas on how I can make this swap happen? I do have the ability to query AWS APIs as part of generating the CloudFormation templates, and since the plan is to get rid of the custom resource I can change its implementation.
In Cloudformation, all delete operations happen after all create and update operations are complete, in a separate "cleanup" phase. So what you are looking for is not possible in a single pass.
A hacky way to partially solve this in a single pass is to change the custom resource's implementation to delete the underlying resource on a update event, add the native cloudformation construct and then make it depend on the custom resource.
This will first trigger an update event for the custom resource, deleting the protection resource, then it will create the native cloudformation resource. However, you'll be stuck with a dummy custom resource in your template - you'll still need another pass to remove it along with the dependency to completely get rid of it.