ARCHITECTURE: PRIMARY source of truth — action rules (redeploy inline, others excluded), 401 retry, API endpoint auto-detect
This commit is contained in:
+49
-13
@@ -1,8 +1,10 @@
|
||||
# Provider Architecture (Source of Truth)
|
||||
# Provider Architecture (PRIMARY SOURCE OF TRUTH)
|
||||
|
||||
**⛔ THIS FILE IS THE FOUNDATION. ALL CODE AND SCRIPTS ARE DERIVED FROM IT.**
|
||||
|
||||
This document defines the project-wide architecture and rules for generation,
|
||||
provider behavior, and documentation. It is the single source of truth for
|
||||
implementation and DevOps workflow.
|
||||
provider behavior, and documentation. Any change to provider logic MUST be
|
||||
reflected here FIRST, then implemented in `gen_v2` and other tools.
|
||||
|
||||
## Core Principles
|
||||
|
||||
@@ -12,6 +14,7 @@ implementation and DevOps workflow.
|
||||
4) Documentation is generated from the same YAML.
|
||||
5) Build artifacts for 3 OS targets are published to the registry, and docs are
|
||||
published to the website.
|
||||
6) `devops/ARCHITECTURE.md` (this file) is the primary spec. Code follows.
|
||||
|
||||
## Service Selection
|
||||
|
||||
@@ -19,6 +22,12 @@ implementation and DevOps workflow.
|
||||
- Each line starts with service_id, followed by service name/alias.
|
||||
- Operation timeouts source is defined by: `devops/config/operation_timeouts.json`.
|
||||
|
||||
## API Endpoint
|
||||
|
||||
The provider supports two API styles, auto-detected by `NUBES_API_ENDPOINT`:
|
||||
- **Legacy proxy**: contains `index.cfm` → `?endpoint=/path`
|
||||
- **REST Gateway**: no `index.cfm` → direct path concatenation
|
||||
|
||||
## Unified YAML (Per Service)
|
||||
|
||||
One YAML file per service. This is the only input for:
|
||||
@@ -39,16 +48,33 @@ Required top-level fields:
|
||||
### Operations: Kinds and Rules
|
||||
|
||||
Each operation has a kind:
|
||||
- kind: instance (CRUD for the service instance, plus suspend/resume)
|
||||
- kind: subresource (CRUD for objects inside the service, e.g. users/databases)
|
||||
- kind: action (one-shot operations, e.g. restart/recovery/redeploy)
|
||||
|
||||
**instance** — CRUD for the service instance, plus suspend/resume:
|
||||
| API action | Terraform behavior |
|
||||
|---|---|
|
||||
| create | `terraform apply` (new resource) |
|
||||
| delete | `terraform destroy` |
|
||||
| modify | `terraform apply` (params changed) |
|
||||
| suspend | `terraform destroy` when `suspend_on_destroy=true` |
|
||||
| resume | `terraform apply` when `adopt_existing_on_create=true` |
|
||||
|
||||
**subresource** — CRUD for objects inside the service (users, databases, topics):
|
||||
- Exposed as separate resources: `nubes_{service}_{subresource}`
|
||||
- Identity = `{parent_instance_uid, subresource_key}` (e.g. `{postgres_id, username}`)
|
||||
- Supports `adopt_existing_on_create` — if subresource already exists, adopt it instead of failing
|
||||
|
||||
**action** — one-shot operations. **Only `redeploy` is included**:
|
||||
- `redeploy` → **inline**: field `git_revision` in the main resource. When it changes, call redeploy instead of (or after) modify
|
||||
- `restart`, `recovery`, `reconcile` → **excluded**. These are manual operational tasks, performed via UI only. Reason:
|
||||
- `restart` — modify handles pod restart when needed
|
||||
- `recovery` — creates a new instance from backup, not a modification of existing
|
||||
- `reconcile` — sync after manual changes; Terraform owns its own state
|
||||
|
||||
### Idempotency Rules
|
||||
|
||||
- instance CRUD is idempotent via standard Terraform behavior.
|
||||
- subresource CRUD is idempotent by resource identity.
|
||||
- action operations are idempotent via a trigger field (e.g. run_id/nonce).
|
||||
If the trigger does not change, the action is not re-run.
|
||||
- `redeploy`: idempotent via `git_revision` field — if unchanged, no redeploy
|
||||
|
||||
### Lifecycle Behavior
|
||||
|
||||
@@ -83,6 +109,13 @@ Each operation has a kind:
|
||||
- Core is universal: no service-specific logic inside the core.
|
||||
- Generated service resources contain only schema/params and references.
|
||||
|
||||
### API Resilience
|
||||
|
||||
- Core MUST retry transient 401 errors from Gateway (3 attempts, exponential backoff).
|
||||
Gateway may temporarily reject valid JWT tokens.
|
||||
- GET operations (GetInstanceState, GetInstanceStateRaw) retry 401 with 2s/4s/8s backoff.
|
||||
- `doRequest` treats 401 as retryable for GET requests (alongside 429, 502, 503, 504).
|
||||
|
||||
### Subresource Resources
|
||||
|
||||
Subresource operations are exposed as standard resources.
|
||||
@@ -98,14 +131,17 @@ resource "nubes_postgres_user" "user1" {
|
||||
role = "app_user"
|
||||
}
|
||||
|
||||
### Action Resources
|
||||
### Redeploy (inline action)
|
||||
|
||||
Services with `redeploy` operation get a `git_revision` field in the main resource.
|
||||
Changing `git_revision` triggers `redeploy` instead of `modify`.
|
||||
|
||||
Action operations are exposed as action resources with a trigger field.
|
||||
Example HCL:
|
||||
|
||||
resource "nubes_postgres_restart" "restart1" {
|
||||
postgres_id = nubes_postgres.db.id
|
||||
run_id = "2026-02-20-001"
|
||||
resource "nubes_flask" "app" {
|
||||
resource_name = "my-flask"
|
||||
git_revision = "abc123" # ← change this to trigger redeploy
|
||||
app_configuration = jsonencode({...})
|
||||
}
|
||||
|
||||
## Concurrency and State Locking
|
||||
|
||||
Reference in New Issue
Block a user