DevOps

Terraform Import Existing Resource: Ultimate Guide

Discover Terraform's import feature, understand challenges with earlier releases, and enhancements in the latest 1.5 config-driven feature

Quick Summary

  • On the other hand, the terraform apply command enables the implementation of the desired state of the resources defined in the configuration files, using provider plugins to interact with each cloud provider.
  • The terraform import module enables teams to bring existing resource objects under Terraform management, marking a significant advantage for mergers and acquisitions or standardization efforts.
  • One of the essential commands within the Terraform toolset is the terraform import command allowing the import of existing resources.

Infrastructure as code (IaC) has become a standard for managing complex IT infrastructures. Terraform, a key player in the IaC sphere, is quite familiar to DevOps engineers and developers alike. One of the essential commands within the Terraform toolset is the terraform import command allowing the import of existing resources. There are some challenges with the legacy terraform import command. However, with the release of Terraform 1.5, Hashicorp has introduced new import functionality. Let’s dive into Terraform import existing resources step-by-step and see how this is done in 1.5 and higher.

What is Terraform?

Terraform is a very popular player in Infrastructure as Code (IaC) solutions developed by HashiCorp. It offers a practical way for DevOps teams to define and manage resources across many cloud providers, including but not limited to AWS, Google Cloud, Azure and VMware vSphere.

The core function of Terraform revolves around writing declarative configuration files. These configuration files allow teams to describe their target environment in a human-readable format, thus enabling the automatic creation, modification, and destruction of infrastructure resources. This is accomplished using HashiCorp Configuration Language (HCL), the language used in the provider configuration, allowing for an efficient way to define resources.

Below, we are adding AWS resources using Terraform.

Creating AWS infrastructure with Terraform
Creating AWS infrastructure with Terraform

A noteworthy feature that sets Terraform apart is its ability to manage low-level and high-level cloud infrastructure components. Terraform covers everything from networking features like subnets and routing to higher-level components such as SaaS.

Using the terraform plan and terraform apply commands, Terraform allows teams to systematically plan and apply infrastructure changes. The terraform plan command enables teams to check their configurations and see exactly what actions Terraform will perform when the configurations are applied. It’s an essential step that prevents potential mishaps.

On the other hand, the terraform apply command enables the implementation of the desired state of the resources defined in the configuration files, using provider plugins to interact with each cloud provider. The results of these actions are then stored in a Terraform state file, which is used for maintaining and modifying the created resources.

What is Terraform import command?

But Terraform truly shines in its ability to import resources created into its management that already existed. The terraform import module enables teams to bring existing resource objects under Terraform management, marking a significant advantage for mergers and acquisitions or standardization efforts.

Terraform import command instructions
Terraform import command instructions

However, as efficient as the import command was, it had limitations for import operations. This is where Terraform 1.5 stepped in and revolutionized the way to import existing infrastructure into Terraform’s management. With a slew of new features like config-driven import, Terraform made the process of managing existing infrastructure resources more straightforward and less error-prone.

Breaking Down Terraform Import Syntax

The basic syntax of the Terraform import command is quite straightforward:

terraform import [options] ADDRESS ID

Here, ‘ADDRESS’ specifies the Terraform state address of the resource to import, and ‘ID’ identifies the specific resource in the existing infrastructure. The optional ‘options’ argument allows for additional flags to fine-tune the import process.

Despite its usefulness, the initial design of the import command had certain limitations, mainly that resources had to be imported one by one, the state was immediately modified without a preview, and the corresponding configurations were manually written. With the introduction of Terraform 1.5, these concerns have been addressed.

The Challenges with Terraform Import Prior to Version 1.5

The previous import command in Terraform had limitations, making importing existing infrastructure cumbersome. There are three limitations to note:

  1. One-by-one Resource Importation

  2. Risk of Accidental Resource Modifications or Deletions

  3. Manual Writing of Matching Resource Code

1. One-by-one Resource Importation

The earlier versions of Terraform only allowed resources to be imported one at a time. This was manageable for small infrastructures or for occasional use. But, when you had to bring a substantial infrastructure under Terraform management, the process became tedious and time-consuming. It also required a significant degree of manual intervention, increasing human error likelihood.

2. Risk of Accidental Resource Modifications or Deletions

Another major challenge was that the state was immediately modified after running the import command, with no opportunity to preview the results. This could lead to accidental resource modifications or deletions if an apply operation was executed on the shared state by another team member before the corresponding configuration was added. This lack of a preview step made the import process riskier, especially in a collaborative environment.

Below, working with Terraform version less than 1.5, you will need to understand the limitations and even concerns of using the terraform import command.

Legacy version of Terraform
Legacy version of Terraform

Manual Writing of Matching Resource Code

The import command was dependent on the corresponding resource code. It required the matching resource code to be manually written, often leading to a multi-step process of running plans, identifying the required attribute values, and achieving a clean run. This was an extra task, adding to the complexity of the import process and increasing the time taken to onboard resources onto Terraform.

While these limitations didn’t make the import command unworkable, they did add complexity and potential risks to the process. Therefore, a solution was sought to streamline and secure the import procedure, paving the way for config-driven import in Terraform 1.5.

Terraform 1.5: A Game-Changer for Importing Existing Infrastructure

Terraform 1.5 was a game-changer for importing existing infrastructure, introducing a config-driven import feature. This feature simplifies bringing resources under Terraform management as Terraform resource objects.

You can check the version of Terraform you are running using the terraform version command:

Recent version of Terraform with the new config driven import
Recent version of Terraform with the new config driven import

The config-driven import process introduces an import block in your Terraform code, replacing the previous import commands. The import block takes two parameters: the cloud resource ID and the resource address in the Terraform configuration.

For example, for an Amazon EC2 instance, the import block would look something like this:

import { 
     id = "i-abcd1234"
     to = "aws_instance.example"
}

In this example, the id refers to your Terraform configuration’s EC2 instance ID and the destination resource block. By doing so, the EC2 instance is recognized as an AWS resource and can be managed by Terraform.

Running the terraform plan command with the -generate-config-out parameter creates a Terraform configuration file with all the attributes of the imported resources. This allows automatic code generation, significantly reducing the need to create the corresponding resource code manually.

Once the Terraform configuration file is generated and reviewed, running a normal apply operation successfully imports the resources into the Terraform state. This results in a successful import that is more manageable and less prone to human errors.

Check Blocks for Enhanced Validation

Along with config-driven imports, Terraform 1.5 introduces check blocks. These blocks offer a more comprehensive validation of the provisioned infrastructure, allowing users to confirm that the final product aligns with their expectations. This top-level construct can reference all resources, data sources, and module outputs in the configuration, offering a more holistic perspective than its predecessors.

Here’s an example:

check "health_check" {
  data "http" "example" {
    url = "https://${aws_lb.example.dns_name}"
  }

  assert {
    condition     = data.http.example.status_code == 200
    error_message = "${data.http.example.url} returned an unhealthy status code"
  }
}

Terraform 1.5 import lab

Ok, so I have created just three resources using some Terraform code to build out a simple AWS environment, with a VPC, subnet, and an EC2 instance.

What I’m going to do is create the infrastructure with Terraform and then delete the state data. This will simulate a case where we have infrastructure unmanaged by Terraform. So, below we are deleting the state file.

Deleting the Terraform state file
Deleting the Terraform state file

First, we are going to create an import.tf file that contains the following similar code with the real identifiers in the real code:

import { 

     id = "i-1234123412341234"
     to = aws_instance.testec2
	 
}

import {

     id = "vpc-1234123412341234"
     to = aws_vpc.testvpc

}

import {

     id = "subnet-1234123412341234"
     to = aws_subnet.testsubnet

}

If you don’t have a configuration file that matches the import resources you are defining, you will see something like this:

Error that the import block target does not exist
Error that the import block target does not exist

So I do have the configuration file in the example, so let’s just copy back over the .tf file containing the configuration. After copying over the configuration file, running the terraform plan correctly shows that we have 3 to import and 0 to add, 0 to change, and importantly, 0 to destroy.

Running the plan after having the configuration file in place
Running the plan after having the configuration file in place

However, now let’s test out the new config-driven import capabilities. Let’s say we don’t have a configuration file that already contains the configuration which is a likely scenario if you are bringing in existing infrastructure to manage.

Let’s use the command:

terraform plan -generate-config-out=generated.tf

After running the command, as you can see below, we had several error messages. After all the function at this point is experimental as noted in the output.

Errors after generating the new config using the generate functionality
Errors after generating the new config using the generate functionality

However, after you use the -generate-config-out command, you can now run the terraform plan command to start testing your code after you get to the bottom of the errors in the output above. If you keep running the plan with the -generate parameter, it will keep trying to generate a new file. We want to work with the one we have at this point.

What I was able to do was either comment out missing resource requirements or just delete them out of the generated.tf file. What I would recommend is delete or comment them out one at a time and then run a terraform plan. After getting rid of the errors, the generated.tf code is now good.

Errors resolved and running a plan and apply
Errors resolved and running a plan and apply

After you have no errors, then you can run a terraform apply. This will actually add the resources into the terraform state data. At this point the process is just like creating new infrastructure for the import process. Type Yes to verify the apply.

Verifying the Terraform apply operation
Verifying the Terraform apply operation

As you can see, we have imported 3 resources as expected, our VPC, subnet, and EC2 instance.

Resources successfully imported using the new Terraform import functionality
Resources successfully imported using the new Terraform import functionality

Frequently Asked Questions

Can Terraform manage resources created manually or by other IaC tools?

Absolutely. One of the powerful features of Terraform is its ability to import existing resources into its management. By using the terraform import command, you can bring resources created manually or by other Infrastructure as Code (IaC) tools under Terraform management. This makes it a great choice for companies undergoing mergers and acquisitions or those looking to standardize their infrastructure management.

What is the terraform state file and why is it crucial?

The terraform state file is an essential component of Terraform. It stores the current state of your managed infrastructure and configuration. Terraform uses this file to map resources defined in your configuration files to real-world resources. The terraform state file also helps Terraform to track metadata and manage changes to your infrastructure.

What is an import block and how does it help with Terraform configurations?

Introduced in Terraform 1.5, the import block is a declarative approach to importing existing resources into Terraform management. It takes two parameters: the ID of the cloud resource and the HCL address of the new resource block. This feature makes the process of importing resources into Terraform easier and safer by allowing for planned import operations, reducing the risk of unexpected state modifications.

How does Terraform ensure that the infrastructure matches the configuration?

Terraform uses a technique known as ‘desired state management’. Essentially, you describe your desired infrastructure state in a Terraform configuration file, and Terraform works to make the actual infrastructure match this desired state. If a discrepancy is detected, Terraform will propose a plan to rectify it. You can then approve or modify this plan before Terraform executes it.

How does Terraform’s terraform plan command work?

The terraform plan command is essential for checking your configurations before applying them. This command shows Terraform’s actions, without making any actual changes. This way, you can ensure your changes are correct and safe before executing them with the terraform apply command.

What resources can be managed with Terraform?

Terraform is incredibly flexible and can manage a wide range of resources. From compute instances like EC2 instances to networking resources, database instances, and even higher-level services like DNS entries. Be sure to check the provider documentation for a list of all importable resources.

What is the terraform init command?

The terraform init command initializes a working directory containing Terraform configuration files. This command performs several tasks, such as downloading provider plugins, creating the backend for storing your state file, and setting up the necessary provider configurations. It’s an essential first step in any Terraform workflow.

Can Terraform manage resources across different cloud providers?

Yes, Terraform is cloud-agnostic and supports many cloud providers like AWS, Google Cloud, Azure, and many more. You can even manage multi-cloud deployments, allowing you to utilize the best offerings from each cloud provider in a single, unified infrastructure as code solution.

Does Terraform support validations of provisioned infrastructure?

Terraform 1.5 introduced a new ‘check blocks’ feature to validate provisioned infrastructure better. These blocks help ensure that the provisioned infrastructure functions as expected by defining assertions within the Terraform code, adding another layer of confidence and reliability to your IaC deployments.

Wrapping up

Introducing the import block in Terraform 1.5 has greatly improved managing resources in your infrastructure. It simplifies the import process, allowing you to work with numerous resources simultaneously while providing an opportunity to review changes before applying them.

The enhancements in Terraform 1.5, like config-driven import and checks, have made it even more powerful in managing cloud infrastructure. They have simplified importing existing infrastructure resources, allowing for a more efficient and error-free workflow. The next time you need to bring your existing resources under Terraform management, remember that with Terraform 1.5, the process has become a lot easier and safer.

Subscribe to VirtualizationHowto via Email 🔔

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Brandon Lee

Brandon Lee is the Senior Writer, Engineer and owner at Virtualizationhowto.com and has over two decades of experience in Information Technology. Having worked for numerous Fortune 500 companies as well as in various industries, Brandon has extensive experience in various IT segments and is a strong advocate for open source technologies. Brandon holds many industry certifications, loves the outdoors and spending time with family.

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.