How to import existing infrastructure resources with Terraform

My name is Teraoka and I am an infrastructure engineer

Have you ever thought, "I want to be able to manage my existing infrastructure configuration with Terraform?"
Terraform provides commands that make this possible, and I will introduce them in this article.

I created one VPC in advance without using Terraform

This time, we will import this into Terraform

Directory structure

$ tree . ├── README.md ├── provider.tf ├── terraform.tfstate ├── variables.tf └── vpc.tf 0 directories, 5 files

Describing the provider and variable

Before importing, we need to write the provider and variable as they are the minimum required

provider.tf

provider "aws" { access_key = var.access_key secret_key = var.secret_key region = var.region assume_role { role_arn = var.role_arn } }

variables.tf

#################### # Provider ################### variable "access_key" { description = "AWS Access Key" } variable "secret_key" { description = "AWS Secret Key" } variable "role_arn" { description = "AWS Role Arn" } variable "region" { default = "ap-northeast-1" }

Store your AWS access keys in environment variables

$ export TF_VAR_access_key=XXXXXXXXXXXXXXXXXX $ export TF_VAR_secret_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX $ export TF_VAR_role_arn=arn:aws:iam::XXXXXXXXXXXX:role/XXXXXXXXXXXXXXXXXXX

Run the plan

Let’s try running plan.
Since we haven’t imported anything yet, the execution will end with “No changes.”

$ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. --------------------------------------------------------------------------- No changes. Infrastructure is up-to-date. This means that Terraform did not detect any differences between your configuration and real physical resources that exist. As a result, no actions need to be performed.

Run the import

To import existing resources using Terraform, run the "terraform import" command.
The command format is described in the Terraform manual (※1) , so refer to it and run the following command.

$ terraform import aws_vpc.vpc vpc-09a9f1827bfd851f4 Error: resource address "aws_vpc.vpc" does not exist in the configuration. Before importing this resource, please create its configuration in the root module. For example: resource "aws_vpc" "vpc" { # (resource arguments) }

An error occurred

When importing, you will specify the resource type and name, such as "aws_vpc.vpc", and the information of existing resources will be imported into the resources in the tf file specified here

Therefore, you need to write the corresponding resources in the tf file in advance

Describe a vpc resource

I will write it as follows:

vpc.tf

#################### # VPC ################### resource "aws_vpc" "vpc" { cidr_block = "10.0.0.0/16" enable_dns_support = true enable_dns_hostnames = true tags = { Name = "vpc-tfstate-test" } }

Run the import again

Let's try again.
This time the import went smoothly.

$ terraform import aws_vpc.vpc vpc-09a9f1827bfd851f4 aws_vpc.vpc: Importing from ID "vpc-09a9f1827bfd851f4"... aws_vpc.vpc: Import prepared! Prepared aws_vpc for import aws_vpc.vpc: Refreshing state... [id=vpc-09a9f1827bfd851f4] 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.

What does this terraform import do?
When you run the command, you will see that a file named "terraform.tfstate" is created.

terraform.tfstate

{ "version": 4, "terraform_version": "0.12.24", "serial": 1, "lineage": "c0359eb1-d905-e252-2d8d-525710adddb1", "outputs": {}, "resources": [ { "mode": "managed", "type": "aws_vpc", "name": "vpc", "provider": "provider.aws", "instances": [ { "schema_version": 1, "attributes": { "arn": "arn:aws:ec2:ap-northeast-1:485076298277:vpc/vpc-09a9f1827bfd851f4", "assign_generated_ipv6_cidr_block": false, "cidr_block": "10.0.0.0/16", "default_network_acl_id": "acl-0cd8abfed52e0e951", "default_route_table_id": "rtb-08c13269b1b26c9b8", "default_security_group_id": "sg-007ef29e563b6f9c7", "dhcp_options_id": "dopt-6c0f430b", "enable_classiclink": false, "enable_classiclink_dns_support": false, "enable_dns_hostnames": true, "enable_dns_support": true, "id": "vpc-09a9f1827bfd851f4", "instance_tenancy": "default", "ipv6_association_id": "", "ipv6_cidr_block": "", "main_route_table_id": "rtb-08c13269b1b26c9b8", "owner_id": "485076298277", "tags": { "Name": "vpc-tfstate-test" } }, "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjEifQ==" } ] } ] }

If you look at the contents, you will see that the information about the resources you just imported is saved

When Terraform is executed, it automatically determines whether to create, modify, or delete resources and creates them accordingly. This determination is made based on the difference between the tf file loaded at runtime and the contents written in tfstate

In other words, in order to manage specified existing resources on Terraform, you need to change the contents of tfstate, and terraform import is a command that reads the information of specified existing resources and adds them to tfstate

Run plan again

Now that we've run terraform import, let's run plan again

$ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. aws_vpc.vpc: Refreshing state... [id=vpc-09a9f1827bfd851f4] --------------------------------------------------------------------------- No changes. Infrastructure is up-to-date. This means that Terraform did not detect any differences between your configuration and real physical resources that exist. As a result, no actions need to be performed.

aws_vpc.vpc is loaded as a resource on Terraform.
Let's change enable_dns_hostnames to false.

$ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. aws_vpc.vpc: Refreshing state... [id=vpc-09a9f1827bfd851f4] --------------------------------------------------------------------------- An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # aws_vpc.vpc will be updated in-place ~ resource "aws_vpc" "vpc" { arn = "arn:aws:ec2:ap-northeast-1:485076298277:vpc/vpc-09a9f1827bfd851f4" assign_generated_ipv6_cidr_block = false cidr_block = "10.0.0.0/16" default_network_acl_id = "acl-0cd8abfed52e0e951" default_route_table_id = "rtb-08c13269b1b26c9b8" default_security_group_id = "sg-007ef29e563b6f9c7" dhcp_options_id = "dopt-6c0f430b" enable_classiclink = false enable_classiclink_dns_support = false ~ enable_dns_hostnames = true -> false enable_dns_support = true id = "vpc-09a9f1827bfd851f4" instance_tenancy = "default" main_route_table_id = "rtb-08c13269b1b26c9b8" owner_id = "485076298277" tags = { "Name" = "vpc-tfstate-test" } } Plan: 0 to add, 1 to change, 0 to destroy. --------------------------------------------------------------------------- Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.

It seems to be trying to change only the differences

summary

As stated on the import command explanation page (※2)

In other words, you need to write the actual tf file yourself while looking at the differences with tfstate. In the future, it seems that a function will be added to automatically generate tf files, but for now, the more targets there are, the more difficult it becomes..

To solve this problem, Terraformer (※3) has been released as open source software.
In my next blog post, I will explain how to use it.

Reference URL

*1 : https://www.terraform.io/docs/providers/aws/r/vpc.html
*2 : https://www.terraform.io/docs/import/index.html
*3 : https://github.com/GoogleCloudPlatform/terraformer

 

If you found this article useful, please click [Like]!
2
Loading...
2 votes, average: 1.00 / 12
42,098
X Facebook Hatena Bookmark pocket

The person who wrote this article

About the author

Yuki Teraoka

He joined Beyond in 2016 and is currently in his sixth year
as an infrastructure engineer working for an MSP, where he troubleshoots issues while also designing
and building infrastructure using public clouds such as AWS. Recently, he has been

using Hashicorp tools such as Terraform and Packer as part of the construction and operation automation
of container infrastructure such as Docker and Kubernetes, and he also plays the role of evangelist, speaking at external study groups and seminars.

・GitHub
https://github.com/nezumisannn

・Speaking history
https://github.com/nezumisannn/my-profile

・Presentation materials (SpeakerDeck)
https://speakerdeck.com/nezumisannn

・Certification:
AWS Certified Solutions Architect - Associate
Google Cloud Professional Cloud Architect