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

91 lines
4.5 KiB
Markdown

# CLAUDE.md — Project context for AI assistants
## Project Overview
Terraform provider for VirtFusion (virtualization management platform). Written in Go using the [Terraform Plugin Framework](https://developer.hashicorp.com/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
```bash
# 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.