Add project CLAUDE.md and rewrite README.md for current provider
Some checks failed
CI / build (push) Failing after 34s
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>
This commit is contained in:
90
CLAUDE.md
Normal file
90
CLAUDE.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user