EN 
09.03.2026 Františka WELCOME IN MY WORLD

This website is originally written in the Czech language. Most content is machine (AI) translated into English. The translation may not be exact and may contain errors.

Tento článek si můžete zobrazit v originální české verzi. You can view this article in the original Czech version.
Terraform a VMware Cloud Director - import existujících prostředků (VM)

Terraform and VMware Cloud Director - Importing Existing Resources (VMs)

| Petr Bouška - Samuraj |
The principle of Terraform is that it creates (or destroys) defined objects. It stores information in a state file (State) and uses it to detect the difference between the current and desired state. Resources created this way can be modified or destroyed by changing the configuration. If we want to use Terraform to modify resources that were created in a different way, we must import them into Terraform. This is not entirely straightforward. In the example, we will import all VMs from a specific vApp.
displayed: 289x (168 CZ, 121 EN) | Comments [0]

Note: The description in this article is based on Terraform version 1.14.4, VMware Cloud Director Provider version 3.14, and VMware Cloud Director 10.6.

Existing Objects and Terraform

Terraform can work with objects that are defined in its configuration (the resource block) and stored in the state file. If they do not exist in the State, it will attempt to create them.

Our infrastructure may contain a number of resources that were not created using Terraform. They were either created before we started using Terraform, or were later created in a different way (for example, by cloning a vApp). If we do not want to change the attributes of existing objects, we do not need to have them managed by Terraform.

If we only want to read some information, we can use data sources (the data block). The loaded data can be referenced in the code, but no changes can be made to it (it is read-only).

If we want to make changes to existing objects that Terraform does not know about, we must import them. We need to obtain their configuration and data in the State.

Import Using Terraform CLI

The oldest option is to use the Terraform CLI command terraform import. We must create a resource configuration (the resource block) and the command will then perform the import into the State. It is better suited for importing a single object. The command requires a number of parameters. It is complicated and inefficient.

Import Using HCL

To import existing infrastructure resources into Terraform, we can manually create an import block. We also need a resource block to go with it. We can create it manually, or alternatively have it generated using terraform plan -generate-config-out. All resource attributes are stored in the state file, but it is not necessary to define all of them in the resource block.

Additional options are described in Import existing resources in bulk.

General Procedure

  • define the configuration (the resource block) for each resource we want to import
  • add a corresponding import block for each resource we want to import
  • run terraform plan and verify the import plan
  • run terraform apply to import the resources and update the Terraform State (only imports should occur, not resource creation)
  • we can remove the import block from the configuration (even though re-running it does not perform the import again)

The Import Block

We must specify the target resource address (to), which consists of the resource type and label (how we reference the resource in the configuration). This must match the resource block we have prepared. And the identity of the existing resource (id), which depends on the provider. For VMware Cloud Director, this is a path composed of component names, for example for a VM: Org.vDC.vApp.VM.

import {
  to = TYPE.LABEL
  id =  "<RESOURCE-ID>"
}

To import multiple objects (instances) of the same type, we can use the meta-arguments for_each and count in the target resource.

Generating Configuration

Note: This feature has been available in Terraform since version 1.5, but is still marked as experimental.

Terraform generates code for resources defined in import blocks that do not yet exist in our configuration. It creates HCL containing Terraform's best guess at the appropriate value for each resource argument. It is recommended to review and adjust the generated content (remove some arguments, fix values, etc.).

To generate the configuration, the Terraform CLI command is used with a parameter specifying the name of the new file (path) where the configuration will be saved.

terraform plan -generate-config-out="generated_resources.tf"

Problem with Specifying the Parameter

When running the Terraform CLI from the terminal in Visual Studio Code (i.e. within PowerShell), I was getting an error.

PS D:\VCD-terraform> terraform plan -generate-config-out=generated.tf

- Error: Too many command line arguments
-
- To specify a working directory for the plan, use the global -chdir flag.

For more help on using this command, run:
  terraform plan -help

The solution is to specify the parameter with two dashes --.

PS D:\VCD-terraform> terraform plan --generate-config-out=generated.tf

The vcd_resource_list Data Source

The VMware Cloud Director provider offers a special data source called vcd_resource_list. It allows you to retrieve a list of existing resources of a specific type and represent them in various formats. One option is to generate an import file.

data "vcd_resource_list" "list_of_nets" {
  name             = "list_of_nets"
  resource_type    = "network"
  list_mode        = "import"
  import_file_name = "network-import.tf"
}

Importing All Existing VMs from a Given vApp

Let us walk through an example that demonstrates the most automated import solution possible for all existing VMs from a given vApp.

Individual Steps

  • create the file import.tf with the vcd_resource_list data source
  • use the Terraform CLI command terraform plan to generate the import file import-vms_from_vapp.tf
  • use the Terraform CLI command terraform plan --generate-config-out=generated.tf to generate the configuration file generated.tf
  • use the Terraform CLI command terraform apply to import into the state file
  • we can delete the files import.tf and import-vms_from_vapp.tf
  • we can use the Terraform CLI command terraform plan to verify that the infrastructure matches the configuration, confirming the import was successful
  • we can modify the configuration and apply changes; if we want to perform operations sequentially (by default, 10 operations are performed in parallel), we can use terraform apply -parallelism=1
Visual Studio Code - Terraform project - import resources

The Import.tf File

Our Terraform project requires a basic configuration for connecting to the VMware Cloud Director provider. We create a file, which we name import.tf here, and add the vcd_resource_list configuration to it. The important fields are the resource type (VM), the parent name (vApp), the import mode, and the filename for saving the import blocks.

data "vcd_resource_list" "import_vms_from_vapp" {
  name             = "import_vms_from_vapp"
  resource_type    = "vcd_vapp_vm"
  parent           = "Demo-vApp"
  list_mode        = "import"
  import_file_name = "import-vms_from_vapp.tf"
}

Generating the Import File

Once we have the data source ready, we simply use the Terraform CLI command to generate the import file.

PS D:\VCD-terraform> terraform plan
data.vcd_resource_list.import_vms_from_vapp: Reading...
data.vcd_resource_list.import_vms_from_vapp: Read complete after 6s [id=import_vms_from_vapp]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

In the current directory, we will find the generated file import-vms_from_vapp.tf, whose contents may look roughly as follows.

import {
  to = vcd_vapp_vm.Demo-VM-2537464da65e
  id = "Firma.Firma vDC.Demo-vApp.Demo-VM"
}

import {
  to = vcd_vapp_vm.Next-VM-36979c7d5244
  id = "Firma.Firma vDC.Demo-vApp.Next-VM"
}

Generating the Configuration File

In the next step, we use the import file and have the configuration generated for the individual objects.

PS D:\VCD-terraform> terraform plan --generate-config-out=generated.tf
data.vcd_resource_list.import_vms_from_vapp: Reading...
vcd_vapp_vm.Next-VM-36979c7d5244: Preparing import... [id=Firma.Firma vDC.Demo-vApp.Next-VM]
vcd_vapp_vm.Demo-VM-2537464da65e: Preparing import... [id=Firma.Firma vDC.Demo-vApp.Demo-VM]
vcd_vapp_vm.Demo-VM-2537464da65e: Refreshing state... [id=urn:vcloud:vm:4415c19d-a813-40ca-b2a3-2537464da65e]
vcd_vapp_vm.Next-VM-36979c7d5244: Refreshing state... [id=urn:vcloud:vm:da0d2be9-3117-464e-88ab-36979c7d5244]
data.vcd_resource_list.import_vms_from_vapp: Read complete after 5s [id=import_vms_from_vapp]

Terraform will perform the following actions:

  # vcd_vapp_vm.Demo-VM-2537464da65e will be imported
  # (config will be generated)
    resource "vcd_vapp_vm" "Demo-VM-2537464da65e" {

...

Plan: 2 to import, 0 to add, 0 to change, 0 to destroy.

- Warning: Config generation is experimental
-
- Generating configuration during import is currently experimental, and the generated configuration format may change in future
 versions.

----------------------------------------------------------------------------------

Terraform has generated configuration and written it to generated.tf. Please review the configuration and edit it as necessary
 before adding it to version control.
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run
 "terraform apply" now.

In the current directory, we will find the generated file generated.tf, which contains resource blocks for the individual VMs with complete arguments.

Importing into the State File

Finally, we apply the changes, during which the combined import and resource blocks are used and the resources are imported.

PS D:\VCD-terraform> terraform apply
vcd_vapp_vm.Demo-VM-2537464da65e: Preparing import... [id=Firma.Firma vDC.Demo-vApp.Demo-VM]
vcd_vapp_vm.Next-VM-36979c7d5244: Preparing import... [id=Firma.Firma vDC.Demo-vApp.Next-VM]
data.vcd_resource_list.import_vms_from_vapp: Reading...
vcd_vapp_vm.Demo-VM-2537464da65e: Refreshing state... [id=urn:vcloud:vm:4415c19d-a813-40ca-b2a3-2537464da65e]
vcd_vapp_vm.Next-VM-36979c7d5244: Refreshing state... [id=urn:vcloud:vm:da0d2be9-3117-464e-88ab-36979c7d5244]
data.vcd_resource_list.import_vms_from_vapp: Read complete after 5s [id=import_vms_from_vapp]

Terraform will perform the following actions:

  # vcd_vapp_vm.Demo-VM-bb229083e6ec will be imported
    resource "vcd_vapp_vm" "Demo-VM-bb229083e6ec" {

...

Plan: 2 to import, 0 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

vcd_vapp_vm.Next-VM-36979c7d5244: Importing... [id=Firma.Firma vDC.Demo-vApp.Next-VM]
vcd_vapp_vm.Next-VM-36979c7d5244: Import complete [id=Firma.Firma vDC.Demo-vApp.Next-VM]
vcd_vapp_vm.Demo-VM-2537464da65e: Importing... [id=Firma.Firma vDC.Demo-vApp.Demo-VM]
vcd_vapp_vm.Demo-VM-2537464da65e: Import complete [id=Firma.Firma vDC.Demo-vApp.Demo-VM]

Apply complete! Resources: 2 imported, 0 added, 0 changed, 0 destroyed.
Author:

Related articles:

Infrastructure as Code - Terraform

Infrastructure as Code (IaC) tools allow you to define, deploy, and manage infrastructure in a declarative (or imperative) way using configuration files. We describe the resources (servers, networks, storage, etc.) in a text file that defines the desired state. The tool ensures that the real environment matches the definition. For now, we will focus on the Terraform tool.

Virtualization

Articles from popular topics about virtualization of servers and workstations.

If you want write something about this article use comments.

Comments

There are no comments yet.

Add comment

Insert tag: strong em link

Help:
  • maximum length of comment is 2000 characters
  • HTML tags are not allowed (they will be removed), you can use only the special tags listed above the input field
  • new line (ENTER) ends paragraph and start new one
  • when you respond to a comment, put the original comment number in squar brackets at the beginning of the paragraph (line)