visit
It’s effortless to use, for creating new infrastructure, but not so much for importing existing infrastructure, and hopefully, this post will demystify some of these complexities!
Because like everything else in life, it is sometimes impossible to plan for the future. Without adequate planning with the creation of infrastructure, it can lead to situations where infrastructure needs to be created manually due to time pressures, emergency releases or just the fact that the infrastructure exists, and terraform was never used in the first instance.
It’s worth reiterating that its always much simpler to create the terraform first, you would only ever import when you need to do something reactive, like an emergency releaseBefore the terraform import is run, two places can be used as a starting point:
At present, it is not possible to directly take an AWS resource and import it into a terraform resource definition. Still, it is possible to import into a state equivalent and then convert that into a terraform resource definition.
Imagine that something was going wrong in production, and a change had to be applied quickly to prevent an outage. A change was added manually in route53 to add a DNS record.
Once things had settled down, the same record was defined as a terraform resource, but when apply is ran, a messages is returned to say that the resource already exists. It causes the apply stage to fail.What needs to happen, is to import the state with the existing resource, so that next time a terraform apply is run, the terraform software will consider the resource in its state. Going forward, this means any changes made will be picked up as modifications, rather than additions.In this hypothetical situation, let us imagine that the following resources were created from within the AWS console:
resource "aws_route53_record" "www" {
name = "www.mywebsite.com"
type = "CNAME"
zone_id = "${data.aws_route53_zone.zone.id}"
records = ["mywebsite.com"]
ttl = 300
}
data "aws_route53_zone" "zone" {
name = "mywebsite.com"
private_zone = false
}
* aws_route53_record.www: 1 error(s) occurred:
* aws_route53_record.www: [ERR]: Error building changeset:
InvalidChangeBatch:
RRSet of type CNAME with DNS name www.mywebsite.com. is not permitted as it conflicts with other records with the same DNS name in zone mywebsite.com.
status code: 400
AWS_PROFILE=mywebsite terraform import aws_route53_record.www Z0ZZZZZZ0ZZZZ0_www.mywebsite.com_CNAME
Which corresponds to:
AWS_PROFILE={AwsProfileName} terraform import {resource_type}.{resource_name} {zone_id}_{record_name}_{record_type}
aws_route53_record.www: Importing from ID "Z0ZZZZZZ0ZZZZ0_www.mywebsite.com_CNAME"...
aws_route53_record.www: Import complete!
Imported aws_route53_record (ID: Z0ZZZZZZ0ZZZZ0_www.mywebsite.com_CNAME)
aws_route53_record.www: Refreshing state... (ID: Z0ZZZZZZ0ZZZZ0_www.mywebsite.com_CNAME)
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
aws_route53_record.www: Importing from ID "Z0ZZZZZZ0ZZZZ0_www.mywebsite.com_CNAME"...
aws_route53_record.www: Import complete!
Imported aws_route53_record (ID: Z0ZZZZZZ0ZZZZ0_www.mywebsite.com_CNAME)
Error: aws_route53_record.www (import id: Z0ZZZZZZ0ZZZZ0_www.mywebsite.com_CNAME): Can't import aws_route53_record.www, would collide with an existing resource.
Please remove or rename this resource before continuing.
Imagine that something went wrong, and you had to quickly migrate from a physical server to EC2.
You spin up an EC2 and applied a load of settings.
Once things settled down after the deployment, you wanted to build the terraform and sync the state so that it can be managed via terraform going forward.What needs to happen is we need to understand what currently exists in AWS, so that we can build a terraform resource, so that it can be imported.In this scenario, I will work with the hypothetical AWS resource:EC2 instance Name: mywebsite-server
resource "aws_instance" "mywebsite-server" {
}
AWS_PROFILE=mywebsite terraform import aws_instance.mywebsite-server i-0Z000ZZ0Z0Z00Z0Z0
Which corresponds to:
AWS_PROFILE={AwsProfileName} terraform import {resource_type}.{resource_name} {instance_id}
aws_instance.mywebsite-server: Importing from ID "i-0Z000ZZ0Z0Z00Z0Z0"...
aws_instance.mywebsite-server: Import complete!
Imported aws_instance (ID: i-0Z000ZZ0Z0Z00Z0Z0)
aws_instance.mywebsite-server: Refreshing state... (ID: i-0Z000ZZ0Z0Z00Z0Z0)
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
"resources": {
"aws_instance.mywebsite-server": {
"type": "aws_instance",
"depends_on": [],
"primary": {
"id": "i-0Z000ZZ0Z0Z00Z0Z0",
"attributes": {
"ami": "ami-zzz00zz0",
"arn": "arn:aws:ec2:eu-west-2:XXXXXXXXXXXX:instance/i-0Z000ZZ0Z0Z00Z0Z0",
"associate_public_ip_address": "true",
"availability_zone": "eu-west-2a",
"cpu_core_count": "1",
"cpu_threads_per_core": "1",
"credit_specification.#": "1",
"credit_specification.0.cpu_credits": "standard",
"disable_api_termination": "false",
"ebs_block_device.#": "0",
"ebs_optimized": "false",
"ephemeral_block_device.#": "0",
"get_password_data": "false",
"iam_instance_profile": "",
"id": "i-0Z000ZZ0Z0Z00Z0Z0",
"instance_state": "running",
"instance_type": "t2.micro",
"ipv6_addresses.#": "0",
"key_name": "mywebsite",
"monitoring": "false",
"network_interface.#": "0",
"network_interface_id": "eni-00zzzzz00zz000z00",
"password_data": "",
"placement_group": "",
"primary_network_interface_id": "eni-00zzzzz00zz000z00",
"private_dns": "ip-1-1-1-1.eu-west-2.compute.internal",
"private_ip": "1.1.1.1",
"public_dns": "ec2-1-1-1-1.eu-west-2.compute.amazonaws.com",
"public_ip": "1.1.1.1",
"root_block_device.#": "1",
"root_block_device.0.delete_on_termination": "true",
"root_block_device.0.iops": "0",
"root_block_device.0.volume_id": "vol-0z00zz0zzz000z0zz",
"root_block_device.0.volume_size": "8",
"root_block_device.0.volume_type": "standard",
"security_groups.#": "0",
"source_dest_check": "true",
"subnet_id": "subnet-000000z0000z00z0z",
"tags.%": "1",
"tags.Name": "MyWebsite",
"tenancy": "default",
"user_data": "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz",
"volume_tags.%": "0",
"vpc_security_group_ids.#": "1",
"vpc_security_group_ids.3064782471": "sg-00zz00zzz00zz0000"
},
"meta": {
"e2bfb730-ecaa-11e6-8f88-34363bc7c4c0": {
"create": 600000000000,
"delete": 00,
"update": 600000000000
},
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": "provider.aws"
}
},
Graphic Attributions: