docs: add human-friendly documentation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5626d99a17
commit
42024ef476
3 changed files with 534 additions and 0 deletions
252
docs/architecture.md
Normal file
252
docs/architecture.md
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
---
|
||||
title: Architecture
|
||||
description: Internal design of go-infra -- shared HTTP client, provider clients, configuration model, and CLI command structure.
|
||||
---
|
||||
|
||||
# Architecture
|
||||
|
||||
go-infra is organised into four layers: a shared HTTP client, provider-specific API clients, a declarative configuration parser, and CLI commands that tie them together.
|
||||
|
||||
```
|
||||
cmd/prod/ CLI commands (setup, status, dns, lb, ssh)
|
||||
cmd/monitor/ CLI commands (security finding aggregation)
|
||||
|
|
||||
v
|
||||
config.go YAML config parser (infra.yaml)
|
||||
hetzner.go Hetzner Cloud + Robot API clients
|
||||
cloudns.go CloudNS DNS API client
|
||||
|
|
||||
v
|
||||
client.go Shared APIClient (retry, backoff, rate-limit)
|
||||
|
|
||||
v
|
||||
net/http Go standard library
|
||||
```
|
||||
|
||||
## Shared HTTP Client (`client.go`)
|
||||
|
||||
All provider-specific clients delegate HTTP requests to `APIClient`, which provides:
|
||||
|
||||
- **Exponential backoff with jitter** -- retries on 5xx errors and network failures
|
||||
- **Rate-limit compliance** -- honours `Retry-After` headers on 429 responses
|
||||
- **Configurable authentication** -- each provider injects its own auth function
|
||||
- **Context-aware cancellation** -- all waits respect `context.Context` deadlines
|
||||
|
||||
### Key Types
|
||||
|
||||
```go
|
||||
type APIClient struct {
|
||||
client *http.Client
|
||||
retry RetryConfig
|
||||
authFn func(req *http.Request)
|
||||
prefix string // error message prefix, e.g. "hcloud API"
|
||||
mu sync.Mutex
|
||||
blockedUntil time.Time // rate-limit backoff window
|
||||
}
|
||||
|
||||
type RetryConfig struct {
|
||||
MaxRetries int // 0 = no retries
|
||||
InitialBackoff time.Duration // delay before first retry
|
||||
MaxBackoff time.Duration // upper bound on backoff duration
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration via Options
|
||||
|
||||
`APIClient` uses the functional options pattern:
|
||||
|
||||
```go
|
||||
client := infra.NewAPIClient(
|
||||
infra.WithHTTPClient(customHTTPClient),
|
||||
infra.WithAuth(func(req *http.Request) {
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
}),
|
||||
infra.WithRetry(infra.RetryConfig{
|
||||
MaxRetries: 5,
|
||||
InitialBackoff: 200 * time.Millisecond,
|
||||
MaxBackoff: 10 * time.Second,
|
||||
}),
|
||||
infra.WithPrefix("my-api"),
|
||||
)
|
||||
```
|
||||
|
||||
Default configuration (from `DefaultRetryConfig()`): 3 retries, 100ms initial backoff, 5s maximum backoff.
|
||||
|
||||
### Request Flow
|
||||
|
||||
The `Do(req, result)` and `DoRaw(req)` methods follow this flow for each attempt:
|
||||
|
||||
1. **Rate-limit check** -- if a previous 429 response set `blockedUntil`, wait until that time passes (or the context is cancelled).
|
||||
2. **Apply authentication** -- call `authFn(req)` to inject credentials.
|
||||
3. **Execute request** -- send via the underlying `http.Client`.
|
||||
4. **Handle response**:
|
||||
- **429 Too Many Requests** -- parse `Retry-After` header, set `blockedUntil`, and retry.
|
||||
- **5xx Server Error** -- retryable; sleep with exponential backoff + jitter.
|
||||
- **4xx Client Error** (except 429) -- not retried; return error immediately.
|
||||
- **2xx Success** -- if `result` is non-nil, JSON-decode the body into it.
|
||||
5. If all attempts are exhausted, return the last error.
|
||||
|
||||
The backoff calculation uses `base = initialBackoff * 2^attempt`, capped at `maxBackoff`, with jitter applied as a random factor between 50% and 100% of the calculated value.
|
||||
|
||||
### Do vs DoRaw
|
||||
|
||||
- `Do(req, result)` -- decodes the response body as JSON into `result`. Pass `nil` for fire-and-forget requests (e.g. DELETE).
|
||||
- `DoRaw(req)` -- returns the raw `[]byte` response body. Used by CloudNS, whose responses need manual parsing due to inconsistent JSON shapes.
|
||||
|
||||
## Hetzner Clients (`hetzner.go`)
|
||||
|
||||
Two separate clients cover Hetzner's two distinct APIs.
|
||||
|
||||
### HCloudClient (Hetzner Cloud API)
|
||||
|
||||
Manages cloud servers, load balancers, and snapshots via `https://api.hetzner.cloud/v1`. Uses bearer token authentication.
|
||||
|
||||
```go
|
||||
hc := infra.NewHCloudClient("your-token")
|
||||
```
|
||||
|
||||
**Operations:**
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `ListServers(ctx)` | List all cloud servers |
|
||||
| `ListLoadBalancers(ctx)` | List all load balancers |
|
||||
| `GetLoadBalancer(ctx, id)` | Get a load balancer by ID |
|
||||
| `CreateLoadBalancer(ctx, req)` | Create a load balancer from a typed request struct |
|
||||
| `DeleteLoadBalancer(ctx, id)` | Delete a load balancer by ID |
|
||||
| `CreateSnapshot(ctx, serverID, description)` | Create a server snapshot |
|
||||
|
||||
**Data model hierarchy:**
|
||||
|
||||
```
|
||||
HCloudServer
|
||||
+-- HCloudPublicNet --> HCloudIPv4
|
||||
+-- []HCloudPrivateNet
|
||||
+-- HCloudServerType (name, cores, memory, disk)
|
||||
+-- HCloudDatacenter
|
||||
|
||||
HCloudLoadBalancer
|
||||
+-- HCloudLBPublicNet --> HCloudIPv4
|
||||
+-- HCloudLBAlgorithm
|
||||
+-- []HCloudLBService
|
||||
| +-- HCloudLBHTTP (optional)
|
||||
| +-- HCloudLBHealthCheck --> HCloudLBHCHTTP (optional)
|
||||
+-- []HCloudLBTarget
|
||||
+-- HCloudLBTargetIP (optional)
|
||||
+-- HCloudLBTargetServer (optional)
|
||||
+-- []HCloudLBHealthStatus
|
||||
```
|
||||
|
||||
### HRobotClient (Hetzner Robot API)
|
||||
|
||||
Manages dedicated (bare-metal) servers via `https://robot-ws.your-server.de`. Uses HTTP Basic authentication.
|
||||
|
||||
```go
|
||||
hr := infra.NewHRobotClient("user", "password")
|
||||
```
|
||||
|
||||
**Operations:**
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `ListServers(ctx)` | List all dedicated servers |
|
||||
| `GetServer(ctx, ip)` | Get a server by IP address |
|
||||
|
||||
The Robot API wraps each server object in a `{"server": {...}}` envelope. `HRobotClient` unwraps this automatically.
|
||||
|
||||
## CloudNS Client (`cloudns.go`)
|
||||
|
||||
Manages DNS zones and records via `https://api.cloudns.net`. Uses query-parameter authentication (`auth-id` + `auth-password`).
|
||||
|
||||
```go
|
||||
dns := infra.NewCloudNSClient("12345", "password")
|
||||
```
|
||||
|
||||
**Operations:**
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `ListZones(ctx)` | List all DNS zones |
|
||||
| `ListRecords(ctx, domain)` | List all records in a zone (returns `map[id]CloudNSRecord`) |
|
||||
| `CreateRecord(ctx, domain, host, type, value, ttl)` | Create a record; returns the new record ID |
|
||||
| `UpdateRecord(ctx, domain, id, host, type, value, ttl)` | Update an existing record |
|
||||
| `DeleteRecord(ctx, domain, id)` | Delete a record by ID |
|
||||
| `EnsureRecord(ctx, domain, host, type, value, ttl)` | Idempotent create-or-update; returns whether a change was made |
|
||||
| `SetACMEChallenge(ctx, domain, value)` | Create a `_acme-challenge` TXT record with 60s TTL |
|
||||
| `ClearACMEChallenge(ctx, domain)` | Delete all `_acme-challenge` TXT records in a zone |
|
||||
|
||||
**CloudNS quirks handled internally:**
|
||||
|
||||
- Empty zone lists come back as `{}` (an object) instead of `[]` (an array). `ListZones` handles this gracefully.
|
||||
- All mutations use POST with query parameters (not request bodies).
|
||||
- Response status is checked via a `"status": "Success"` field in the JSON body, not HTTP status codes alone.
|
||||
|
||||
## Configuration Model (`config.go`)
|
||||
|
||||
The `Config` struct represents the full infrastructure topology, parsed from an `infra.yaml` file. It covers:
|
||||
|
||||
```
|
||||
Config
|
||||
+-- Hosts (map[string]*Host) Servers with SSH details, role, and services
|
||||
+-- LoadBalancer Hetzner managed LB (name, type, backends, listeners, health)
|
||||
+-- Network Private network CIDR
|
||||
+-- DNS Provider config + zone records
|
||||
+-- SSL Wildcard certificate settings
|
||||
+-- Database Galera/MariaDB cluster nodes + backup config
|
||||
+-- Cache Redis/Dragonfly cluster nodes
|
||||
+-- Containers (map[string]*Container) Container deployments (image, replicas, depends_on)
|
||||
+-- S3 Object storage endpoint + buckets
|
||||
+-- CDN CDN provider and zones
|
||||
+-- CICD CI/CD provider, runner, registry
|
||||
+-- Monitoring Health endpoints and alert thresholds
|
||||
+-- Backups Daily and weekly backup jobs
|
||||
```
|
||||
|
||||
### Loading
|
||||
|
||||
Two functions load configuration:
|
||||
|
||||
- `Load(path)` -- reads and parses a specific file. Expands `~` in SSH key paths and defaults SSH port to 22.
|
||||
- `Discover(startDir)` -- walks up from `startDir` looking for `infra.yaml`, then calls `Load`. Returns the config, the path found, and any error.
|
||||
|
||||
### Host Queries
|
||||
|
||||
```go
|
||||
// Get all hosts with a specific role
|
||||
appServers := cfg.HostsByRole("app")
|
||||
|
||||
// Shorthand for role="app"
|
||||
appServers := cfg.AppServers()
|
||||
```
|
||||
|
||||
## CLI Commands
|
||||
|
||||
### `core prod` (`cmd/prod/`)
|
||||
|
||||
The production command group reads `infra.yaml` (auto-discovered or specified via `--config`) and provides:
|
||||
|
||||
| Subcommand | Description |
|
||||
|------------|-------------|
|
||||
| `status` | Parallel SSH health check of all hosts. Checks Docker, Galera cluster size, Redis, Traefik, Coolify, Forgejo runner. Also queries Hetzner Cloud for load balancer health if `HCLOUD_TOKEN` is set. |
|
||||
| `setup` | Runs a three-step foundation pipeline: **discover** (enumerate Hetzner Cloud + Robot servers), **lb** (create load balancer from config), **dns** (ensure DNS records via CloudNS). Supports `--dry-run` and `--step` for partial runs. |
|
||||
| `dns list [zone]` | List DNS records for a zone (defaults to `host.uk.com`). |
|
||||
| `dns set <host> <type> <value>` | Idempotent create-or-update of a DNS record. |
|
||||
| `lb status` | Display load balancer details and per-target health status. |
|
||||
| `lb create` | Create the load balancer defined in `infra.yaml`. |
|
||||
| `ssh <host>` | Look up a host by name in `infra.yaml` and `exec` into an SSH session. |
|
||||
|
||||
The `status` command uses `go-ansible`'s `SSHClient` to connect to each host in parallel, then runs shell commands to probe service state (Docker containers, MariaDB cluster, Redis ping, etc.).
|
||||
|
||||
### `core monitor` (`cmd/monitor/`)
|
||||
|
||||
Aggregates security findings from GitHub's Security tab using the `gh` CLI:
|
||||
|
||||
- **Code scanning alerts** -- from Semgrep, Trivy, Gitleaks, CodeQL, etc.
|
||||
- **Dependabot alerts** -- dependency vulnerability alerts.
|
||||
- **Secret scanning alerts** -- exposed secrets/credentials (always classified as critical).
|
||||
|
||||
Findings are normalised to a common `Finding` struct, sorted by severity (critical first), and output as either a formatted table or JSON.
|
||||
|
||||
## Licence
|
||||
|
||||
EUPL-1.2
|
||||
160
docs/development.md
Normal file
160
docs/development.md
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
---
|
||||
title: Development
|
||||
description: How to build, test, and contribute to go-infra.
|
||||
---
|
||||
|
||||
# Development
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Go 1.26+**
|
||||
- **Go workspace** -- this module is part of the workspace at `~/Code/go.work`. After cloning, run `go work sync` if module resolution fails.
|
||||
- **`gh` CLI** (optional) -- required only for `core monitor` commands.
|
||||
|
||||
## Building
|
||||
|
||||
The library package (`infra`) has no binary output. The CLI commands in `cmd/prod/` and `cmd/monitor/` are compiled into the `core` binary via the `forge.lthn.ai/core/cli` module -- they are not standalone binaries.
|
||||
|
||||
To verify the package compiles:
|
||||
|
||||
```bash
|
||||
cd /Users/snider/Code/core/go-infra
|
||||
go build ./...
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# All tests
|
||||
go test ./...
|
||||
|
||||
# With race detector
|
||||
go test -race ./...
|
||||
|
||||
# A specific test
|
||||
go test -run TestAPIClient_Do_Good_Success
|
||||
|
||||
# Verbose output
|
||||
go test -v ./...
|
||||
```
|
||||
|
||||
If the `core` CLI is available:
|
||||
|
||||
```bash
|
||||
core go test
|
||||
core go test --run TestAPIClient_Do_Good_Success
|
||||
```
|
||||
|
||||
### Test Organisation
|
||||
|
||||
Tests follow the `_Good`, `_Bad`, `_Ugly` suffix convention:
|
||||
|
||||
| Suffix | Purpose | Example |
|
||||
|--------|---------|---------|
|
||||
| `_Good` | Happy path -- expected successful behaviour | `TestAPIClient_Do_Good_Success` |
|
||||
| `_Bad` | Expected error conditions -- invalid input, auth failures, exhausted retries | `TestAPIClient_Do_Bad_ClientError` |
|
||||
| `_Ugly` | Edge cases -- context cancellation, malformed data, panics | `TestAPIClient_Do_Ugly_ContextCancelled` |
|
||||
|
||||
### Test Approach
|
||||
|
||||
All API client tests use `net/http/httptest.Server` to mock HTTP responses. No real API calls are made during tests. The test servers simulate:
|
||||
|
||||
- Successful JSON responses
|
||||
- HTTP error codes (400, 401, 403, 404, 500, 502, 503)
|
||||
- Rate limiting (429 with `Retry-After` header)
|
||||
- Transient failures that succeed after retries
|
||||
- Authentication verification (bearer tokens, basic auth, query parameters)
|
||||
|
||||
The config tests use `Discover()` to find a real `infra.yaml` in parent directories (skipped if not present) and also test error paths with nonexistent and malformed files.
|
||||
|
||||
### Test Coverage by File
|
||||
|
||||
| File | Tests | Coverage Focus |
|
||||
|------|-------|----------------|
|
||||
| `client_test.go` | 20 tests | Constructor defaults/options, `Do` JSON decoding, `DoRaw` raw responses, retry on 5xx, no retry on 4xx, rate-limit handling, context cancellation, `parseRetryAfter`, integration with HCloud/CloudNS clients |
|
||||
| `hetzner_test.go` | 10 tests | HCloud/HRobot constructors, `ListServers`, JSON deserialisation of servers/load balancers/Robot servers, auth header verification, error responses |
|
||||
| `cloudns_test.go` | 16 tests | Constructor, auth params, raw HTTP calls, zone/record JSON parsing, CRUD round-trips, ACME challenge helpers, `EnsureRecord` logic (already correct / needs update / needs create), edge cases (empty body, empty map) |
|
||||
| `config_test.go` | 4 tests | `Load` with real config, missing file, invalid YAML, `expandPath` with tilde/absolute/relative paths |
|
||||
|
||||
## Code Style
|
||||
|
||||
- **UK English** in all documentation, comments, and user-facing strings (colour, organisation, centre, serialisation).
|
||||
- **Strict typing** -- all function parameters and return values have explicit types.
|
||||
- **Error wrapping** -- use `fmt.Errorf("context: %w", err)` to preserve error chains.
|
||||
- **Formatting** -- standard `gofmt`. Run `go fmt ./...` or `core go fmt` before committing.
|
||||
|
||||
## Adding a New Provider Client
|
||||
|
||||
To add support for a new infrastructure provider:
|
||||
|
||||
1. Create a new file (e.g. `vultr.go`) in the package root.
|
||||
2. Define a client struct that embeds or holds an `*APIClient`:
|
||||
|
||||
```go
|
||||
type VultrClient struct {
|
||||
apiKey string
|
||||
baseURL string
|
||||
api *APIClient
|
||||
}
|
||||
|
||||
func NewVultrClient(apiKey string) *VultrClient {
|
||||
c := &VultrClient{
|
||||
apiKey: apiKey,
|
||||
baseURL: "https://api.vultr.com/v2",
|
||||
}
|
||||
c.api = NewAPIClient(
|
||||
WithAuth(func(req *http.Request) {
|
||||
req.Header.Set("Authorization", "Bearer "+c.apiKey)
|
||||
}),
|
||||
WithPrefix("vultr API"),
|
||||
)
|
||||
return c
|
||||
}
|
||||
```
|
||||
|
||||
3. Add internal helper methods (`get`, `post`, `delete`) that delegate to `c.api.Do(req, result)`.
|
||||
4. Write tests using `httptest.NewServer` -- never call real APIs in tests.
|
||||
5. Follow the `_Good`/`_Bad`/`_Ugly` test naming convention.
|
||||
|
||||
## Adding CLI Commands
|
||||
|
||||
CLI commands live in subdirectories of `cmd/`. Each command package:
|
||||
|
||||
1. Calls `cli.RegisterCommands(AddXyzCommands)` in an `init()` function (see `cmd/prod/cmd_commands.go`).
|
||||
2. Defines a root `*cli.Command` with subcommands.
|
||||
3. Uses `loadConfig()` to auto-discover `infra.yaml` when needed.
|
||||
|
||||
The `core` binary picks up these commands via blank imports in its main package.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
go-infra/
|
||||
client.go Shared APIClient
|
||||
client_test.go APIClient tests (20 tests)
|
||||
config.go YAML config types + parser
|
||||
config_test.go Config tests (4 tests)
|
||||
hetzner.go HCloudClient + HRobotClient
|
||||
hetzner_test.go Hetzner tests (10 tests)
|
||||
cloudns.go CloudNSClient
|
||||
cloudns_test.go CloudNS tests (16 tests)
|
||||
cmd/
|
||||
prod/
|
||||
cmd_commands.go Command registration
|
||||
cmd_prod.go Root 'prod' command + flags
|
||||
cmd_status.go Parallel host health checks
|
||||
cmd_setup.go Foundation setup pipeline (discover, lb, dns)
|
||||
cmd_dns.go DNS record management
|
||||
cmd_lb.go Load balancer management
|
||||
cmd_ssh.go SSH into production hosts
|
||||
monitor/
|
||||
cmd_commands.go Command registration
|
||||
cmd_monitor.go Security finding aggregation
|
||||
go.mod
|
||||
go.sum
|
||||
CLAUDE.md
|
||||
```
|
||||
|
||||
## Licence
|
||||
|
||||
EUPL-1.2
|
||||
122
docs/index.md
Normal file
122
docs/index.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
---
|
||||
title: go-infra
|
||||
description: Infrastructure provider API clients and YAML-based configuration for managing production environments.
|
||||
---
|
||||
|
||||
# go-infra
|
||||
|
||||
`forge.lthn.ai/core/go-infra` provides typed Go clients for infrastructure provider APIs (Hetzner Cloud, Hetzner Robot, CloudNS) and a declarative YAML configuration layer for describing production topology. It also ships CLI commands for production management (`core prod`) and security monitoring (`core monitor`).
|
||||
|
||||
The library has no framework dependencies beyond the Go standard library, YAML parsing, and testify for tests. All HTTP communication goes through a shared `APIClient` that handles retries, exponential backoff, and rate-limit compliance automatically.
|
||||
|
||||
## Module Path
|
||||
|
||||
```
|
||||
forge.lthn.ai/core/go-infra
|
||||
```
|
||||
|
||||
Requires **Go 1.26+**.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Using the API Clients Directly
|
||||
|
||||
```go
|
||||
import "forge.lthn.ai/core/go-infra"
|
||||
|
||||
// Hetzner Cloud -- list all servers
|
||||
hc := infra.NewHCloudClient(os.Getenv("HCLOUD_TOKEN"))
|
||||
servers, err := hc.ListServers(ctx)
|
||||
|
||||
// Hetzner Robot -- list dedicated servers
|
||||
hr := infra.NewHRobotClient(user, password)
|
||||
dedicated, err := hr.ListServers(ctx)
|
||||
|
||||
// CloudNS -- ensure a DNS record exists
|
||||
dns := infra.NewCloudNSClient(authID, authPassword)
|
||||
changed, err := dns.EnsureRecord(ctx, "example.com", "www", "A", "1.2.3.4", 300)
|
||||
```
|
||||
|
||||
### Loading Infrastructure Configuration
|
||||
|
||||
```go
|
||||
import "forge.lthn.ai/core/go-infra"
|
||||
|
||||
// Auto-discover infra.yaml by walking up from the current directory
|
||||
cfg, path, err := infra.Discover(".")
|
||||
|
||||
// Or load a specific file
|
||||
cfg, err := infra.Load("/path/to/infra.yaml")
|
||||
|
||||
// Query the configuration
|
||||
appServers := cfg.AppServers()
|
||||
for name, host := range appServers {
|
||||
fmt.Printf("%s: %s (%s)\n", name, host.IP, host.Role)
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Commands
|
||||
|
||||
When registered with the `core` CLI binary, go-infra provides two command groups:
|
||||
|
||||
```bash
|
||||
# Production infrastructure management
|
||||
core prod status # Health check all hosts, services, and load balancer
|
||||
core prod setup # Phase 1 foundation: discover topology, create LB, configure DNS
|
||||
core prod setup --dry-run # Preview what setup would do
|
||||
core prod setup --step=dns # Run a single setup step
|
||||
core prod dns list # List DNS records for a zone
|
||||
core prod dns set www A 1.2.3.4 # Create or update a DNS record
|
||||
core prod lb status # Show load balancer status and target health
|
||||
core prod lb create # Create load balancer from infra.yaml
|
||||
core prod ssh noc # SSH into a named host
|
||||
|
||||
# Security monitoring (aggregates GitHub Security findings)
|
||||
core monitor # Scan current repo
|
||||
core monitor --all # Scan all repos in registry
|
||||
core monitor --repo core-php # Scan a specific repo
|
||||
core monitor --severity high # Filter by severity
|
||||
core monitor --json # JSON output
|
||||
```
|
||||
|
||||
## Package Layout
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `client.go` | Shared HTTP API client with retry, exponential backoff, and rate-limit handling |
|
||||
| `config.go` | YAML infrastructure configuration parser and typed config structs |
|
||||
| `hetzner.go` | Hetzner Cloud API (servers, load balancers, snapshots) and Hetzner Robot API (dedicated servers) |
|
||||
| `cloudns.go` | CloudNS DNS API (zones, records, ACME challenge helpers) |
|
||||
| `cmd/prod/` | CLI commands for production infrastructure management (`core prod`) |
|
||||
| `cmd/monitor/` | CLI commands for security finding aggregation (`core monitor`) |
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Direct
|
||||
|
||||
| Module | Purpose |
|
||||
|--------|---------|
|
||||
| `forge.lthn.ai/core/cli` | CLI framework (cobra-based command registration) |
|
||||
| `forge.lthn.ai/core/go-ansible` | SSH client used by `core prod status` for host health checks |
|
||||
| `forge.lthn.ai/core/go-i18n` | Internationalisation strings for monitor command |
|
||||
| `forge.lthn.ai/core/go-io` | Filesystem abstraction used by monitor's registry lookup |
|
||||
| `forge.lthn.ai/core/go-log` | Structured error logging |
|
||||
| `forge.lthn.ai/core/go-scm` | Repository registry for multi-repo monitoring |
|
||||
| `gopkg.in/yaml.v3` | YAML parsing for `infra.yaml` |
|
||||
| `github.com/stretchr/testify` | Test assertions |
|
||||
|
||||
The core library types (`config.go`, `client.go`, `hetzner.go`, `cloudns.go`) only depend on the standard library and `gopkg.in/yaml.v3`. The heavier dependencies (`cli`, `go-ansible`, `go-scm`, etc.) are confined to the `cmd/` packages.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Used by | Description |
|
||||
|----------|---------|-------------|
|
||||
| `HCLOUD_TOKEN` | `prod setup`, `prod status`, `prod lb` | Hetzner Cloud API bearer token |
|
||||
| `HETZNER_ROBOT_USER` | `prod setup` | Hetzner Robot API username |
|
||||
| `HETZNER_ROBOT_PASS` | `prod setup` | Hetzner Robot API password |
|
||||
| `CLOUDNS_AUTH_ID` | `prod setup`, `prod dns` | CloudNS sub-auth user ID |
|
||||
| `CLOUDNS_AUTH_PASSWORD` | `prod setup`, `prod dns` | CloudNS auth password |
|
||||
|
||||
## Licence
|
||||
|
||||
EUPL-1.2
|
||||
Loading…
Add table
Reference in a new issue