Skip to content

About

Terraform AVI Networks provider

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

35 stars

Watchers

12 watching

Forks

Terraform Provider for Avi (NSX Advanced Load Balancer)

Terraform provider that manages NSX Advanced Load Balancer / Avi Vantage objects (pools, virtual services, health monitors, certs, GSLB, WAF, etc.) via the Avi Controller REST API. Maintained by Broadcom/VMware (vmware/terraform-provider-avi), built on top of hashicorp/terraform-plugin-sdk/v2 and vmware/alb-sdk (the Go client for the Avi Controller API).

  • Provider version tracks Avi Controller releases
  • License: Mozilla Public License 2.0 (see LICENSE).
  • Registry namespace (TF 0.13+): vmware.com/avi/avi.

Repository layout

.
├── main.go                      # plugin entrypoint: plugin.Serve(avi.Provider)
├── avi/                         # provider implementation (single Go package)
│   ├── provider.go              #   schema.Provider{}: auth schema + Resource/DataSource maps (~195/136 objects)
│   ├── utils.go                 #   generic CRUD engine (APICreate/APIRead/APIUpdate/APIDelete/...),
│   │                             #   schema<->API marshaling (SchemaToAviData/APIDataToSchema), importer
│   ├── diff_suppress_func.go    #   ValidateFunc helpers (validateInteger/Bool/Float) + sensitive-field diff suppression
│   ├── resource_avi_rest_dependants.go  # ~46k lines, AUTO-GENERATED nested/sub-object schemas (skipped by lint)
│   ├── resource_avi_<object>.go        # one file per top-level API object: schema + thin Create/Read/Update/Delete
│   ├── datasource_avi_<object>.go      # matching read-only data source per object
│   ├── resource_avi_<object>_test.go   # acceptance tests (TF_ACC=1), one set per resource
│   └── data_source_avi_<object>_test.go
├── website/docs/{r,d}/*.html.markdown  # Terraform Registry docs, one page per resource/data source
├── examples/                    # example .tf configs (aws, azure, gcp, nsxt, openstack, vmware, pool, waf_V2, ...)
├── modules/                     # reusable TF modules (services/vmware_deploy, nia/pool - Consul-Terraform-Sync)
├── scripts/                     # gofmtcheck.sh, errcheck.sh, changelog-links.sh, gogetcookie.sh
├── GNUmakefile                  # build/test/lint targets
└── .github/workflows/           # golangci-lint.yml, release.yml (goreleaser)

Architecture

  • provider.go is the single source of truth for what's registered: Schema (connection params), DataSourcesMap, ResourcesMap. Every Avi API object type has one entry in each map, wired to a resourceAvi<Object>() / dataSourceAvi<Object>() constructor.
  • Generic CRUD: individual resource_avi_*.go files mostly just define the Terraform schema (Resource<Object>Schema()) and delegate Create/Read/Update/Delete to the generic helpers in utils.go (APICreate, APIRead, APIUpdate, APIDelete), passing the API object type string and schema. This is what lets ~195 resource types share one CRUD implementation instead of each hand-rolling REST calls.
  • resource_avi_rest_dependants.go holds schemas for nested/sub-objects referenced by the top-level resources (e.g. ResourceACSubjectInfoSchema). It's large and mechanically generated — it's excluded from golangci-lint (skip-files in .golangci.yml) and should not be hand-edited piecemeal.
  • Codegen note: git history is dominated by "Updated assets for terraform" commits synced from an internal Jenkins job (no generator script lives in this repo). Assume most resource_avi_*.go / datasource_avi_*.go / website/docs/** files are regenerated from the Avi Controller's Swagger/API spec upstream — hand edits to generated sections are likely to be overwritten on the next sync. Manual, durable changes belong in utils.go, provider.go, diff_suppress_func.go, examples, or genuinely hand-maintained resource logic.
  • Auth: provider.go supports username/password, API token (avi_authtoken), and VMware Cloud CSP token (avi_csp_token / avi_csp_host) auth against the Avi Controller, using lazy authentication (session is only established when a resource actually needs it).
  • Special-cased objects: utils.go maintains a postNotAllowed list (IsPostNotAllowed) for API objects that can't be created via POST (e.g. singleton/system objects like cluster, useraccount) — Create for these effectively becomes a Read/Update against an existing object.
  • Sensitive field diffs: AVI_SUPPRESS_SENSITIVE_FIELDS_DIFF env var (diff_suppress_func.go) can suppress plan diffs on sensitive fields the API masks on read.

Requirements

  • Go 1.25.6+ (see go.mod)
  • Terraform 0.13+ (0.12 build path still exists but is legacy)
  • Network access to an Avi Controller for acceptance testing

Building the provider

Clone into your GOPATH (module-aware builds still expect this path for the historical ~/.terraform.d/plugins layout used below):

mkdir -p $GOPATH/src/github.com/vmware && cd $GOPATH/src/github.com/vmware
git clone https://github.com/vmware/terraform-provider-avi.git
cd terraform-provider-avi

Terraform 0.13+ (recommended):

make build13

Installs to ~/.terraform.d/plugins/vmware.com/avi/avi/<AVI_PROVIDER_VERSION>/$(GOOS)_$(GOARCH)/ (version pinned by AVI_PROVIDER_VERSION in GNUmakefile). Reference it in a plan:

terraform {
  required_providers {
    avi = {
      source  = "vmware.com/avi/avi"
      version = "<provider_version>"
    }
  }
}

Terraform 0.12.x (legacy):

make build   # go install; then wire up ~/.terraformrc `providers {}` block or
             # copy the binary into ~/.terraform/plugins/linux_amd64/

Faster local iteration without bumping the pinned version each time — use a dev override in ~/.terraformrc:

provider_installation {
  dev_overrides {
    "vmware.com/avi/avi" = "/path/to/GOPATH/bin"
  }
  direct {}
}

Usage

provider "avi" {
  avi_username   = "admin"
  avi_tenant     = "admin"
  avi_password   = "password"
  avi_controller = "x.x.x.x"
  avi_version    = "21.1.1"
}

Example: a pool depending on data sources and other resources in the same plan.

data "avi_tenant" "default_tenant" {
  name = "admin"
}
data "avi_cloud" "default_cloud" {
  name = "Default-Cloud"
}

resource "avi_applicationpersistenceprofile" "test_applicationpersistenceprofile" {
  name             = "terraform-app-pers-profile"
  tenant_ref       = data.avi_tenant.default_tenant.id
  persistence_type = "PERSISTENCE_TYPE_CLIENT_IP_ADDRESS"
}

resource "avi_healthmonitor" "test_hm_1" {
  name       = "terraform-monitor"
  type       = "HEALTH_MONITOR_HTTP"
  tenant_ref = data.avi_tenant.default_tenant.id
}

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 controller objects read-only via a data source:

data "avi_applicationprofile" "system_http_profile" {
  name = "System-HTTP"
}
# use as: application_profile_ref = data.avi_applicationprofile.system_http_profile.id

More end-to-end examples (AWS/Azure/GCP/NSX-T/OpenStack/vSphere, WAF, GSLB, Horizon, autoscale) live under examples/.

Development workflow

make build13        # build + install locally (also runs fmtcheck)
make fmt             # gofmt -w over the tree
make fmtcheck        # scripts/gofmtcheck.sh — CI-equivalent format check
make vet             # go vet
make errcheck        # scripts/errcheck.sh

Adding/changing a resource:

  1. Confirm whether the object type is actually generated upstream — check if a matching website/docs/r/*.html.markdown and Avi API object already exist. If this is a genuine new object type, add resource_avi_<object>.go + datasource_avi_<object>.go following the pattern in an existing simple resource (e.g. resource_avi_healthmonitor.go): a Resource<Object>Schema() map, a thin resourceAvi<Object>() wired to utils.go's generic CRUD, and register both in provider.go's ResourcesMap/DataSourcesMap.
  2. Add the docs page under website/docs/r/ (and d/ for the data source).
  3. Add acceptance tests (resource_avi_<object>_test.go, data_source_avi_<object>_test.go).

Testing

make test            # unit tests, no live controller needed
make testacc         # acceptance tests — TF_ACC=1, creates REAL objects against a live Avi Controller

Acceptance tests need AVI_CONTROLLER, AVI_USERNAME, AVI_PASSWORD (or token equivalents) in the environment, cost real controller resources, and can take a long time (testacc uses a 120m timeout). Run a single test with specific_test=TestAcc... make testacc.

conftest.py / test_terraform_acc.py are pytest wrappers used by the internal CI pipeline to shell out to make testacc and capture logs — not needed for local go test development.

Linting / CI

  • .github/workflows/golangci-lint.yml runs golangci-lint (enabled: errcheck, gofmt, gosimple, ineffassign, nakedret, misspell, vet, vetshadow; see .golangci.yml). avi/resource_avi_rest_dependants.go is excluded.
  • .github/workflows/release.yml + .goreleaser.yml handle tagged releases (multi-OS/arch builds, checksums, GPG-signed, draft GitHub release).

Contributing / ownership

  • CODEOWNERS: @mayank-avinetworks @manojkumarjain own the whole repo by default.
  • See CONTRIBUTING.md for branch/PR/commit-message conventions (CLA required).
  • CHANGELOG.md tracks released versions; reference internal AV-xxxxx ticket IDs and/or GitHub issue numbers in bug-fix entries, matching existing style.

About

Terraform AVI Networks provider

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

35 stars

Watchers

12 watching

Forks

Releases

Used by

Contributors

Languages