Files
Andrew 7dba96409f
Some checks failed
CI / build (push) Failing after 34s
Add project CLAUDE.md and rewrite README.md for current provider
- CLAUDE.md: architecture guide, conventions, type mapping quirks,
  build commands, and common pitfalls for AI-assisted development
- README.md: full resource/data source tables, quick start guide,
  environment variable configuration, and usage examples

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 02:11:28 -04:00

4.5 KiB

CLAUDE.md — Project context for AI assistants

Project Overview

Terraform provider for VirtFusion (virtualization management platform). Written in Go using the Terraform Plugin Framework (not the older SDKv2).

  • Registry address: registry.terraform.io/EZSCALE/virtfusion
  • Git hosting: https://git.ezscale.cloud/EZSCALE/terraform-provider-virtfusion (Gitea, not GitHub)
  • VirtFusion API: Laravel-based REST API with Bearer token auth. API docs defined in openapi.yaml.

Architecture

main.go                          # Entry point, provider server
internal/
  client/
    client.go                    # HTTP client constructor, endpoint normalization
    request.go                   # HTTP methods (Get, Post, Put, Delete, GetAllPages)
    types.go                     # API request/response struct definitions
    errors.go                    # APIError type with status code helpers
  provider/
    provider.go                  # Provider config, resource/datasource registration,
                                 # shared pagination helpers (resultsSchemaAttribute, resultsQueryParam)
    resource_*.go                # Managed resources (20 total)
    data_source_*.go             # Data sources (30 total)

Key Conventions

API Client

  • All HTTP methods return (json.RawMessage, error) — raw JSON to be unmarshalled by the caller.
  • GetAllPages(ctx, path) handles Laravel-style pagination automatically: fetches all pages, merges data arrays, returns a synthetic {"data": [...]} response. Use this for all list endpoints.
  • Query parameters must be appended to the path string (e.g., /servers?results=300). The client splits path from query before calling url.JoinPath to avoid %3F encoding.
  • List endpoints use ?results=N to set page size (default 300 via defaultResultsPerPage).

Data Sources

  • List data sources use GetAllPages and expose an optional results attribute (default 300).
  • Single-item data sources use Get and take a required id attribute.
  • Server list responses use a flat structure; single server GET returns nested objects (cpu.cores, settings.resources.memory, etc.).

Resources

  • Server creation uses ServerCreateRequest (POST /servers) then separate PUT/POST calls for update-only attributes (name, CPU throttle, VNC, suspend, etc.).
  • User resources are keyed by ext_relation_id (external relation ID), not numeric ID.
  • Security: All user-supplied strings interpolated into URL paths MUST be wrapped with url.PathEscape().
  • Sensitive attributes: api_token, password, token, and auth token url fields must be marked Sensitive: true in schemas.

API Type Mappings (known quirks)

  • ServerData.Suspended is bool (API returns true/false, not 0/1).
  • ServerData uses ownerId (not userId) and nests resources under cpu.cores, settings.resources.*.
  • PackageData uses primaryStorage, primaryNetworkSpeedIn, primaryNetworkSpeedOut (not storage, networkSpeedInbound, etc.).
  • IPBlockData.Type is int64 (4=IPv4, 6=IPv6). Gateway/netmask are nested under ipv4.
  • Hypervisor group resources returns a paginated array of per-hypervisor entries, not a single aggregate object.
  • API error bodies are truncated to 500 bytes in error messages to prevent leaking sensitive data.

Build & Test

# Build
go build ./...

# Install locally (goes to $GOPATH/bin)
go install .

# Lint
golangci-lint run

# Run against live VirtFusion (read-only test)
# Requires ~/.terraformrc with dev_overrides and test/main.tf (gitignored)
cd test && terraform apply -auto-approve

Environment Variables

  • VIRTFUSION_ENDPOINT — API base URL (e.g., https://cp.example.com or https://cp.example.com/api/v1)
  • VIRTFUSION_API_TOKEN — API bearer token

CI/CD

Uses Gitea Actions (.gitea/workflows/). GoReleaser for binary releases (.goreleaser.yml).

Common Pitfalls

  • url.JoinPath encodes ? as %3F — never put query params in the path argument. The client handles this by splitting at ? first.
  • The VirtFusion /servers endpoint caps at 20 results per page regardless of the results parameter. GetAllPages handles this transparently by fetching all pages.
  • Don't use json:"storage" for package storage — the API field is json:"primaryStorage".
  • Single server GET and list server responses have different shapes. ServerData type handles both via optional nested pointer fields.