Skip to content

Commit a4f9b6c

Browse files
authored
feat: migrate provider to generated schema (#1208)
- add code generation tooling (parser, templates, docs, tests) to mirror libvirtxml - switch domain, network, pool, and volume resources plus examples/docs to the generated schemas/models/conversions - add schema helpers, lint fixes, and improved snake_case utility
1 parent a33277d commit a4f9b6c

38 files changed

+5806
-6096
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ jobs:
2727
- uses: actions/setup-go@v5
2828
with:
2929
go-version: ${{ matrix.go-version }}
30+
- name: Generate code
31+
run: make generate
3032
- name: golangci-lint
3133
uses: golangci/golangci-lint-action@v7
3234
with:

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Binaries
22
terraform-provider-libvirt
3+
/codegen
34
*.exe
45
*.dll
56
*.so
@@ -35,3 +36,9 @@ override.tf.json
3536
# OS
3637
.DS_Store
3738
Thumbs.db
39+
40+
# Generated code
41+
internal/generated/*.gen.go
42+
43+
tmp
44+
tmp/

AGENTS.md

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -189,28 +189,23 @@ Example:
189189

190190
**Key principle**: If libvirt XML has a container element (like `<devices>`), we must have a corresponding nested object in HCL.
191191

192-
**Preserve User Intent Pattern**
192+
**Field Read Semantics**
193193

194-
**Rule**: Only populate optional fields in state if the user explicitly specified them in their configuration.
194+
Terraform state reflects what the user cares about, not the entire API response.
195195

196-
**Why**: Libvirt sets defaults for many optional fields. If we naively read all values back, Terraform detects drift between null (user didn't specify) and libvirt's default, causing unwanted plan diffs.
196+
**Computed** (not Optional) - Always read from API
197+
- Examples: `id`, `key`, `allocation`, `physical`
198+
- `model.Key = types.StringValue(xml.Key)`
197199

198-
**Apply to**: Optional fields where libvirt provides defaults (on_poweroff, current_memory, boot_devices, autostart, unit, type, etc.)
200+
**Optional** (with or without Computed) - Only read if user specified
201+
- If user didn't specify, don't populate (libvirt defaults are irrelevant)
202+
- Examples: `on_poweroff`, `type`, `capacity` (when optional)
203+
- `if !plan.Field.IsNull() { model.Field = types.StringValue(xml.Field) }`
199204

200-
**Don't apply to**: Required fields (name, memory) or purely computed fields (uuid, id)
205+
**Required** - Always read
206+
- User must specify, always in state
201207

202-
Example:
203-
```go
204-
// ❌ WRONG
205-
if domain.OnPoweroff != "" {
206-
model.OnPoweroff = types.StringValue(domain.OnPoweroff)
207-
}
208-
209-
// ✅ CORRECT
210-
if !model.OnPoweroff.IsNull() && !model.OnPoweroff.IsUnknown() && domain.OnPoweroff != "" {
211-
model.OnPoweroff = types.StringValue(domain.OnPoweroff)
212-
}
213-
```
208+
Key insight: The `Optional` flag means "only populate if user cares", regardless of whether it's also Computed.
214209

215210
## Project Structure
216211

Makefile

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: help build install test testacc testacc-tofu sweep lint fmt clean
1+
.PHONY: help build install test testacc testacc-tofu sweep lint fmt clean generate
22

33
# Default target
44
.DEFAULT_GOAL := help
@@ -13,7 +13,11 @@ help: ## Display this help message
1313
@echo "Terraform Provider Libvirt - Available targets:"
1414
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}'
1515

16-
build: ## Build the provider binary
16+
generate: ## Run code generation
17+
@echo "Running code generator..."
18+
@go run ./internal/codegen
19+
20+
build: generate ## Build the provider binary
1721
@echo "Building terraform-provider-libvirt..."
1822
@go build $(LDFLAGS) -o terraform-provider-libvirt
1923

@@ -23,11 +27,11 @@ install: build ## Install the provider to local Terraform plugin directory
2327
@cp terraform-provider-libvirt ~/.terraform.d/plugins/registry.terraform.io/dmacvicar/libvirt/$(VERSION)/linux_amd64/
2428
@echo "Installed to ~/.terraform.d/plugins/registry.terraform.io/dmacvicar/libvirt/$(VERSION)/linux_amd64/"
2529

26-
test: ## Run unit tests
30+
test: generate ## Run unit tests
2731
@echo "Running unit tests..."
2832
@go test ./... -v
2933

30-
testacc: ## Run acceptance tests (requires running libvirt)
34+
testacc: generate ## Run acceptance tests (requires running libvirt)
3135
@echo "Running acceptance tests..."
3236
@TF_ACC=1 go test -count=1 -v -timeout 10m ./internal/provider
3337

@@ -38,7 +42,7 @@ sweep: ## Clean up leaked test resources from failed tests
3842
@echo "Running test sweepers..."
3943
@cd internal/provider && go test -sweep=$(shell if [ -n "$$LIBVIRT_TEST_URI" ]; then echo "$$LIBVIRT_TEST_URI"; else echo "qemu:///system"; fi) -timeout 10m .
4044

41-
lint: ## Run golangci-lint
45+
lint: generate ## Run golangci-lint
4246
@echo "Verifying golangci-lint config..."
4347
@golangci-lint config verify
4448
@echo "Running golangci-lint..."

0 commit comments

Comments
 (0)