Services could not carry hostnames through cast: `desiredFromManifest` dropped a service's `domains` and warned they were a manual Coolify UI act, citing a re-checked "no flat `domains` on a 4.1.2 service, on any route." The audit (#72) disproved that — the same failure mode #51 corrected for backup schedules. The FLAT shape genuinely has no route; the per-container CAPABILITY was there at 4.1.2 all along. `POST /services` and `PATCH /services/{uuid}` both take a `urls` list ([{name, url}], url comma-joined) that `applyServiceUrls` matches to a `ServiceApplication` by name and stores as its `fqdn`; `GET /services/{uuid}` loads `applications` and returns each `fqdn` (verified against ServicesController v4.1.2). So services now speak the SAME per-container vocabulary a dockercompose app does: - **Manifest:** `service_domains: { <container>: [url] }` replaces the flat, unhonorable `domains` on a service (a flat list cannot name which container a hostname belongs to — exactly what `urls` requires). Canonicalized (keys and each URL array sorted) so container order never false-drifts. - **Write:** `serviceApiFields` builds `urls` on create and update. - **Read/diff:** a supplementary `GET /services/{uuid}` per service (`attachServiceDomains`, gated to `diff`/`apply` like backups) projects `applications[].fqdn` back into `service_domains`, so a declared hostname is compared every run — no perpetual drift, no manual UI step. - **Pre-flight:** a service create's `service_domains` joins `desiredDomainsOfCreate`, the more important because a service create whose domain conflicts is DELETED server-side before the 409 (rollback). Two limits stated out loud: the read is fail-closed (an unreachable/ unrecognized `GET /services/{uuid}` aborts rather than projecting empty and re-PATCHing forever), and `inventory --emit-draft` does not yet make the per-service GET, so a drafted service's hostnames are still declared by hand (same as backups) — draft/semantics say so. `npm run check` clean · 514 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
32 lines
938 B
YAML
32 lines
938 B
YAML
project: widget
|
|
environments:
|
|
prod:
|
|
applications:
|
|
core-api:
|
|
source: { repo: acme/widget, branch: main }
|
|
build: { pack: nixpacks, base_directory: /apps/core }
|
|
port: 3000
|
|
healthcheck: /health
|
|
domains: ["https://api.example.com"]
|
|
env_template: core-api.prod.env.template
|
|
databases:
|
|
postgres:
|
|
type: postgresql
|
|
version: "17"
|
|
backup: { frequency: "0 3 * * *", retention: 7 }
|
|
redis:
|
|
type: redis
|
|
services:
|
|
metabase:
|
|
type: metabase
|
|
service_domains:
|
|
metabase: ["https://metabase.example.com"]
|
|
staging:
|
|
applications:
|
|
core-api:
|
|
source: { repo: acme/widget, branch: main }
|
|
build: { pack: nixpacks, base_directory: /apps/core }
|
|
port: 3000
|
|
healthcheck: /health
|
|
domains: ["http://api.staging.example.com"]
|
|
env_template: core-api.staging.env.template
|