Terraform provider for the busbar LLM gateway, driving
its admin API.
Contents
- A generated Go API client (
internal/apiclient, from busbar's OpenAPI 3.1 contract).
- Provider authentication: the operator token as the
x-admin-token header, plus
optional mTLS / custom CA / insecure-skip-verify for the admin plane.
- One read-only data source,
busbar_info → GET /api/v1/admin/info.
- Three resources:
busbar_virtual_key — mint/read/update/revoke a governance virtual key
(POST/GET/PATCH/DELETE /api/v1/admin/keys). The plaintext secret is returned
once, at creation, and stored as a sensitive value.
busbar_hook — register/read/replace/remove a routing hook
(POST/GET/PUT/DELETE /api/v1/admin/hooks).
busbar_config — a GitOps singleton that applies the whole running config
document (POST /api/v1/admin/config/apply) and tracks config_version.
Per-resource documentation lives under docs/ (generated by tfplugindocs);
runnable examples are under examples/.
Provider configuration
provider "busbar" {
endpoint = "https://busbar-admin.internal:8081" # required; admin listener URL
token = var.busbar_admin_token # required; sent as x-admin-token
# mTLS, when the admin plane requires client certs:
# client_cert_pem = file("client.crt")
# client_key_pem = file("client.key")
# ca_cert_pem = file("admin-ca.crt") # trust a private admin server cert
# insecure = false # skip TLS verify (dev only)
}
endpoint and token fall back to the BUSBAR_ENDPOINT and BUSBAR_ADMIN_TOKEN
environment variables, so provider "busbar" {} with those set is valid.
The busbar_info data source
data "busbar_info" "this" {}
output "gateway_version" {
value = data.busbar_info.this.version
}
Surfaced attributes (all computed): version, uptime_seconds, started_at,
config_persistence, config_version, auth_modules, hook_plugins,
weighted_floor, pools, models, providers.
Building
make generate # regenerate the client from internal/apiclient/openapi.json
make build # -> ./terraform-provider-busbar
make fmt vet test
The API client is generated with oapi-codegen
(pinned in tools.go); internal/apiclient/client.gen.go is generated — do not hand-edit it.
Local development (dev overrides)
Point Terraform at the locally built binary instead of the registry:
make build
cat > dev.tfrc <<EOF
provider_installation {
dev_overrides {
"GetBusbar/busbar" = "$(pwd)"
}
direct {}
}
EOF
export TF_CLI_CONFIG_FILE="$(pwd)/dev.tfrc"
Then, in a directory with a .tf using the provider:
terraform providers schema -json # inspect the loaded schema (no init needed)
terraform plan # reads busbar_info against the live gateway
With dev overrides, skip terraform init — Terraform prints a warning that the
provider is dev-overridden, which is expected.
Acceptance tests
Gated on TF_ACC; require a reachable gateway:
BUSBAR_ENDPOINT=http://localhost:8081 \
BUSBAR_ADMIN_TOKEN=… \
make testacc
The suite (TestAcc*) runs the real Create→Read→Update→Delete→Import lifecycle for
each resource against a live gateway. A disposable gateway is recommended, since the
config and hook tests bump the gateway's config_version.
terraform-registry-manifest.json (protocol 6.0), .goreleaser.yml, and the
release workflow are in place. To publish under registry.terraform.io/GetBusbar/busbar:
- Create the GitHub repo
GetBusbar/terraform-provider-busbar and push.
- Generate a GPG signing key; add
GPG_PRIVATE_KEY (ASCII-armored) and, if the key
has one, PASSPHRASE as repository secrets. The release workflow exports the key
fingerprint to GPG_FINGERPRINT for GoReleaser.
- Register the provider on registry.terraform.io (add the GPG public key there).
- Push a
vX.Y.Z tag — the release workflow runs GoReleaser and the registry ingests
the resulting GitHub release.