Integrating Terraform with Avi Vantage

Overview

This guide explains the details of integrating Terraform with Avi Vantage.

Terraform is an open-source infrastructure that allows you to define and provision a datacenter infrastructure. You can do this using a high-level configuration language designed to allow concise description of the infrastructure.

The Terraform language helps you in describing an intended goal rather than the steps to reach that goal.

Each Terraform module must declare which providers it requires, so that Terraform can install and use them. Provider requirements are declared in a required_providers block.

Starting with Terraform version 0.13+, Avi terraform provider has been migrated to terraform registry. In order to use it, you need to add the below block in versions.tf file.

Note: You need to create this file if it is not present in each directory that has terraform plans.


terraform {                                                                        
  required_providers {
    avi = {
      source  = "vmware/avi"
      version = "20.1.4"
    }
    required_version = ">= 0.13"
  }

where,

  • source — Source of Terraform provider. Terraform will pull the released Avi Terraform provider from Terraform registry from this namespace.

  • version — Avi Terraform provider release version in Terraform registry. If this field is skipped then Terraform will pull the latest release of Avi Terraform provider from Terraform registry.

  • required_version — Protects the Terraform plans from running on non-supported versions of Terraform.

Integrating Avi Terraform

Avi Terraform provider is a native integration into the Terraform to setup all Avi configuration that is part of Avi REST API. With the Avi Terraform provider, a Terraform plan written in HCL syntax can specify any Avi configuration and it will be reflected on the Avi Controller. For instance, you can use a Terraform plan with the following code to setup a pool in Avi Vantage.


"resource "avi_pool" "testpool" {
 name= "pool-42",
 health_monitor_refs= ["${avi_healthmonitor.test_hm_1.id}"]
 tenant_ref= "${data.avi_tenant.default_tenant.id}"
 cloud_ref= "${data.avi_cloud.default_cloud.id}"
 application_persistence_profile_ref= "${avi_applicationpersistenceprofile.test_applicationpersistenceprofile.id}"
 servers {
  ip= {
    type= "V4",
    addr= "10.90.64.66",
  }
  port= 8080
  }
  fail_action= {
  type= "FAIL_ACTION_CLOSE_CONN"
  }
}

You can break the above code as follows:

  • The following is the CLI to setup a resource of avi pool type with testpool name:

    
      resource "avi_pool" "testpool" {
      
  • The following is the CLI to reference another resource that was specified in the Terraform plan:

    
      health_monitor_refs= ["${avi_healthmonitor.test_hm_1.id}"]
  • The following is the CLI to reference a read only resource that is not being created and managed via this plan.

    
      tenant_ref= "${data.avi_tenant.default_tenant.id}"
      

Configuring Avi Terraform

Each Avi Vantage REST resource is exposed as a resource in Terraform. For instance, you can setup a pool by using avi_pool as the resource type in Terraform. There are more than 50 different REST resource supported.

The definition of every resource or resource schema is built using Avi Vantage API spec represented as swagger specs or in Avi API guide. There is 1:1 mapping between the fields in Terraform schema to Avi Vantage object/resource definition. For instance, the definition of Avi Pool in Terraform is coded as Terraform Avi Pool Resource schema.

In addition to the Terraform resource you can check for the existing objects in Avi Controller using data sources. For instance, you can load System HTTP Application profile in a Terraform plan as follows:


data "avi_applicationprofile" "system_http_profile" {
  name= "System-HTTP"
}

// can be referenced as "${data.avi_applicationprofile.system_http_profile.id}"

You can also use existing UUID of the object to lookup from the Avi Controller as follows:


data "avi_applicationprofile" "system_http_profile" {
uuid= "applicationprofile-xxxxxxx"
}

Installing Avi Terraform

The following is the process to install Avi Terraform:

Usage

The following are the steps to use the provider:

  1. Create Avi provider in Terraform plan. For instance, to restrict template version in 0.1.x, you can use the following CLI:

    
     provider "avi" {
       avi_username = "admin"
       avi_tenant = "admin"
       avi_password = "something"
       avi_controller= "42.42.42.42"
     }    
  2. Create Avi pool example. Here the pool depends on read only tenant data source and another health monitor defined as a resource in the Terraform plan.

    
     resource "avi_pool" "testpool" {
       name= "pool-42",
       health_monitor_refs= ["${avi_healthmonitor.test_hm_1.id}"]
       tenant_ref= "${data.avi_tenant.default_tenant.id}"
       cloud_ref= "${data.avi_cloud.default_cloud.id}"
       application_persistence_profile_ref= "${avi_applicationpersistenceprofile.test_applicationpersistenceprofile.id}"
       servers {
         ip= {
           type= "V4",
           addr= "10.90.64.66",
         }
         port= 8080
       }
       fail_action= {
         type= "FAIL_ACTION_CLOSE_CONN"
       }
     }
     
  3. Reference existing resources as readonly or data sources.

    
     data "avi_applicationprofile" "system_http_profile" {
       name= "System-HTTP"
     }
        
     application_profile_ref= "${data.avi_applicationprofile.system_https_profile.id}"
     

Building The Provider

The following is the process to build the provider:

  1. You can clone repository to the following path:

    
     $GOPATH/src/github.com/terraform-providers/terraform-provider-avi  
    
     $ mkdir -p $GOPATH/src/github.com/terraform-providers; cd $GOPATH/src/github.com/terraform-providers
     $ git clone https://github.com/terraform-providers/terraform-provider-avi.git 
  2. Specify the provider directory and build the provider as follows:

    
     $ cd $GOPATH/src/github.com/terraform-providers/terraform-provider-
        
        
     $ make     

Developing the Provider

The following are the steps to develop the provider:

  1. Install Go on your machine. You can setup GOPATH by adding $GOPATH/bin to your $PATH.

  2. To compile the provider, run make build. This will build the provider and put the provider binary in the $GOPATH/bin directory.

    
     $ make bin
     ...
     $ $GOPATH/bin/terraform-provider-avi
     ...
     
  3. Run make test to test the provider as follows:

    $ make test
  4. Run make testacc test to run the full suite of acceptance tests as follows:

    $ make testacc

Note: You need to export AVI_SUPPRESS_SENSITIVE_FIELDS_DIFF environment variable as AVI_SUPPRESS_SENSITIVE_FIELDS_DIFF=true if you want terraform to suppress the difference for sensitive fields during the plan update. However, if you want to intentionally update the sensitive fields in the plan update then you need to un-export the environment variable or set it to false, i.e. export AVI_SUPPRESS_SENSITIVE_FIELDS_DIFF=false or unset AVI_SUPPRESS_SENSITIVE_FIELDS_DIFF.

Example

The following is an example of virtual service using Terraform:


provider "avi" {
  avi_username = "admin"
  avi_tenant = "admin"
  avi_password = "something"
  avi_controller= "10.10.25.42"
}

data "avi_applicationprofile" "system_http_profile" {
  name= "System-HTTP"
}

data "avi_applicationprofile" "system_https_profile" {
  name= "System-Secure-HTTP"
}

data "avi_tenant" "default_tenant" {
  name= "admin"
}

data "avi_cloud" "default_cloud" {
  name= "Default-Cloud"
}

data "avi_serviceenginegroup" "se_group" {
  name = "Default-Group"
}

data "avi_networkprofile" "system_tcp_profile" {
  name= "System-TCP-Proxy"
}

data "avi_analyticsprofile" "system_analytics_profile" {
  name= "System-Analytics-Profile"
}

data "avi_sslkeyandcertificate" "system_default_cert" {
  name= "System-Default-Cert"
}

data "avi_sslprofile" "system_standard_sslprofile" {
  name= "System-Standard"
}

data "avi_vrfcontext" "global_vrf" {
  name= "global"
}

resource "avi_networkprofile" "test_networkprofile" {
  name= "networkprofile-42"
  tenant_ref= "${data.avi_tenant.default_tenant.id}"
  profile{
    type= "PROTOCOL_TYPE_TCP_PROXY"
  }
}

resource "avi_applicationpersistenceprofile" "test_applicationpersistenceprofile" {
  name = "applicationpersistence-42"
  tenant_ref= "${data.avi_tenant.default_tenant.id}"
  persistence_type = "PERSISTENCE_TYPE_CLIENT_IP_ADDRESS"
}

resource "avi_vsvip" "test_vsvip" {
  name= "vip-42"
  vip {
    vip_id= "0"
    ip_address {
      type= "V4",
      addr= "10.90.64.88",
    }
  }
}

resource "avi_virtualservice" "test_vs" {
  name= "vs-42"
  pool_ref= "${avi_pool.testpool.id}"
  tenant_ref= "${data.avi_tenant.default_tenant.id}"
  cloud_ref= "${data.avi_cloud.default_cloud.id}"
  application_profile_ref= "${data.avi_applicationprofile.system_https_profile.id}"
  network_profile_ref = "${data.avi_networkprofile.system_tcp_profile.id}"
  vsvip_ref = "${avi_vsvip.test_vsvip.id}"
  vip {
    vip_id= "0"
    ip_address {
      type= "V4",
      addr= "10.90.64.88",
    }
  }
  services {
    port= 80
    enable_ssl= true
    port_range_end= 80
  }
  cloud_type = "CLOUD_VCENTER"
  se_group_ref= "${data.avi_serviceenginegroup.se_group.id}"
  analytics_profile_ref= "${data.avi_analyticsprofile.system_analytics_profile.id}"
  ssl_key_and_certificate_refs= ["${data.avi_sslkeyandcertificate.system_default_cert.id}"]
  ssl_profile_ref= "${data.avi_sslprofile.system_standard_sslprofile.id}"
  vrf_context_ref= "${data.avi_vrfcontext.global_vrf.id}"
}

resource "avi_healthmonitor" "test_hm_1" {
  name = "healthmonitor-42"
  type = "HEALTH_MONITOR_HTTP"
}

resource "avi_pool" "testpool" {
  name= "pool-42",
  health_monitor_refs= ["${avi_healthmonitor.test_hm_1.id}"]
  tenant_ref= "${data.avi_tenant.default_tenant.id}"
  cloud_ref= "${data.avi_cloud.default_cloud.id}"
  application_persistence_profile_ref= "${avi_applicationpersistenceprofile.test_applicationpersistenceprofile.id}"
  servers {
    ip= {
      type= "V4",
      addr= "10.90.64.66",
    }
    port= 8080
  }
  fail_action= {
    type= "FAIL_ACTION_CLOSE_CONN"
  }
}

Note: For more details on the models, refer to OpenAPI (Swagger 2.0) Specification Integration guide.