Skip to content

App Deployments (4a/N): shared compose parser + admin validation#218

Merged
v0l merged 1 commit into
masterfrom
feat/app-deployments-operator
Jul 24, 2026
Merged

App Deployments (4a/N): shared compose parser + admin validation#218
v0l merged 1 commit into
masterfrom
feat/app-deployments-operator

Conversation

@v0l

@v0l v0l commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Increment 4a of the managed App Deployments epic (see work/app-deployments.md). Extracts the app compose-ish YAML parser into a small shared crate so the API validates a compose with the exact same code the operator will use to render Kubernetes objects — no drift between what admins can save and what the operator can deploy.

New crate: lnvps_compose

Minimal deps (serde + serde_yaml + anyhow) so it's cheap for both the API and the operator binary to pull in.

  • Typed model: Compose (services / secrets / config, plain top-level keys, no x-*), Service, Port (expose/protocol), Volume, SecretDecl (generate), ConfigField, Backup.
  • parse + validate, referenced_vars, and resolve_env (${…} substitution across services — generated secrets, config values, ${HOSTNAME}, service refs — erroring on unknown references).

Validation enforced at parse time

  • ≥1 service; image required.
  • expose: ingress only on protocol: http ports (WS rides HTTP → wss).
  • Volume mount paths must be absolute, non-root, and contain no .. (directory-traversal guard).
  • depends_on must reference real services.
  • backup is exactly one of command | volume (and volume must be declared).

Shared with the API

lnvps_api_admin now runs lnvps_compose::Compose::parse on POST/PATCH /api/admin/v1/apps, so invalid/unsafe compose is rejected with a clear 400 at catalog-edit time (previously only a non-empty check).

Tests / docs

  • 9 unit tests in the crate (route96+MariaDB multi-service parse, defaults, var extraction, cross-service resolution, and every rejection path) + updated admin validator test.
  • API_CHANGELOG.md.

Next

4b) operator reconcile: lnvps_compose → Namespace + Deployment/StatefulSet + Service + Ingress + PVC + generated Secret + NetworkPolicy + ResourceQuota, status write-back, teardown; filtered by the operator's cluster_id.

Increment 4a of the App Deployments epic. Extract the app 'compose-ish'
YAML parser into a small shared crate so the API validates it with the
exact same code the operator will use to render Kubernetes objects.

- New lnvps_compose crate (serde + serde_yaml, no heavy deps): typed model
  (Compose/Service/Port/Volume/SecretDecl/ConfigField/Backup), parse +
  validate, referenced_vars, and resolve_env (${...} substitution across
  services, errors on unknown refs).
- Validation enforced at parse: at least one service, image required,
  expose: ingress only on http ports, absolute non-traversal volume mount
  paths, depends_on must reference real services, backup is exactly one of
  command|volume (volume must be declared).
- lnvps_api_admin now parses compose via lnvps_compose::Compose::parse on
  app create/update, rejecting invalid/unsafe compose with a clear 400
  (was: non-empty check only).
- 9 unit tests in the crate (route96+mariadb multi-service, defaults,
  var extraction, cross-service resolution, all rejection paths) + admin
  validator test updated.

Operator reconcile (compose -> k8s objects) is increment 4b.
Part of work/app-deployments.md.
@v0l
v0l merged commit d4bf795 into master Jul 24, 2026
8 checks passed
@v0l
v0l deleted the feat/app-deployments-operator branch July 24, 2026 15:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant