Some checks failed
CI / build (push) Failing after 34s
- 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>
91 lines
4.5 KiB
Markdown
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.
|