This topic describes how to solve management problems with existing cloud resources by using Terraform.
Background information
This topic applies to the following O&M scenarios:
Scenario 1: Terraform is being used for the first time, but the web console, Alibaba Cloud CLI, ROS, or APIs have already been in use to create and manage resources.
Scenario 2: Terraform has already been in use to manage resources. Resource states need to remain unchanged if the properties of a resource are changed.
Scenario 3: All resources are defined in a template. Increasing resources do not cause difficulty in managing templates or resource states if the existing template is rebuilt or split.
Scenario 4: The new parameters from the latest providers need to be synchronized to original documents.
Terraform can use resource template definitions not only to create, change, and delete new resources, but also to import and manage resources that are outside of the Terraform management system through simple commands for centralized management.
Import existing resources
You can perform the following operations to import existing resources in Terraform:
Obtain resource IDs.
Query resources based on their IDs and obtain their properties.
Declare the resources to be imported in the template.
Terraform uses the template-driven method. You must declare resources to be imported in the template.
Complete resource template definitions.
After resources are imported, complete the resource definitions declared in the template based on resource properties.
Obtain resource IDs.
You can obtain resource IDs by using methods such as the web console, Alibaba Cloud CLI, and APIs. The simplest way is to enter simple query conditions through Terraform data sources. The following example shows how to obtain the ID of an SLB instance:
data "alicloud_slbs" "default" { name_regex = "for-demo*" } output "slb_ids" { value = data.alicloud_slbs.default.ids }
Run the terraform apply command to view the IDs of all qualified SLB instances:
$ terraform apply data.alicloud_slbs.default: Refreshing state... Apply complete! Resources: 0 added, 0 changed, 0 destroyed. Outputs: slb_ids = [ "lb-gw8vinrqxxxxxxxxxxx", "lb-gw8axostxxxxxxxxxxx", ]
Declare the resources to be imported in the template.
Similar to creating resources, you must declare the resources in the template before importing the resources to specify the storage path of the resources in the state. The following examples declare an SLB instance:
resource "alicloud_slb" "this" {}
You can import resources without defining specific parameters after a simple declaration. In Terraform, you can run the import command to import a resource. The complete command format is
Terraform import <Resource type>.<Resource name> <Resource ID>
.$ terraform import alicloud_slb.this lb-gw8vinrqxxxxxxxxxxx alicloud_slb.this: Importing from ID "lb-gw8vinrqxxxxxxxxxxx"... alicloud_slb.this: Import prepared! Prepared alicloud_slb for import alicloud_slb.this: Refreshing state... [id=lb-gw8vinrqxxxxxxxxxxx] 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.
Complete resource template definitions.
the template does not contain full definitions of the imported resources, so the template content is different from the content stored in the state after the resources are imported. When you run the plan command, an update is displayed.
$ 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. data.alicloud_slbs.default: Refreshing state... alicloud_slb.this: Refreshing state... [id=lb-gw8vinrqxxxxxxxxxxx] ------------------------------------------------------------------------ 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: # alicloud_slb.this will be updated in-place ~ resource "alicloud_slb" "this" { address = "47.254.181.122" ... ~ delete_protection = "on" -> "off" id = "id=lb-gw8vinrqxxxxxxxxxxx" ... ~ name = "for_demo-test" -> "tf-lb-20191108144235105700000001" ... } 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.
To keep the template consistent with the resource state, you must manually add absent parameter definitions in the template till no update is displayed when you run the plan command.
resource "alicloud_slb" "this" { delete_protection = "on" name = "for_demo-test" }
You must add the fields that cause the update. Run the plan command to check the results after you complete parameter definitions.
$ 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. data.alicloud_slbs.default: Refreshing state... alicloud_slb.this: Refreshing state... [id=lb-gw8vinrqtqx1ro1r94c96] ------------------------------------------------------------------------ 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.
The preceding information indicates that no further change is required and that the resource import process is complete.
Remove existing resources
Some problems may occur in practice: incorrect resources are imported, resourced are imported to incorrect paths, resource paths need to be modified, or some resources need to be retained permanently. A simple solution for these problems: remove the imported resources from the state and then import them again.
You can run the state rm command to remove resources. The complete command format is terraform state rm <Resource type>.<Resource name>
.
$ terraform state rm alicloud_slb.this
Removed alicloud_slb.this
Successfully removed 1 resource instance(s).
The state rm command only removes the specified resource from the state file and does not delete them. Therefore, you can import the resources again.
Summary
The following solutions can be used to cope with the preceding four scenarios:
Solution for scenario 1:
Run the terraform import command to import existing resources for centralized management with Terraform.
Solution for scenario 2:
You must determine the values of the parameter properties. If the values in the template are to be used, you must run the apply command and then change the values. If the values in the web console are to be used, you must add or modify the values in the template.
Solution for scenario 3:
Run the terraform state rm command to remove all resources to be rebuilt from the state. Then run the terraform import command to import the resources.
Solution for scenario 4:
Similar to the solution for scenario 3, remove the resources and then import them.
Terraform provides simple commands. The terraform import command can be used for centralized management of existing resources based on the principle that the template and state must have consistent content. You do not need to worry about whether resources are outside of the Terraform management system or whether resources are removed from the state.