Manage Resources Using Terraform

Terraform is a third-party tool that you can use to create and manage your IaaS and PaaS resources on Oracle Cloud at Customer. This guide shows you how to install and configure Terraform, and then use it to deploy a sample set of Compute Classic resources.

Scenario Overview

In this example, you create the following Compute Classic resources:

  • A persistent boot disk

  • An IP network

  • A vNICset

  • A VM based on the image in the boot disk and attached to the IP network

  • An SSH public key associated with the VM

  • A data volume attached to the VM

  • A public IP reservation for the VM

  • A security protocol for SSH traffic to the VM

  • A security rule to permit SSH access to the VM, and an ACL for the security rule

Prerequisites

  1. If you are new to Terraform, learn the basics.
    At a minimum, read the brief introduction here: https://www.terraform.io/intro/index.html.
  2. Download and install Terraform on your local computer.
    Binary packages are available for several operating systems and processor architectures. For the instructions to download and install Terraform, go to https://www.terraform.io/intro/getting-started/install.html.
  3. Generate an SSH key pair. See Generate an SSH Key Pair.
  4. Gather the required Oracle Cloud account information:
    • Your Oracle Cloud user name and password.
    • The service instance ID.
      1. Sign in to Oracle Cloud My Services.
      2. Locate the Compute Classic tile and click Compute Classic.
      3. Locate the Service Instance ID field, and the note its value (example: 500099999).
    • The REST endpoint URL for Compute Classic.
      1. Sign in to Oracle Cloud My Services, using the My Services URL from the welcome email.
      2. Click Menu icon near the upper left corner of the page.
      3. In the menu that appears, expand Services, and click Compute Classic. The Instances page of the Compute Classic web console is displayed.
      4. Click Site near the top of the page, and select the site for which you want to find out the REST endpoint URL.
      5. In the Site Selector dialog box, note the URL in the REST Endpoint field.

Create the Required Resources Using Terraform

Define the resources you need in a Terraform configuration and then apply the configuration.

  1. On the computer where you installed Terraform, create a new directory.
  2. In the new directory, create an empty text file, name-of-your-choice.tf.

    This is a Terraform configuration. In this file, you define the following:

    • The parameters that Terraform must use to connect to your Oracle Cloud at Customer machine

    • The resources to be provisioned

    Important:

    The .tf extension is mandatory. When Terraform performs any operation, it looks for a file with the .tf extension in the current directory.
  3. Open the text file in an editor of your choice.
  4. Add the following code to define the parameters that Terraform needs to connect to your account:
    provider "opc" {
      user            = "jack.smith@example.com"
      password        = "mypassword"
      identity_domain = "500099999"
      endpoint        = "https://compute.site99.ocm.rack100.example.com"
    }

    In this code:

    • Don’t change the provider line.

    • user and password: Replace with your Oracle Cloud credentials.

    • identity_domain: Replace with the service instance ID that you identified earlier.

    • endpoint: Replace with the REST endpoint URL of Compute Classic.

  5. Add code for each resource that you want to create using Terraform.

    Note:

    When copying and editing the code, follow the instructions carefully.
    1. Create an ACL by appending the following code.
      # Create an ACL
      resource "opc_compute_acl" "default" {
        name = "occACL"
      }
      In this code:
      • Don’t change the resource line.

      • name: Replace with a name of your choice, or leave the example as is.

    2. Create an IP network by appending the following code:
      # Create an IP network
      resource "opc_compute_ip_network" "default" {
        name              = "occIPnetwork"
        ip_address_prefix = "192.168.100.0/24"
      }
      In this code:
      • Don't change the resource line.

      • name: Replace with a name of your choice, or leave the example as is.

      • ip_address_prefix: Replace with an address range of your choice in CIDR format, or leave the value in the example as is.

    3. Reserve a public IP address for the VM by appending the following code:
      # Reserve a public IP address
      resource "opc_compute_ip_address_reservation" "default" {
        name            = "occIPreservation"
        ip_address_pool = "public-ippool"
        lifecycle {
          prevent_destroy = true
        }
      }
      In this code:
      • Don't change the resource line.

      • name: Replace with a name of your choice, or leave the example as is.

      • ip_address_pool: You need a publicly routable IP address. So don't change this line.

      • lifecycle.prevent_destroy=true reduces the chance of accidentally deleting the resource. This setting is useful for resources that you want to retain for future use even after you delete the VM.

    4. Define a security protocol for SSH by appending the following code:
      # Create a security protocol for SSH
      resource "opc_compute_security_protocol" "default" {
        name        = "occSSHprotocol"
        dst_ports   = ["22"]
        ip_protocol = "tcp"
      }
      In this code:
      • Don't change the resource line.

      • name: Replace with a name of your choice, or leave the example as is.

      • dst_ports: 22 is the port for the SSH protocol. So don't change this line.

      • ip_protocol: SSH is a TCP protocol. So don't change this line.

    5. Upload an SSH public key by appending the following code:
      # Specify an SSH public key
      resource "opc_compute_ssh_key" "default" {
        name = "occKey"
        key  = "ssh-rsa AAAAB3NzaC1yc2E..."
        lifecycle {
          prevent_destroy = true
        }
      }
      In this code:
      • Don't change the resource line.

      • name: Replace with a name of your choice, or leave the example as is.

      • key: Replace with the value of your SSH public key. Copy and paste the value exactly as in the public key file. Don't introduce any extra characters or lines.

      • lifecycle.prevent_destroy=true ensures that the resource is retained even when you delete the VM.

    6. Create a virtual NIC set by appending the following code:
      # Create a virtual NIC set
      resource "opc_compute_vnic_set" "default" {
        name         = "occVNICset"
        applied_acls = ["${opc_compute_acl.default.name}"]
      }
      In this code:
      • Don't change the resource line.

      • name: Replace with a name of your choice, or leave the example as is.

      • applied_acls contains a reference to the ACL that you defined earlier.

    7. Define a security rule to permit SSH access to the VM by appending the following code:
      resource "opc_compute_security_rule" "default" {
        name               = "occSecurityRule"
        flow_direction     = "ingress"
        acl                = "${opc_compute_acl.default.name}"
        security_protocols = ["${opc_compute_security_protocol.default.name}"]
        dst_vnic_set       = "${opc_compute_vnic_set.default.name}"
      }
      In this code:
      • Don't change the resource line.

      • name: Replace with a name of your choice, or leave the example as is.

      • flow_direction=ingress means that this rule permits inbound traffic to the VM. Don't change this line.

      • acl contains a reference to the ACL that you defined earlier. Don't change this line.

      • security_protocols contains a reference to the SSH protocol that you defined earlier. Don't change this line.

      • dst_vnic_set contains a reference to the vNICset that you defined earlier. Don't change this line.

    8. Create a persistent boot volume using the Oracle Linux 7.2 image, by appending the following code:
      # Create a persistent boot volume
      resource "opc_compute_storage_volume" "boot" {
        size = "20"
        name = "occBootVolume"
        bootable = true
        image_list = "/oracle/public/OL_7.2_UEKR4_x86_64"
        image_list_entry = 1
        lifecycle {
          prevent_destroy = true
        }
      }
      In this code:
      • Don't change the resource line.

      • size: Leave it at 20 GB or enter a larger size.

      • name: Replace with a name of your choice, or leave the example as is.

      • bootable=true means that this a bootable volume. Don't change this line.

      • image_list: Replace with the full name of the image that you want to use, or leave the example as is.

      • image_list_entry=1 means that the first image in the image list must be used. Don't change this line.

      • lifecycle.prevent_destroy=true ensures that the resource is retained even when you delete the VM.

    9. Create a volume for data and applications that you may want to store, by appending the following code:
      # Create a data volume
      resource "opc_compute_storage_volume" "data" {
        name = "occDataVolume"
        size = 10
        lifecycle {
          prevent_destroy = true
        }
      }
      In this code:
      • Don't change the resource line.

      • name: Replace with a name of your choice, or leave the example as is.

      • size: Replace with a size of your choice, in GB.

      • lifecycle.prevent_destroy=true ensures that the resource is retained even when you delete the VM.

    10. Create a VM by appending the following code:
      # Create a VM
      resource "opc_compute_instance" "default" {
        name       = "occVM"
        shape      = "oc3"
        ssh_keys   = ["${opc_compute_ssh_key.default.name}"]
        hostname   = "occvm"
      
        storage {
          volume = "${opc_compute_storage_volume.boot.name}"
          index  = 1
        }
       
        boot_order = [1]
       
        storage {
          volume = "${opc_compute_storage_volume.data.name}"
          index = 2
        }
       
        networking_info {
          index      = 0
          ip_network = "${opc_compute_ip_network.default.name}"
          nat        = ["${opc_compute_ip_address_reservation.default.name}"]
          vnic_sets  = ["${opc_compute_vnic_set.default.name}"]
        }
      }
      In this code:
      • Don't change the resource line.

      • name: Replace with a name of your choice, or leave the example as is.

      • shape: Replace with a shape of your choice, or leave the example as is.

      • ssh_keys contains a reference to the SSH public key that you specified earlier. Don't change this line.

      • storage.volume: There are two of these fields referring to the boot and data volumes that you defined earlier. Don't change these lines.

      • storage.index indicates the disk number at which volume must be attached to the VM. Don't change these lines.

      • boot_order=1 means that the volume attached at index #1 must be used to boot the VM. Don't change this line.

      • networking_info.index=0 means that this network definition is for eth0. Don't change this line.

      • networking_info.ip_network contains a reference to the IP network that you defined earlier. Don't change this line.

      • networking_info.nat contains a reference to the IP reservation that you defined earlier. Don't change this line.

      • networking_info.vnic_sets contains a reference to the vNICset that you defined earlier. Don't change this line.

  6. After adding all the required code, save the file.
  7. Initialize the directory containing the configuration.
    terraform init

    This command downloads the opc provider and sets up the current directory for use by Terraform.

  8. Verify that the syntax of the configuration has no errors.
    terraform validate

    If any syntactical errors exist, the output lists the errors.

  9. If errors exist, then reopen the configuration, fix the errors, save the file, and run terraform validate again.

    When no error exists, the command doesn't display any output.

    Tip:

    To debug problems from this point onward, you can enable logging.
    1. Configure the log level by setting the TF_LOG environment variable to TRACE, DEBUG, INFO, WARN or ERROR. The TRACE level is the most verbose.

    2. Set the log-file path by using the TF_LOG_PATH environment variable.

  10. Review the resources that you have defined.
    terraform plan

    Terraform displays all the actions that will be performed when you apply this configuration. It lists the resources that will be created and deleted and the attributes of each resource. Here's an example of the output of the command.

    Note:

    In this example, some parts are truncated for brevity, and only the attributes that you defined explicitly are shown. When you run terraform plan, you'll see several more attributes with the value <computed>. The values for those fields will be filled when the resources are created.
    Terraform will perform the following actions:
     
      + opc_compute_acl.default
          enabled:                                       "true"
          name:                                          "occACL"
     
      + opc_compute_instance.default
          boot_order.0:                                  "1"
          name:                                          "occVM"
          networking_info.2552438773.index:              "0"
          networking_info.2552438773.ip_network:         "occIPnetwork"
          networking_info.2552438773.nat.0:              "occIPreservation"
          networking_info.2552438773.vnic_sets.0:        "occVNICset"
          shape:                                         "oc3"
          ssh_keys.0:                                    "occKey"
          storage.1528687378.index:                      "2"
          storage.1528687378.volume:                     "occDataVolume"
          storage.3242904380.index:                      "1"
          storage.3242904380.volume:                     "occBootVolume"
     
      + opc_compute_ip_address_reservation.default
          ip_address_pool:                               "public-ippool"
          name:                                          "occIPreservation"
     
      + opc_compute_ip_network.default
          ip_address_prefix:                             "192.168.100.0/24"
          name:                                          "occIPnetwork"
     
      + opc_compute_security_protocol.default
          dst_ports.0:                                   "22"
          ip_protocol:                                   "tcp"
          name:                                          "occSSHprotocol"
     
      + opc_compute_security_rule.default
          acl:                                           "occACL"
          dst_vnic_set:                                  "occVNICset"
          flow_direction:                                "ingress"
          name:                                          "occSecurityRule"
          security_protocols.0:                          "occSSHprotocol"
     
      + opc_compute_ssh_key.default
          key:                                           "ssh-rsa AAAAB3NzaC1yc2EAAAAB..."
          name:                                          "occKey"
     
      + opc_compute_storage_volume.boot
          bootable:                                      "true"
          image_list:                                    "/oracle/public/OL_7.2_UEKR4_x86_64"
          image_list_entry:                              "1"
          name:                                          "occBootVolume"
          size:                                          "20"
     
      + opc_compute_storage_volume.data
          name:                                          "occDataVolume"
          size:                                          "10"
     
      + opc_compute_vnic_set.default
          applied_acls.0:                                "occACL"
          name:                                          "occVNICset"

    At the end, Terraform summarizes the number of resources that will be added, destroyed, and changed when you apply the configuration.

    Plan: 10 to add, 0 to change, 0 to destroy.
  11. If you want to change anything, edit the configuration, validate it, and review the revised plan.
  12. After finalizing the configuration, create the resources defined in it.
    terraform apply
  13. At the "Do you want to perform these actions" prompt, enter yes.

    Terraform displays the status of the operation, as shown in the following example. For each resource, Terraform shows the status and the time taken for the operation.

    Note:

    In this example, some parts are truncated for brevity.
    opc_compute_security_protocol.default: Creating...
    opc_compute_ssh_key.default: Creating...
    opc_compute_storage_volume.data: Creating...
    opc_compute_storage_volume.boot: Creating...
    opc_compute_ip_network.default: Creating...
    opc_compute_acl.default: Creating...
    opc_compute_ip_address_reservation.default: Creating...
    opc_compute_ip_network.default: Creation complete after 1s (ID: occIPnetwork)
    opc_compute_security_protocol.default: Creation complete after 1s (ID: occSSHprotocol)
    opc_compute_ip_address_reservation.default: Creation complete after 1s (ID: occIPreservation)
    opc_compute_acl.default: Creation complete after 1s (ID: occACL)
    opc_compute_vnic_set.default: Creating...
    opc_compute_vnic_set.default: Creation complete after 0s (ID: occVNICset)
    opc_compute_security_rule.default: Creating...
    opc_compute_security_rule.default: Creation complete after 1s (ID: occSecurityRule)
    opc_compute_ssh_key.default: Creation complete after 2s (ID: occKey)
    opc_compute_storage_volume.data: Creation complete after 12s (ID: occDataVolume)
    opc_compute_storage_volume.boot: Creation complete after 12s (ID: occBootVolume)
    opc_compute_instance.default: Creating...
    opc_compute_instance.default: Creation complete after 43s (ID: 9a3fee81-b742-48f3-be2d-b83b842e3b40)
  14. Wait for the following message:
    Apply complete! Resources: 10 added, 0 changed, 0 destroyed.
  15. Find out the public IP address of the VM.
    terraform state show opc_compute_ip_address_reservation.default

    Here's an example of the output of this command:

    id              = occIPreservation
    description     =
    ip_address      = 198.51.100.1
    ip_address_pool = public-ippool
    name            = occIPreservation
    tags.#          = 0
    uri             = https://203.0.100.1/network/v1/ipreservation/Compute-500099999/jack.smith@example.com/occIPreservation

    In the output, look for the ip_address field. You can use this address to connect to the VM using ssh.

Add, Update, and Delete Resources Using Terraform

You can manage your IaaS and PaaS resources on Oracle Cloud at Customer by using the Terraform configuration that you used originally to create the resources.

Add Resources

Define the required resources in the configuration, and run terraform apply.

Update Resources

Edit the attributes of the resources in the configuration, and run terraform apply.

Delete Resources

  • To delete a specific resource, run the following command:

    terraform destroy -target=resource_type.resource_name

    For example, to delete just the VM in the configuration that you applied earlier, run this command:

    terraform destroy -target=opc_compute_instance.default

    At the "Do you really want to destroy" prompt, enter yes.

    Terraform displays the status of the operation, as shown in the following example. For each resource, Terraform shows the status and the time taken for the operation.

    Note:

    In this example, some parts are truncated for brevity.
    opc_compute_instance.default: Destroying... (ID: 9a3fee81-b742-48f3-be2d-b83b842e3b40)
    ...
    ...
    opc_compute_instance.default: Destruction complete after 41s

    Wait for the following message:

    Destroy complete! Resources: 1 destroyed
  • To delete all the resources, run terraform destroy.

  • To delete specific resources permanently, remove the resources from the configuration, and then run terraform apply.

Re-create Resources

To re-create any resources that you deleted previously but didn’t remove from the configuration, run terraform apply.

Learn More