I'm exploring how refactorable CDK applications are. Suppose I defined a custom construct (a stack) to create an EKS cluster. Let's call it EksStack. Ideally, I'd create the role to be associated with the cluster and the EKS cluster itself, as described by the following snippet (I'm using Scala instead of Java, so the snippets are going to be in Scala syntax):
class EksStack (scope: Construct, id: String, props: StackProps) extends Stack(scope, id, props) {
private val role = new Role(this, "eks-role", RoleProps.builder()
.description(...)
.managedPolicies(...)
.assumedBy(...)
.build()
)
private val cluster = new Cluster(this, "eks-cluster", ClusterProps.builder()
.version(...)
.role(role)
.defaultCapacityType(DefaultCapacityType.EC2)
.build()
)
}
When I synthetize the application, I can see that the generated template contains the definition of the VPC, together with the Elastic IPs, NATs, Internet Gateways, and so on.
Now suppose that I want to refactor EksStack and have a different stack, say VpcStack, explicitly create the VPC:
class VpcStack (scope: Construct, id: String, props: StackProps) extends Stack(scope, id, props) {
val vpc = new Vpc(this, VpcId, VpcProps.builder()
.cidr(...)
.enableDnsSupport(true)
.enableDnsHostnames(true)
.maxAzs(...)
.build()
)
}
Ideally, the cluster in EksStack would just be using the reference to the VPC created by VpcStack, something like (note the new call to vpc() in the builder of cluster):
class EksStack (scope: Construct, id: String, props: StackProps, vpc: IVpc) extends Stack(scope, id, props) {
private val role = new Role(this, "eks-role", RoleProps.builder()
.description(...)
.managedPolicies(...)
.assumedBy(...)
.build()
)
private val cluster = new Cluster(this, "eks-cluster", ClusterProps.builder()
.version(...)
.role(role)
.vpc(vpc)
.defaultCapacityType(DefaultCapacityType.EC2)
.build()
)
}
This obviously doesn't work, as CloudFormation would delete the VPC created by EksStack in favor of the one created by VpcStack. I read here and there and tried to add a retain policy in EksStack and to override the logical ID of the VPC in VpcStack, using the ID I originally saw in the CloudFormation template for EksStack:
val cfnVpc = cluster.getVpc.getNode.getDefaultChild.asInstanceOf[CfnVPC]
cfnVpc.applyRemovalPolicy(RemovalPolicy.RETAIN)
and
val cfnVpc = vpc.getNode.getDefaultChild.asInstanceOf[CfnVPC]
cfnVpc.overrideLogicalId("LogicalID")
and then retried the diff. Again, it seems that the VPC is deleted and re-created.
Now, I saw that it is possible to migrate CloudFormation resources (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/refactor-stacks.html) using the "Import resources into stack" action. My question is: can I move the creation of a resource from a stack to another in CDK without re-creating it?
EDIT:
To elaborate a bit on my problem, when I define the VPC in VpcStack, I'd like CDK to think that the resource was created by VpcStack instead ok EksStack. Something like moving the definition of it from one stack to another without having CloudFormation delete the original one to re-create it. In my use case, I'd have a stack define a create initially (either explicitly or implicitly, such as my VPC), but then, after I while, I might want to refactor my application, moving the creation of that resource in a dedicated stack. I'm trying to understand if this moving always leads to the resource being re-created of if there's any way to avoid it.