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:
-
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" }
-
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" } }
-
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:
-
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
-
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:
-
Install Go on your machine. You can setup GOPATH by adding
$GOPATH/bin
to your$PATH
. -
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 ...
-
Run
make
test to test the provider as follows:$ make test
-
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.