Newer
Older
openstack-caracal-dc-dc / .claude / skills / openstack-cloud-ops / references / opentofu-provider-docs.md

OpenTofu / provider documentation -- sources, versions, and fetch method

Read this before writing or extending anything under repo opentofu/ (the VR1 DC-DC infrastructure-as-code, D-103). Built up during the 2026-07-09 OpenTofu delivery; see repo opentofu/README.md for the full, per-module account (schema notes, an "Audit pass" section, and every finding's exact sourcing) -- this file is the index into that plus the fetch methodology, so a future session does not have to rediscover it by trial and error.

The core lesson: doc-summarization is lossy, real example code is not

Every provider doc page fetched this session went through a summarizing model, which reliably got FIELD NAMES right but repeatedly lost or mis-stated CALL SYNTAX (block vs. attribute style, exact nesting). The opentofu/ scaffold shipped with a real syntax bug from trusting doc summaries alone (fixed once real example .tf files were fetched and read directly -- see repo opentofu/README.md's syntax-bug note). For any new provider/resource: find real example .tf/.go source before trusting a doc-summary's syntax claims. Doc-summaries are fine for "what fields exist"; they are not reliable for "how do I write this."

Fetch gotchas

  • The Terraform/OpenTofu Registry's own doc pages (registry.terraform.io/ providers/.../docs) are client-side-rendered -- a plain fetch returns only the page shell, no content. Go straight to the provider's GitHub repo instead.
  • GitHub's raw file URLs need the CORRECT default branch (varies: main for some repos, master for others -- check api.github.com/repos/<org>/<repo> for the default_branch field first, don't guess).
  • A general web search's own synthesized "summary" of a doc page can itself be wrong (encountered once this session: a search summary confidently named the wrong branch and file path). Treat search-result summaries as leads to verify, not answers -- always follow through to the primary source.
  • When a fetch refuses to "reproduce verbatim" (copyright caution), ask for a specific, narrow thing instead -- "list bare field names only, no prose" reliably works where "reproduce this page" does not.
  • api.github.com/repos/<org>/<repo>/contents/<path> (a JSON directory listing) is a reliable way to discover the REAL current file layout when a guessed raw-file path 404s -- doc reorganizations happen (one provider moved from website/docs/r/*.markdown to docs/resources/*.md between the versions training data and current reality disagree on).

Providers used in repo opentofu/

dmacvicar/libvirt (pinned 0.9.8, confirmed 2026-07-09)

Before writing any libvirt_domain, read references/platform-traps.md section 1. Four schema-level traps there have each cost real time and none of them is a validate-time error: bare memory is KiB not MiB; no features block means acpi=off; no cpu block means no svm (nested KVM silently impossible); and "will be updated in-place" still BOUNCES the guest.

  • Registry: https://registry.terraform.io/providers/dmacvicar/libvirt/latest (JS-rendered -- use the GitHub repo for actual content)
  • GitHub: https://github.com/dmacvicar/terraform-provider-libvirt (default branch main; there is no CHANGELOG.md -- the release NOTES on the releases page are the changelog, and they are unusually informative: .../releases/tag/v0.9.0 is the breaking-rewrite rationale, v0.9.1 is the 0.9.0->0.9.1 attribute-rename migration guide)
  • Version boundary that invalidates most examples on the internet: 0.9.0 (2025-11-08) is a compatibility-BREAKING rewrite (plugin framework, "HCL maps almost 1:1 to libvirt XML"); the legacy provider lives on the v0.8 branch. 0.9.1 then code-generated the schema and renamed attributes again. Anything 0.8-era -- including model memory -- is wrong for this pin.
  • Docs: docs/resources/*.md, docs/data-sources/*.md (NOT the older website/docs/r/*.markdown layout some search results/training data reference -- that's stale)
  • Real example .tf files (the higher-value source): examples/*.tf -- domain_with_network.tf, alpine_cloudinit.tf were the two that resolved every syntax question this session. Fetch these FIRST for any new resource, before the doc pages.
  • Key fact: this provider code-generates its schema as a 1:1 mirror of libvirt's own domain/network/pool XML (confirmed via a general search of provider discussion, not the docs pages themselves) -- when a Terraform schema question stalls, libvirt's own native XML docs (https://libvirt.org/formatdomain.html, https://www.libvirt.org/pci-addresses.html) are a legitimate, stable cross-reference for what a nested attribute is likely to be named/shaped, since the mapping is direct.

canonical/maas (pinned 2.7.2, confirmed 2026-07-09)

  • Registry: https://registry.terraform.io/providers/canonical/maas/latest (same JS-rendering issue -- use GitHub)
  • GitHub: https://github.com/canonical/terraform-provider-maas (default branch master -- NOT main, confirmed by checking default_branch directly rather than assuming)
  • Docs: docs/resources/*.md, docs/index.md (provider block config)
  • Moved from an older maas/maas registry namespace -- use canonical/maas, not maas/maas, for anything current.
  • Key lesson (see repo opentofu/README.md's "MAAS registration + tc netem research" section for the full account): maas_vm_host (register a virsh chassis) and maas_vm_host_machine (MAAS composes/creates a new VM itself) are NOT interchangeable -- read the schema (which fields are INPUTS) before assuming a resource matches a design intent just because its name sounds related.

OpenTofu core (language features, not a provider)

OPNsense (not a Terraform provider -- the guest OS itself)

SUPERSEDED RESEARCH WARNING (2026-07-12/13). repo opentofu/README.md's "OPNsense deployment research" section and the 2026-07-09 changelogs describe a config-ISO / Configuration-Importer delivery path. That path is DEAD and its code is DELETED:

  • D-112: the Configuration Importer can NEVER fire on a pre-installed nano image (upstream opnsense-importer probes for a read-only root and exits before scanning media). The ISO was inert; nothing was ever going to read it.
  • D-113 (ADOPTED 2026-07-13, option a2): OPNsense STAYS, but config moves to the REST API. opentofu/templates/opnsense-config.xml.tmpl, scripts/opnsense-render-config.sh and scripts/opnsense-build-config-iso.sh are DELETED, along with the module's config_seed volume + cdrom disk. A rendered-config.xml push would now CLOBBER live API-managed DHCP.

Current path: scripts/opnsense-api.sh (REST client) + scripts/opnsense-bootstrap-apikey.sh (mints a key via OPNsense's own model over SSH). Traps, exact endpoints, the mandatory service/reconfigure step, the 60-second firewall auto-rollback, and the tcsh trap: references/platform-traps.md section 4.

Where the full findings live (don't duplicate here, it will drift)

Caveat first (2026-07-13): repo opentofu/README.md predates D-112/D-113 and its "OPNsense deployment research" section still describes the DELETED config-ISO path -- see the superseded-research warning above before acting on anything it says about OPNsense. Its libvirt schema notes also predate the four domain traps in references/platform-traps.md section 1. Everything else in it still stands.

repo opentofu/README.md is the authoritative, per-module account -- schema notes, what's confirmed vs. assumed per attribute, and a dated "Audit pass" section recording a later re-review (a real documentation error was found and fixed there: an early claim that libvirt interface list-order directly sets OPNsense's LAN/WAN role conflated two separate mechanisms -- read that section before trusting anything about NIC ordering/roles). Treat this file as the index/methodology; treat that one as the ground truth for what each module actually does and why.