One place for hosting & domains

      Existing

      How To Import Existing DigitalOcean Assets into Terraform


      The author selected the Free and Open Source Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Terraform is an infrastructure as code tool created by HashiCorp that helps developers with deploying, updating, and removing different assets of their infrastructure in an efficient and more scalable way.

      Developers can use Terraform to organize different environments, track changes through version control, and automate repetitive work to limit human error. It also provides a way for teams to collaborate on improving their infrastructure through shared configurations.

      In this tutorial you’ll import existing DigitalOcean infrastructure into Terraform. By the end of this tutorial you’ll be able to use Terraform for all of your existing infrastructure in addition to creating new assets.

      Prerequisites

      Step 1 — Installing Terraform Locally

      In this first step you’ll install Terraform on your local machine. This step details the installation of the Linux binary. If you use Windows or Mac, you can check the Download Terraform page on the Terraform website.

      Move to the folder you want to download Terraform to on your local machine, then use the wget tool to download the Terraform 0.12.12 binary:

      • cd /tmp
      • wget https://releases.hashicorp.com/terraform/0.12.12/terraform_0.12.12_linux_amd64.zip

      To check if the sha256 checksum is the same value provided on the Terraform website, you’ll download the checksum file with the following command:

      • wget -q https://releases.hashicorp.com/terraform/0.12.12/terraform_0.12.12_SHA256SUMS

      Then run the following command to verify the checksums:

      • sha256sum -c --ignore-missing terraform_0.12.12_SHA256SUMS

      The SHA256SUMS file you downloaded lists the filenames and their hashes. This command will look for the same file terraform_0.12.12_SHA256SUMS locally and then check that the hashes match by using the -c flag. Since this file has more than one filename and its platform listed, you use the --ignore-missing flag to avoid errors in your output because you don’t have a copy of the other files.

      You will see output like the following:

      Output

      terraform_0.12.12_linux_amd64.zip: OK

      Use unzip to extract the binary:

      • sudo unzip terraform_0.12.12_linux_amd64.zip -d /usr/local/bin/

      Now check if Terraform is installed properly by checking the version:

      You’ll see output similar to the following:

      Output

      Terraform v0.12.12

      You’ve installed Terraform to your local machine, you’ll now prepare the configuration files.

      Step 2 — Preparing Terraform Configuration Files

      In this step you’ll import your existing assets into Terraform by creating a project directory and writing configuration files. Since Terraform doesn’t support generating configs from the import command at this time, you need to create those configurations manually.

      Run the following command to create your project directory:

      • mkdir -p do_terraform_import

      Then move into that directory with:

      Within this step you’ll create three additional files that will contain the required configurations. Your directory structure for this project will look like the following:

      ├── digitalocean_droplet.tf
      ├── digitalocean_firewall.tf
      └── provider.tf
      

      To begin you’ll create the file provider.tf to define your DigitalOcean Access Token as an environment variable instead of hardcoding it into your configuration.

      Warning: Your access token gives access to your complete infrastructure with unrestricted access, so treat it as such. Be sure that you’re the only one who has access to the machine where that token is stored.

      Besides your access token, you’ll also specify which provider you want to use. In this tutorial that’s digitalocean. For a full list of available Data Sources and Resources for DigitalOcean with Terraform, visit the Providers page on their website.

      Create and edit provider.tf with the following command:

      Add the following content into the provider.tf file:

      provider.tf

      variable "do_token" {}
      
      provider "digitalocean" {
          token   = "${var.do_token}"
          version = "1.9.1"
          }
      

      In this file you add your DigitalOcean Access Token as a variable, which Terraform will use as identification for the DigitalOcean API. You also specify the version of the DigitalOcean provider plugin. Terraform recommends that you specify which version of the provider you’re using so that future updates don’t potentially break your current setup.

      Now you’ll create the digitalocean_droplet.tf file. Here you’ll specify the resource that you’re going to use, in this case: droplet.

      Create the file with the following command:

      • nano digitalocean_droplet.tf

      Add the following configuration:

      digitalocean_droplet.tf

      resource "digitalocean_droplet" "do_droplet" {
          name   = "testing-terraform"
          region = "fra1"
          tags   = ["terraform-testing"]
          count  = "1"
      }
      

      Here you specify four parameters:

      • name: The Droplet name.

      • region: The region that the Droplet is located in.

      • tags: A list of the tags that are applied to this Droplet.

      • count: The number of resources needed for this configuration.

      Next you’ll create a configuration file for your firewall. Create the file digitalocean_firewall.tf with the following command:

      • nano digitalocean_firewall.tf

      Add the following content to the file:

      digitalocean_firewall.tf

      resource "digitalocean_firewall" "do_firewall" {
        name  = "testing-terraform-firewall"
        tags  = ["terraform-testing"]
        count = "1"
      }
      

      Here you specify the name of the firewall you wish to import and the tags of the Droplets to which the firewall rules apply. Finally the count value of 1 defines the required number of the particular resource.

      Note: You can include firewall resources in the digitalocean_droplet.tf file as well, however if you have multiple environments where multiple Droplets share the same firewall, it’s a good idea to separate it in case you only want to remove a single Droplet. This will then leave the firewall unaffected.

      Now it’s time to initialize those changes so Terraform can download the required dependencies. You will use the terraform init command for this, which will allow you to initialize a working directory containing Terraform configuration files.

      Run this command from your project directory:

      You’ll see the following output:

      Output

      Terraform has been successfully initialized!

      Terraform has successfully prepared the working directory by downloading plugins, searching for modules, and so on. Next you’ll begin importing your assets to Terraform.

      Step 3 — Importing Your Assets to Terraform

      In this step, you’ll import your DigitalOcean assets to Terraform. You’ll use doctl to find the ID numbers of your Droplets before importing your assets. You’ll then check the import configuration with the terraform show and terraform plan commands.

      To begin, you’ll export your DigitalOcean Access Token as an environment variable, which you’ll then inject into Terraform during runtime.

      Export it as an environment variable into your current shell session with the following command:

      • export DO_TOKEN="YOUR_TOKEN"

      In order to import your existing Droplet and firewall you’ll need their ID numbers. You can use doctl, the command line interface for the DigitalOcean API. Run the following command to list your Droplets and access their IDs:

      • doctl compute droplet list

      You’ll see output similar to the following:

      Output

      ID Name Public IPv4 Private IPv4 Public IPv6 Memory VCPUs Disk Region Image Status Tags Features Volumes DROPLET-ID DROPLET-NAME DROPLET-IPv4 1024 1 25 fra1 Ubuntu 18.04.3 (LTS) x64 active DROPLET-ID DROPLET-NAME DROPLET-IPv4 2048 1 50 fra1 Ubuntu 18.04.3 (LTS) x64 active DROPLET-ID DROPLET-NAME DROPLET-IPv4 1024 1 25 fra1 Ubuntu 18.04.3 (LTS) x64

      Now you’ll import your existing Droplet and firewall into Terraform:

      • terraform import -var "do_token=${DO_TOKEN}" digitalocean_droplet.do_droplet DROPLET_ID

      You use the -var flag to specify your DigitalOcean Access Token value that you previously exported to your shell session. This is needed so the DigitalOcean API can verify who you are and apply changes to your infrastructure.

      Now run the same command for your firewall:

      • terraform import -var "do_token=${DO_TOKEN}" digitalocean_firewall.do_firewall FIREWALL_ID

      You’ll check that the import was successful by using the terraform show command. This command provides human-readable output of your infrastructure state. It can be used to inspect a plan to ensure that wanted changes are going to be executed, or to inspect the current state as Terraform sees it.

      In this context state refers to the mapping of your DigitalOcean assets to the Terraform configuration that you’ve written and the tracking of metadata. This allows you to confirm that there’s no difference between existing DigitalOcean assets that you want to import and assets that Terraform is keeping track of:

      You’ll see output similar to this:

      Output

      . . . # digitalocean_droplet.do_droplet: resource "digitalocean_droplet" "do_droplet" { backups = false created_at = "2020-02-03T16:12:02Z" disk = 25 id = "DROPLET-ID" image = "DROPLET-IMAGE" ipv4_address = "DROPLET-IP" ipv6 = false locked = false memory = 1024 monitoring = false name = "testing-terraform-0" price_hourly = 0.00744 price_monthly = 5 private_networking = false region = "fra1" resize_disk = true size = "s-1vcpu-1gb" status = "active" tags = [ "terraform-testing", ] urn = "DROPLET-URN" vcpus = 1 volume_ids = [] . . . }

      You’ll see two resources in the output along with their attributes.

      After you import your Droplet and firewall into Terraform state, you need to make sure that configurations represent the current state of the imported assets. To do this, you’ll specify your Droplet’s image and its size. You can find these two values in the output of terraform show for digitalocean_droplet.do_droplet resource.

      Open the digitalocean_droplet.tf file:

      • nano digitalocean_droplet.tf

      In this tutorial:

      • The operating system image used for our existing Droplet is ubuntu-16-04-x64.
      • The region your Droplet is located in is fra1.
      • The Droplet tag for your existing Droplet is terraform-testing.

      The Droplet you imported using the configuration in digitalocean_droplet.tf will look like this:

      digitalocean_droplet.tf

      resource "digitalocean_droplet" "do_droplet" {
          image   = "ubuntu-16-04-x64"
          name    = "testing-terraform"
          region  = "fra1"
          size    = "s-1vcpu-1gb"
          tags    = ["terraform-testing"]
      }
      

      Next you’ll add in the firewall rules. In our example, open ports for inbound traffic are 22, 80, and 443. All ports are opened for outbound traffic. You can adjust this configuration accordingly to your open ports.

      Open digitalocean_firewall.tf:

      • nano digitalocean_firewall.tf

      Add the following configuration:

      digitalocean_firewall.tf

      resource "digitalocean_firewall" "do_firewall" {
        name  = "testing-terraform-firewall"
        tags  = ["terraform-testing"]
        count = "1"
      
        inbound_rule {
            protocol                = "tcp"
            port_range              = "22"
            source_addresses        = ["0.0.0.0/0", "::/0"]
          }
        inbound_rule {
            protocol                = "tcp"
            port_range              = "80"
            source_addresses        = ["0.0.0.0/0", "::/0"]
          }
        inbound_rule {
            protocol                = "tcp"
            port_range              = "443"
            source_addresses        = ["0.0.0.0/0", "::/0"]
          }
      
        outbound_rule {
            protocol                = "tcp"
            port_range              = "all"
            destination_addresses   = ["0.0.0.0/0", "::/0"]
          }
        outbound_rule {
            protocol                = "udp"
            port_range              = "all"
            destination_addresses   = ["0.0.0.0/0", "::/0"]
          }
        outbound_rule {
            protocol                = "icmp"
            destination_addresses   = ["0.0.0.0/0", "::/0"]
          }
      }
      

      These rules replicate the state of the existing example firewall. If you’d like to limit traffic to different IP addresses, different ports, or different protocol, you can adjust the file to replicate your existing firewall.

      After you’ve updated your Terraform files, you’ll use the plan command to see if changes you made replicate state of existing assets on DigitalOcean.

      The terraform plan command is used as a dry run. With this command you can check if changes Terraform is going to make are the changes you want to make. It is a good idea to always run this command for confirmation before applying changes.

      Run terraform plan with the following:

      • terraform plan -var "do_token=$DO_TOKEN"

      You’ll see output similar to the following output:

      Output

      No changes. Infrastructure is up-to-date.

      You’ve successfully imported existing DigitalOcean assets in Terraform, and now you can make changes to your infrastructure through Terraform without the risk of accidentally deleting or modifying existing assets.

      Step 4 — Creating New Assets via Terraform

      In this step you’ll add two additional Droplets to your existing infrastructure. Adding assets in this way to your existing infrastructure can be useful, for example, if you have a live website and don’t want to make any potentially breaking changes to that website while working on it. Instead you can add one more Droplet to use as a development environment and work on your project in the same environment as the production Droplet, without any of the potential risk.

      Now open digitalocean_droplet.tf to add the rules for your new Droplets:

      • nano digitalocean_droplet.tf

      Add the following lines to your file:

      digitalocean_droplet.tf

      resource "digitalocean_droplet" "do_droplet" {
          image   = "ubuntu-16-04-x64"
          name    = "testing-terraform"
          region  = "fra1"
          size    = "s-1vcpu-1gb"
          tags    = ["terraform-testing"]
          count   = "1"
      }
      
      resource "digitalocean_droplet" "do_droplet_new" {
          image   = "ubuntu-18-04-x64"
          name    = "testing-terraform-${count.index}"
          region  = "fra1"
          size    = "s-1vcpu-1gb"
          tags    = ["terraform-testing"]
          count   = "2"
      }
      

      You use the count meta-argument to tell Terraform how many Droplets with the same specifications you want. These new Droplets will also be added to your existing firewall as you specify the same tag as per your firewall.

      Apply these rules to check the changes you’re specifying in digitalocean_droplet.tf:

      • terraform plan -var "do_token=$DO_TOKEN"

      Verify that the changes you want to make are replicated in the output of this command.

      You’ll see output similar to the following:

      Output

      . . . # digitalocean_droplet.do_droplet_new[1] will be created + resource "digitalocean_droplet" "do_droplet_new" { + backups = false + created_at = (known after apply) + disk = (known after apply) + id = (known after apply) + image = "ubuntu-18-04-x64" + ipv4_address = (known after apply) + ipv4_address_private = (known after apply) + ipv6 = false + ipv6_address = (known after apply) + ipv6_address_private = (known after apply) + locked = (known after apply) + memory = (known after apply) + monitoring = false + name = "testing-terraform-1" + price_hourly = (known after apply) + price_monthly = (known after apply) + private_networking = true + region = "fra1" + resize_disk = true + size = "s-1vcpu-1gb" + status = (known after apply) + tags = [ + "terraform-testing", ] + urn = (known after apply) + vcpus = (known after apply) + volume_ids = (known after apply) } Plan: 2 to add, 1 to change, 0 to destroy.

      Once you’re satisfied with the output, use the terraform apply command to apply the changes you’ve specified to the state of the configuration:

      • terraform apply -var "do_token=$DO_TOKEN"

      Confirm the changes by entering yes on the command line. After successful execution, you’ll see output similar to the following:

      Output

      . . . digitalocean_droplet.do_droplet_new[1]: Creating... digitalocean_droplet.do_droplet_new[0]: Creating... digitalocean_firewall.do_firewall[0]: Modifying... [id=FIREWALL-ID] digitalocean_firewall.do_firewall[0]: Modifications complete after 1s [id=FIREWALL-ID] digitalocean_droplet.do_droplet_new[0]: Still creating... [10s elapsed] digitalocean_droplet.do_droplet_new[1]: Still creating... [10s elapsed] digitalocean_droplet.do_droplet_new[0]: Creation complete after 16s [id=DROPLET-ID] digitalocean_droplet.do_droplet_new[1]: Still creating... [20s elapsed] digitalocean_droplet.do_droplet_new[1]: Creation complete after 22s [id=DROPLET-ID] Apply complete! Resources: 2 added, 1 changed, 0 destroyed.

      You’ll see two new Droplets in your DigitalOcean web panel:
      New Droplets

      You’ll also see them attached to your existing firewall:
      Existing Firewall

      You’ve created new assets with Terraform using your existing assets. To learn how to destroy these assets you can optionally complete the next step.

      Step 5 — Destroying Imported and Created Assets (Optional)

      In this step, you’ll destroy assets that you’ve imported and created by adjusting the configuration.

      Begin by opening digitalocean_droplet.tf:

      • nano digitalocean_droplet.tf

      In the file, set the count to 0 as per the following:

      digitalocean_droplet.tf

      resource "digitalocean_droplet" "do_droplet" {
          image   = "ubuntu-16-04-x64"
          name    = "testing-terraform"
          region  = "fra1"
          size    = "s-1vcpu-1gb"
          tags    = ["terraform-testing"]
          count   = "0"
      }
      
      resource "digitalocean_droplet" "do_droplet_new" {
          image   = "ubuntu-18-04-x64"
          name    = "testing-terraform-${count.index}"
          region  = "fra1"
          size    = "s-1vcpu-1gb"
          tags    = ["terraform-testing"]
          count   = "0"
      }
      

      Save and exit the file.

      Open your firewall configuration file to alter the count as well:

      • nano digitalocean_firewall.tf

      Set the count to 0 like the following highlighted line:

      digitalocean_firewall.tf

      resource "digitalocean_firewall" "do_firewall" {
        name  = "testing-terraform-firewall"
        tags  = ["terraform-testing"]
        count = "0"
      
        inbound_rule {
            protocol                = "tcp"
            port_range              = "22"
            source_addresses        = ["0.0.0.0/0", "::/0"]
          }
        inbound_rule {
            protocol                = "tcp"
            port_range              = "80"
            source_addresses        = ["0.0.0.0/0", "::/0"]
          }
        inbound_rule {
            protocol                = "tcp"
            port_range              = "443"
            source_addresses        = ["0.0.0.0/0", "::/0"]
          }
      
        outbound_rule {
            protocol                = "tcp"
            port_range              = "all"
            destination_addresses   = ["0.0.0.0/0", "::/0"]
          }
        outbound_rule {
            protocol                = "udp"
            port_range              = "all"
            destination_addresses   = ["0.0.0.0/0", "::/0"]
          }
        outbound_rule {
            protocol                = "icmp"
            destination_addresses   = ["0.0.0.0/0", "::/0"]
          }
      }
      

      Save and exit the file.

      Now apply those changes with the following command:

      • terraform apply -var "do_token=${DO_TOKEN}"

      Terraform will ask you to confirm if you wish to destroy the Droplets and firewall. This will destroy all assets you imported and created via Terraform, so ensure you verify that you wish to proceed before typing yes.

      You’ll see output similar to:

      Output

      . . . digitalocean_droplet.do_droplet[0]: Destroying... [id=YOUR-DROPLET-ID]] digitalocean_droplet.do_droplet_new[0]: Destroying... [id=YOUR-DROPLET-ID] digitalocean_droplet.do_droplet_new[1]: Destroying... [id=YOUR-DROPLET-ID] digitalocean_firewall.do_firewall[0]: Destroying... [id=YOUR-FIREWALL-ID] digitalocean_firewall.do_firewall[0]: Destruction complete after 1s digitalocean_droplet.do_droplet_new[1]: Still destroying... [id=YOUR-DROPLET-ID, 10s elapsed] digitalocean_droplet.do_droplet[0]: Still destroying... [id=YOUR-DROPLET-ID, 10s elapsed] digitalocean_droplet.do_droplet_new[0]: Still destroying... [id=YOUR-DROPLET-ID, 10s elapsed] digitalocean_droplet.do_droplet_new[1]: Still destroying... [id=YOUR-DROPLET-ID, 20s elapsed] digitalocean_droplet.do_droplet_new[0]: Still destroying... [id=YOUR-DROPLET-ID, 20s elapsed] digitalocean_droplet.do_droplet[0]: Still destroying... [id=YOUR-DROPLET-ID, 20s elapsed] digitalocean_droplet.do_droplet_new[1]: Destruction complete after 22s digitalocean_droplet.do_droplet[0]: Destruction complete after 22s digitalocean_droplet.do_droplet_new[0]: Destruction complete after 22s Apply complete! Resources: 0 added, 0 changed, 4 destroyed.

      You’ve deleted all assets managed by Terraform. This is a useful workflow if you no longer need an asset or are scaling down.

      Conclusion

      In this tutorial you installed Terraform, imported existing assets, created new assets, and optionally destroyed those assets. You can scale this workflow to a larger project, such as deploying a production-ready Kubernetes cluster. Using Terraform you could manage all of the nodes, DNS entries, firewalls, storage, and other assets, as well as use version control to track changes and collaborate with a team.

      To explore further features of Terraform read their documentation. You can also read DigitalOcean’s Terraform content for further tutorials and Q&A.



      Source link

      Import Existing Infrastructure to Terraform


      Updated by Linode Contributed by Linode

      Terraform is an orchestration tool that uses declarative code to build, change, and version infrastructure that is made up of server instances and services. You can use Linode’s official Terraform provider to interact with Linode services. Existing Linode infrastructure can be imported and brought under Terraform management. This guide will describe how to import existing Linode infrastructure into Terraform using the official Linode provider plugin.

      Before You Begin

      1. Terraform and the Linode Terraform provider should be installed in your development environment. You should also have a basic understanding of Terraform resources. To install and learn about Terraform, read our Use Terraform to Provision Linode Environments guide.

      2. To use Terraform you must have a valid API access token. For more information on creating a Linode API access token, visit our Getting Started with the Linode API guide.

      3. This guide uses the Linode CLI to retrieve information about the Linode infrastructure you will import to Terraform. For more information on the setup, installation, and usage of the Linode CLI, check out the Using the Linode CLI guide.

      Terraform’s Import Command

      Throughout this guide the terraform import command will be used to import Linode resources. At the time of writing this guide, the import command does not generate a Terraform resource configuration. Instead, it imports your existing resources into Terraform’s state.

      State is Terraform’s stored JSON mapping of your current Linode resources to their configurations. You can access and use the information provided by the state to manually create a corresponding resource configuration file and manage your existing Linode infrastructure with Terraform.

      Additionally, there is no current way to import more than one resource at a time. All resources must be individually imported.

      Caution

      When importing your infrastructure to Terraform, failure to accurately provide your Linode service’s ID information can result in the unwanted alteration or destruction of the service. Please follow the instructions provided in this guide carefully. It might be beneficial to use multiple Terraform Workspaces to manage separate testing and production infrastructures.

      Import a Linode to Terraform

      Retrieve Your Linode’s ID

      1. Using the Linode CLI, retrieve a list of all your Linode instances and find the ID of the Linode you would like to manage under Terraform:

        linode-cli linodes list --json --pretty
        
          
        [
          {
            "id": 11426126,
            "image": "linode/debian9",
            "ipv4": [
            "192.0.2.2"
            ],
            "label": "terraform-import",
            "region": "us-east",
            "status": "running",
            "type": "g6-standard-1"
          }
        ]
        
        

        This command will return a list of your existing Linodes in JSON format. From the list, find the Linode you would like to import and copy down its corresponding id. In this example, the Linode’s ID is 11426126. You will use your Linode’s ID to import your Linode to Terraform.

      Create An Empty Resource Configuration

      1. Ensure you are in your Terraform project directory. Create a Terraform configuration file to manage the Linode instance you will import in the next section. Your file can be named anything you like, but it must end in .tf. Add a Linode provider block with your API access token and an empty linode_instance resource configuration block in the file:

        Note

        The example resource block defines example_label as the label. This can be changed to any value you prefer. This label is used to reference your Linode resource configuration within Terraform, and does not have to be the same label originally assigned to the Linode when it was created outside of Terraform.

        linode_import.tf
        1
        2
        3
        4
        5
        
        provider "linode" {
            token = "your_API_access_token"
        }
        
        resource "linode_instance" "example_label" {}

      Import Your Linode to Terraform

      1. Run the import command, supplying the linode_instance resource’s label, and the Linode’s ID that was retrieved in the Retrieve Your Linode’s ID section :

        terraform import linode_instance.example_label linodeID
        

        You should see a similar output:

          
        linode_instance.example_label: Importing from ID "11426126"...
        linode_instance.example_label: Import complete!
          Imported linode_instance (ID: 11426126)
        linode_instance.example_label: Refreshing state... (ID: 11426126)
        
        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.
        
        

        This command will create a terraform.tfstate file with information about your Linode. You will use this information to fill out your resource configuration.

      2. To view the information created by terraform import, run the show command. This command will display a list of key-value pairs representing information about the imported Linode instance.

        terraform show
        

        You should see an output similar to the following:

          
        linode_instance.example_label:
          id = 11426126
          alerts.# = 1
          alerts.0.cpu = 90
          alerts.0.io = 10000
          alerts.0.network_in = 10
          alerts.0.network_out = 10
          alerts.0.transfer_quota = 80
          backups.# = 1
          boot_config_label = My Debian 9 Disk Profile
          config.# = 1
          config.0.comments =
          config.0.devices.# = 1
          config.0.devices.0.sda.# = 1
          config.0.devices.0.sda.0.disk_id = 24170011
          config.0.devices.0.sda.0.disk_label = Debian 9 Disk
          config.0.devices.0.sda.0.volume_id = 0
          config.0.devices.0.sdb.# = 1
          config.0.devices.0.sdb.0.disk_id = 24170012
          config.0.devices.0.sdb.0.disk_label = 512 MB Swap Image
          config.0.devices.0.sdb.0.volume_id = 0
          config.0.devices.0.sdc.# = 0
          config.0.devices.0.sdd.# = 0
          config.0.devices.0.sde.# = 0
          config.0.devices.0.sdf.# = 0
          config.0.devices.0.sdg.# = 0
          config.0.devices.0.sdh.# = 0
          config.0.helpers.# = 1
          config.0.helpers.0.devtmpfs_automount = true
          config.0.helpers.0.distro = true
          config.0.helpers.0.modules_dep = true
          config.0.helpers.0.network = true
          config.0.helpers.0.updatedb_disabled = true
          config.0.kernel = linode/grub2
          config.0.label = My Debian 9 Disk Profile
          config.0.memory_limit = 0
          config.0.root_device = /dev/root
          config.0.run_level = default
          config.0.virt_mode = paravirt
          disk.# = 2
          disk.0.authorized_keys.# = 0
          disk.0.filesystem = ext4
          disk.0.id = 24170011
          disk.0.image =
          disk.0.label = Debian 9 Disk
          disk.0.read_only = false
          disk.0.root_pass =
          disk.0.size = 50688
          disk.0.stackscript_data.% = 0
          disk.0.stackscript_id = 0
          disk.1.authorized_keys.# = 0
          disk.1.filesystem = swap
          disk.1.id = 24170012
          disk.1.image =
          disk.1.label = 512 MB Swap Image
          disk.1.read_only = false
          disk.1.root_pass =
          disk.1.size = 512
          disk.1.stackscript_data.% = 0
          disk.1.stackscript_id = 0
          group = Terraform
          ip_address = 192.0.2.2
          ipv4.# = 1
          ipv4.1835604989 = 192.0.2.2
          ipv6 = 2600:3c03::f03c:91ff:fef6:3ebe/64
          label = terraform-import
          private_ip = false
          region = us-east
          specs.# = 1
          specs.0.disk = 51200
          specs.0.memory = 2048
          specs.0.transfer = 2000
          specs.0.vcpus = 1
          status = running
          swap_size = 512
          type = g6-standard-1
          watchdog_enabled = true
        
        

        You will use this information in the next section.

        Note

        There is a current bug in the Linode Terraform provider that causes the Linode’s root_device configuration to display an import value of /dev/root, instead of /dev/sda. This is visible in the example output above: config.0.root_device = /dev/root. However, the correct disk, /dev/sda, is in fact targeted. For this reason, when running the terraform plan or the terraform apply commands, the output will display config.0.root_device: "/dev/root" => "/dev/sda".

        You can follow the corresponding GitHub issue for more details.

      Fill In Your Linode’s Configuration Data

      As mentioned in the Terraform’s Import Command section, you must manually create your resource configurations when importing existing infrastructure.

      1. Fill in the configuration values for the linode_instance resource block. In the example below, the necessary values were collected from the output of the terraform show command applied in Step 2 of the Import Your Linode to Terraform section. The file’s comments indicate the corresponding keys used to determine the values for the linode_instance configuration block.

        linode_instance_import.tf
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        
        provider "linode" {
            token = "a12b3c4e..."
        }
        
        resource "linode_instance" "example_label" {
            label = "terraform-import" #label
            region = "us-east"         #region
            type = "g6-standard-1"     #type
            config {
                label = "My Debian 9 Disk Profile"     #config.0.label
                kernel = "linode/grub2"                #config.0.kernel
                root_device = "/dev/sda"               #config.0.root_device
                devices {
                    sda = {
                        disk_label = "Debian 9 Disk"    #config.0.devices.0.sda.0.disk_label
                    }
                    sdb = {
                        disk_label = "512 MB Swap Image" #config.0.devices.0.sdb.0.disk_label
                    }
                }
            }
            disk {
                label = "Debian 9 Disk"      #disk.0.label
                size = "50688"               #disk.0.size
            }
            disk {
                label = "512 MB Swap Image"  #disk.1.label
                size = "512"                 #disk.1.size
            }
        }
            

        Note

        If your Linode uses more than two disks (for instance, if you have attached a Block Storage Volume), you will need to add those disks to your Linode resource configuration block. In order to add a disk, you must add the disk to the devices stanza and create an additional disk stanza.

        Note

        If you have more than one configuration profile, you must choose which profile to boot from with the boot_config_label argument. For example:

        resource "linode_instance" "example_label" {
            boot_config_label = "My Debian 9 Disk Profile"
        ...
        
      2. To check for errors in your configuration, run the plan command:

        terraform plan
        

        terraform plan shows you the changes that would take place if you were to apply the configurations with a terraform apply. Running terraform plan is a good way to determine if the configuration you provided is exact enough for Terraform to take over the management of your Linode.

        Note

        Running terraform plan will display any changes that will be applied to your existing infrastructure based on your configuration file(s). However, you will not be notified about the addition and removal of disks with terraform plan. For this reason, it is vital that the values you include in your linode_instance resource configuration block match the values generated from running the terraform show command.

      3. Once you have verified the configurations you provided in the linode_instance resource block, you are ready to begin managing your Linode instance with Terraform. Any changes or updates can be made by updating your linode_instance_import.tf file, then verifying the changes with the terrform plan command, and then finally applying the changes with the terraform apply command.

        For more available configuration options, visit the Linode Instance Terraform documentation.

      Import a Domain to Terraform

      Retrieve Your Domain’s ID

      1. Using the Linode CLI, retrieve a list of all your domains to find the ID of the domain you would like to manage under Terraform:

        linode-cli domains list --json --pretty
        

        You should see output like the following:

          
        [
          {
            "domain": "import-example.com",
            "id": 1157521,
            "soa_email": "webmaster@import-example.com",
            "status": "active",
            "type": "master"
          }
        ]
        
        

        Find the domain you would like to import and copy down the ID. You will need this ID to import your domain to Terraform.

      Create an Empty Resource Configuration

      1. Ensure you are in your Terraform project directory. Create a Terraform configuration file to manage the domain you will import in the next section. Your file can be named anything you like, but must end in .tf. Add a Linode provider block with your API access token and an empty linode_domain resource configuration block to the file:

        domain_import.tf
        1
        2
        3
        4
        5
        
        provider "linode" {
            token = "Your API Token"
        }
        
        resource "linode_domain" "example_label" {}

      Import Your Domain to Terraform

      1. Run the import command, supplying the linode_domain resource’s label, and the domain ID that was retrieved in the Retrieve Your Domain’s ID section:

        terraform import linode_domain.example_label domainID
        

        You should see output similar to the following:

          
        linode_domain.example_label: Importing from ID "1157521"...
        linode_domain.example_label: Import complete!
          Imported linode_domain (ID: 1157521)
        linode_domain.example_label: Refreshing state... (ID: 1157521)
        
        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.
        
        

        This command will create a terraform.tfstate file with information about your domain. You will use this information to fill out your resource configuration.

      2. To view the information created by terraform import, run the show command. This command will display a list of key-value pairs representing information about the imported domain:

        terraform show
        

        You should see output like the following:

          
        linode_domain.example_label:
          id = 1157521
          description =
          domain = import-example.com
          expire_sec = 0
          group =
          master_ips.# = 0
          refresh_sec = 0
          retry_sec = 0
          soa_email = webmaster@import-example.com
          status = active
          ttl_sec = 0
          type = master
        
        

      Fill In Your Domain’s Configuration Data

      As mentioned in the Terraform’s Import Command section, you must manually create your resource configurations when importing existing infrastructure.

      1. Fill in the configuration values for the linode_domain resource block. The necessary values for the example resource configuration file were collected from the output of the terraform show command applied in Step 2 of the Import Your Domain to Terraform section.

        linode_domain_example.tf
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        
        provider "linode" {
            token = "1a2b3c..."
        }
        
        resource "linode_domain" "example_label" {
            domain = "import-example.com"
            soa_email = "webmaster@import-example.com"
            type = "master"
        }
            

        Note

        If your Domain type is slave then you’ll need to include a master_ips argument with values set to the IP addresses that represent the Master DNS for your domain.

      2. Check for errors in your configuration by running the plan command:

        terraform plan
        

        terraform plan shows you the changes that would take place if you were to apply the configurations with the terraform apply command. Running terraform plan should result in Terraform displaying that no changes are to be made.

      3. Once you have verified the configurations you provided in the linode_domain block, you are ready to begin managing your domain with Terraform. Any changes or updates can be made by updating your linode_domain_example.tf file, then verifying the changes with the terrform plan command, and then finally applying the changes with the terraform apply command.

        For more available configuration options, visit the Linode Domain Terraform documentation.

      Import a Block Storage Volume to Terraform

      Retrieve Your Block Storage Volume’s ID

      1. Using the Linode CLI, retrieve a list of all your volumes to find the ID of the Block Storage Volume you would like to manage under Terraform:

        linode-cli volumes list --json --pretty
        

        You should see output similar to the following:

          
        [
          {
            "id": 17045,
            "label": "import-example",
            "linode_id": 11426126,
            "region": "us-east",
            "size": 20,
            "status": "active"
          }
        ]
        
        

        Find the Block Storage Volume you would like to import and copy down the ID. You will use this ID to import your volume to Terraform.

      Create an Empty Resource Configuration

      1. Ensure you are in your Terraform project directory. Create a Terraform configuration file to manage the Block Storage Volume you will import in the next section. Your file can be named anything you like, but must end in .tf. Add a Linode provider block with your API access token and an empty linode_volume resource configuration block to the file:

        linode_volume_example.tf
        1
        2
        3
        4
        5
        
        provider "linode" {
            token = "Your API Token"
        }
        
        resource "linode_volume" "example_label" {}

      Import Your Volume to Terraform

      1. Run the import command, supplying the linode_volume resource’s label, and the volume ID that was retrieved in the Retrieve Your Block Storage Volume’s ID section:

        terraform import linode_volume.example_label volumeID
        

        You should see output similar to the following:

          
        linode_volume.example_label: Importing from ID "17045"...
        linode_volume.example_label: Import complete!
          Imported linode_volume (ID: 17045)
        linode_volume.example_label: Refreshing state... (ID: 17045)
        
        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.
        
        

        This command will create a terraform.tfstate file with information about your Volume. You will use this information to fill out your resource configuration.

      2. To view the information created by terraform import, run the show command. This command will display a list of key-value pairs representing information about the imported Volume:

        terraform show
        

        You should see output like the following:

          
        linode_volume.example_label:
          id = 17045
          filesystem_path = /dev/disk/by-id/scsi-0Linode_Volume_import-example
          label = import-example
          linode_id = 11426126
          region = us-east
          size = "20"
          status = active
        
        

      Fill In Your Volume’s Configuration Data

      As mentioned in the Terraform’s Import Command section, you must manually create your resource configurations when importing existing infrastructure.

      1. Fill in the configuration values for the linode_volume resource block. The necessary values for the example resource configuration file were collected from the output of the terraform show command applied in Step 2 of the Import Your Volume to Terraform section:

        linode_volume_example.tf
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        
        provider "linode" {
            token = "1a2b3c..."
        }
        
        resource "linode_volume" "example_label" {
            label = "import-example"
            region = "us-east"
            size = "20"
        }
            

        Note

        Though it is not required, it’s a good idea to include a configuration for the size of the volume so that it can be managed more easily should you ever choose to expand the Volume. It is not possible to reduce the size of a volume.

      2. Check for errors in your configuration by running the plan command:

        terraform plan
        

        terraform plan shows you the changes that would take place if you were to apply the configurations with the terraform apply command. Running terraform plan should result in Terraform displaying that no changes are to be made.

      3. Once you have verified the configurations you provided in the linode_volume block, you are ready to begin managing your Block Storage Volume with Terraform. Any changes or updates can be made by updating your linode_volume_example.tf file, then verifying the changes with the terrform plan command, and then finally applying the changes with the terraform apply command.

        For more optional configuration options, visit the Linode Volume Terraform documentation.

      Import a NodeBalancer to Terraform

      Configuring Linode NodeBalancers with Terraform requires three separate resource configuration blocks: one to create the NodeBalancer, a second for the NodeBalancer Configuration, and a third for the NodeBalancer Nodes.

      Retrieve Your NodeBalancer, NodeBalancer Config, NodeBalancer Node IDs

      1. Using the Linode CLI, retrieve a list of all your NodeBalancers to find the ID of the NodeBalancer you would like to manage under Terraform:

        linode-cli nodebalancers list --json --pretty
        

        You should see output similar to the following:

          
        [
          {
            "client_conn_throttle": 0,
            "hostname": "nb-192-0-2-3.newark.nodebalancer.linode.com",
            "id": 40721,
            "ipv4": "192.0.2.3",
            "ipv6": "2600:3c03:1::68ed:945f",
            "label": "terraform-example",
            "region": "us-east"
          }
        ]
        
        

        Find the NodeBalancer you would like to import and copy down the ID. You will use this ID to import your NodeBalancer to Terraform.

      2. Retrieve your NodeBalancer configuration by supplying the ID of the NodeBalancer you retrieved in the previous step:

        linode-cli nodebalancers configs-list 40721 --json --pretty
        

        You should see output similar to the following:

          
        [
          {
            "algorithm": "roundrobin",
            "check_passive": true,
            "cipher_suite": "recommended",
            "id": 35876,
            "port": 80,
            "protocol": "http",
            "ssl_commonname": "",
            "ssl_fingerprint": "",
            "stickiness": "table"
          }
        ]
        
        

        Copy down the ID of your NodeBalancer configuration, you will use it to import your NodeBalancer configuration to Terraform.

      3. Retrieve a list of Nodes corresponding to your NodeBalancer to find the label and address of your NodeBalancer Nodes. Supply the ID of your NodeBalancer as the first argument and the ID of your NodeBalancer configuration as the second:

        linode-cli nodebalancers nodes-list 40721 35876 --json --pretty
        

        You should see output like the following:

          
        [
          {
            "address": "192.168.214.37:80",
            "id": 327539,
            "label": "terraform-import",
            "mode": "accept",
            "status": "UP",
            "weight": 100
          }
        ]
        
        

        If you are importing a NodeBalancer, chances are your output lists more than one Node. Copy down the IDs of each Node. You will use them to import your Nodes to Terraform.

      Create Empty Resource Configurations

      1. Ensure you are in your Terraform project directory. Create a Terraform configuration file to manage the NodeBalancer you will import in the next section. Your file can be named anything you like, but must end in .tf.

        Add a Linode provider block with your API access token and empty linode_nodebalancer, linode_nodebalancer_config, and linode_nodebalancer_node resource configuration blocks to the file. Be sure to give the resources appropriate labels. These labels will be used to reference the resources locally within Terraform:

        linode_nodebalancer_example.tf
        1
        2
        3
        4
        5
        6
        7
        8
        9
        
        provider "linode" {
            token = "Your API Token"
        }
        
        resource "linode_nodebalancer" "example_nodebalancer_label" {}
        
        resource "linode_nodebalancer_config" "example_nodebalancer_config_label" {}
        
        resource "linode_nodebalancer_node" "example_nodebalancer_node_label" {}

        If you have more than one NodeBalancer Configuration, you will need to supply multiple linode_nodebalancer_config resource blocks with different labels. The same is true for each NodeBalancer Node requiring an additional linode_nodebalancer_node block.

      Import Your NodeBalancer, NodeBalancer Configuration, and NodeBalancer Nodes to Terraform

      1. Run the import command for your NodeBalancer, supplying your local label and the ID of your NodeBalancer as the last parameter.

        terraform import linode_nodebalancer.example_nodebalancer_label nodebalancerID
        

        You should see output similar to the following:

          
        linode_nodebalancer.example_nodebalancer_label: Importing from ID "40721"...
        linode_nodebalancer.example_nodebalancer_label: Import complete!
          Imported linode_nodebalancer (ID: 40721)
        linode_nodebalancer.example_nodebalancer_label: Refreshing state... (ID: 40721)
        
        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.
        
        
      2. Run the import command for your NodeBalancer configuration, supplying your local label, and the ID of your NodeBalancer and the ID of your NodeBalancer configuration separated by commas as the last argument.

        terraform import linode_nodebalancer_config.example_nodebalancer_config_label nodebalancerID,nodebalancerconfigID
        

        You should see output similar to the following:

          
        linode_nodebalancer_config.example_nodebalancer_config_label: Importing from ID "40721,35876"...
        linode_nodebalancer_config.example_nodebalancer_config_label: Import complete!
          Imported linode_nodebalancer_config (ID: 35876)
        linode_nodebalancer_config.example_nodebalancer_config_label: Refreshing state... (ID: 35876)
        
        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.
        
        
      3. Run the import command for you NodeBalancer Nodes, supplying your local label, and the ID of your NodeBalancer, the ID of your NodeBalancer Configuration, and your NodeBalancer Node, separated by commas, as the last argument.

        terraform import linode_nodebalancer_node.example_nodebalancer_node_label nodebalancerID,nodebalancerconfigID,nodebalancernodeID
        

        You should see output like the following:

          
        linode_nodebalancer_node.example_nodebalancer_node_label: Importing from ID "40721,35876,327539"...
        linode_nodebalancer_node.example_nodebalancer_node_label: Import complete!
          Imported linode_nodebalancer_node (ID: 327539)
        linode_nodebalancer_node.example_nodebalancer_node_label: Refreshing state... (ID: 327539)
        
        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.
        
        
      4. Running terraform import creates a terraform.tfstate file with information about your NodeBalancer. You will use this information to fill out your resource configuration. To view the information created by terraform import, run the show command:

        terraform show
        

        You should see output like the following:

          
        linode_nodebalancer.example_nodebalancer_label:
          id = 40721
          client_conn_throttle = 0
          created = 2018-11-16T20:21:03Z
          hostname = nb-192-0-2-3.newark.nodebalancer.linode.com
          ipv4 = 192.0.2.3
          ipv6 = 2600:3c03:1::68ed:945f
          label = terraform-example
          region = us-east
          transfer.% = 3
          transfer.in = 0.013627052307128906
          transfer.out = 0.0015048980712890625
          transfer.total = 0.015131950378417969
          updated = 2018-11-16T20:21:03Z
        
        linode_nodebalancer_config.example_nodebalancer_config_label:
          id = 35876
          algorithm = roundrobin
          check = none
          check_attempts = 2
          check_body =
          check_interval = 5
          check_passive = true
          check_path =
          check_timeout = 3
          cipher_suite = recommended
          node_status.% = 2
          node_status.down = 0
          node_status.up = 1
          nodebalancer_id = 40721
          port = 80
          protocol = http
          ssl_commonname =
          ssl_fingerprint =
          ssl_key =
          stickiness = table
        
        linode_nodebalancer_node.example_nodebalancer_node_label:
          id = 327539
          address = 192.168.214.37:80
          config_id = 35876
          label = terraform-import
          mode = accept
          nodebalancer_id = 40721
          status = UP
          weight = 100
        
        

      Fill In Your NodeBalancer’s Configuration Data

      As mentioned in the Terraform’s Import Command section, you must manually create your resource configurations when importing existing infrastructure.

      1. Fill in the configuration values for all three NodeBalancer resource configuration blocks. The necessary values for the example resource configuration file were collected from the output of the terraform show command applied in Step 4 of the Import Your NodeBalancer, NodeBalancer Configuration, and NodeBalancer Nodes to Terraform section:
      linode_nodebalancer_example.tf
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      
      provider "linode" {
          token = "1a2b3c..."
      }
      
      resource "linode_nodebalancer" "nodebalancer_import" {
          label = "terraform-example"
          region = "us-east"
      }
      
      resource "linode_nodebalancer_config" "nodebalancer_config_import" {
          nodebalancer_id = "40721"
      }
      
      resource "linode_nodebalancer_node" "nodebalancer_node_import" {
          label = "terraform-import"
          address = "192.168.214.37:80"
          nodebalancer_id = "40721"
          config_id = "35876"
      }
      1. Check for errors in your configuration by running the plan command:

        terraform plan
        

        terraform plan shows you the changes that would take place if you were to apply the configurations with the terraform apply command. Running terraform plan should result in Terraform displaying that no changes are to be made.

      2. Once you have verified the configurations you provided in all three NodeBalancer configuration blocks, you are ready to begin managing your NodeBalancers with Terraform. Any changes or updates can be made by updating your linode_nodebalancer_example.tf file, then verifying the changes with the terrform plan command, and finally, applying the changes with the terraform apply command.

        For more available configuration options, visit the Linode NodeBalancer, Linode NodeBalancer Config, and Linode NodeBalancer Node Terraform documentation.

      Next Steps

      You can follow a process similar to what has been outlined in this guide to begin importing other pieces of your Linode infrastructure such as images, SSH keys, access tokens, and StackScripts. Check out the links in the More Information section below for helpful information.

      More Information

      You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.



      Source link