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.
.
├── 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)
provider.gois 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 aresourceAvi<Object>()/dataSourceAvi<Object>()constructor.- Generic CRUD: individual
resource_avi_*.gofiles mostly just define the Terraform schema (Resource<Object>Schema()) and delegate Create/Read/Update/Delete to the generic helpers inutils.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.goholds schemas for nested/sub-objects referenced by the top-level resources (e.g.ResourceACSubjectInfoSchema). It's large and mechanically generated — it's excluded fromgolangci-lint(skip-filesin.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 inutils.go,provider.go,diff_suppress_func.go, examples, or genuinely hand-maintained resource logic. - Auth:
provider.gosupports 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.gomaintains apostNotAllowedlist (IsPostNotAllowed) for API objects that can't be created via POST (e.g. singleton/system objects likecluster,useraccount) — Create for these effectively becomes a Read/Update against an existing object. - Sensitive field diffs:
AVI_SUPPRESS_SENSITIVE_FIELDS_DIFFenv var (diff_suppress_func.go) can suppress plan diffs on sensitive fields the API masks on read.
- 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
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-aviTerraform 0.13+ (recommended):
make build13Installs 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 {}
}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.idMore end-to-end examples (AWS/Azure/GCP/NSX-T/OpenStack/vSphere, WAF, GSLB, Horizon, autoscale) live
under examples/.
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.shAdding/changing a resource:
- Confirm whether the object type is actually generated upstream — check if a matching
website/docs/r/*.html.markdownand Avi API object already exist. If this is a genuine new object type, addresource_avi_<object>.go+datasource_avi_<object>.gofollowing the pattern in an existing simple resource (e.g.resource_avi_healthmonitor.go): aResource<Object>Schema()map, a thinresourceAvi<Object>()wired toutils.go's generic CRUD, and register both inprovider.go'sResourcesMap/DataSourcesMap. - Add the docs page under
website/docs/r/(andd/for the data source). - Add acceptance tests (
resource_avi_<object>_test.go,data_source_avi_<object>_test.go).
make test # unit tests, no live controller needed
make testacc # acceptance tests — TF_ACC=1, creates REAL objects against a live Avi ControllerAcceptance 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.
.github/workflows/golangci-lint.ymlrunsgolangci-lint(enabled:errcheck,gofmt,gosimple,ineffassign,nakedret,misspell,vet,vetshadow; see.golangci.yml).avi/resource_avi_rest_dependants.gois excluded..github/workflows/release.yml+.goreleaser.ymlhandle tagged releases (multi-OS/arch builds, checksums, GPG-signed, draft GitHub release).
CODEOWNERS:@mayank-avinetworks @manojkumarjainown the whole repo by default.- See
CONTRIBUTING.mdfor branch/PR/commit-message conventions (CLA required). CHANGELOG.mdtracks released versions; reference internalAV-xxxxxticket IDs and/or GitHub issue numbers in bug-fix entries, matching existing style.