python-3.xterraform-cdk

CDKTF ec2 Recreation with specific private IP address


Problem - I have 3 ec2 vms created in a single stack of CDKTF the plan file looks like below-

resources {
  instances:[{instance 1},{instance 2},{instance 3}]
}

Now I want to delete the instance 3 as I want to change the flavour from amd64 to arm, but I want to preserve the IP.

ASK- How can I pass a count iterative private IP like [none, none, 10.xxx.xx.xxx] resulting in an IP address assignment to my instance 3 and not affecting the instance 1 and 2?

My current code is below-

private_ip = [None,None,'10.xxx.xx.xxx']

instance = ec2.Instance(self.scope_obj,
                        "%s-instance-%s" % (self.app, zone), ami=self.ami, instance_type=self.flavor_name,
                        subnet_id=data_subnet_obj.id, tags=vm_tags, volume_tags=vol_tags,
                        root_block_device=root_volume,
                        count=instance_count,
                        metadata_options=metadata_options,
                        availability_zone=zones,
                        disable_api_termination=disable_api_termination,
                        iam_instance_profile = iam_instance_profile,
                        vpc_security_group_ids = vpc_security_group_ids,
                        key_name = key_name,
                        private_ip = private_ip["${count.index}"]
                        )

Error: TypeError: list indices must be integers or slices, not str


Solution

  • As to what I understand, you already have an infrastructure and using a count.index you want to fetch the IP and attach it to the VM after delete the VM and changing the flavour type.

    You can create a map instead of a list and then a terraform variable and do a lookup, check out the code below-

    from cdktf import TerraformVariable
    
    private_ip_map_variable = {0:'ip1',1:'10.xx.xxx.xx', 2:'10.90.xxx.xx'}
    
    var = TerraformVariable(self.scope_obj,'varname',default=private_ip_map_variable, type="map(string)")
    
    instance = ec2.Instance(self.scope_obj,
                            "%s-instance-%s" % (self.app, zone), ami=self.ami, instance_type=self.flavor_name,
                            subnet_id=data_subnet_obj.id, tags=vm_tags, volume_tags=vol_tags,
                            root_block_device=root_volume,
                            count=instance_count,
                            metadata_options=metadata_options,
                            availability_zone=zones,
                            disable_api_termination=disable_api_termination,
                            iam_instance_profile = iam_instance_profile,
                            vpc_security_group_ids = vpc_security_group_ids,
                            key_name = key_name,
                            private_ip = "${lookup(var.varname,count.index)}"
                            )
    

    Note- Don't keep private_ip None, else it would not show up in the TerraformVariable object