Skip to content

feat(gateway): add TOML configuration file (RFC 0003)#1317

Open
TaylorMutch wants to merge 4 commits into
mainfrom
tmutch/gateway-config-impl
Open

feat(gateway): add TOML configuration file (RFC 0003)#1317
TaylorMutch wants to merge 4 commits into
mainfrom
tmutch/gateway-config-impl

Conversation

@TaylorMutch
Copy link
Copy Markdown
Collaborator

Summary

Implements RFC 0003: an opt-in --config / OPENSHELL_GATEWAY_CONFIG flag that loads a TOML file with gateway-wide settings and per-driver tables. Source precedence stays CLI > env > file > built-in default, so existing flags and OPENSHELL_* env vars are not affected when no file is supplied. Includes the matching Helm ConfigMap cutover.

Related Issue

N/A — implements RFC 0003.

Changes

  • Loader (crates/openshell-server/src/config_file.rs): TOML parser with deny_unknown_fields everywhere, version-1 enforcement, env-only rejection of database_url / ssh_handshake_secret, and a driver_table() that overlays inheritable [openshell.gateway] defaults onto each [openshell.drivers.<name>] table.
  • CLI (crates/openshell-server/src/cli.rs): new --config flag; merge_file_into_args() applies file values only when clap's ValueSource::DefaultValue indicates an arg was not supplied; new build_vm_config() / build_docker_config() consume merged driver tables.
  • Driver crates (kubernetes, docker, podman, vm): config structs derive Deserialize/Serialize with struct-level #[serde(default, deny_unknown_fields)]. SupervisorSideloadMethod gains Deserialize with kebab-case rename. Refreshed Default impls where needed.
  • run_server / build_compute_runtime thread Option<&ConfigFile> through; the ad-hoc env reads for Kubernetes/Podman supervisor settings now fold into the file-driven pipeline (env still wins).
  • Helm chart: new templates/gateway-config.yaml ConfigMap rendering gateway.toml from existing .Values.server.* / .Values.service.* / .Values.supervisor.* keys; StatefulSet mounts it at /etc/openshell/gateway.toml, passes --config, and drops the 18 migrated OPENSHELL_* env entries. Only OPENSHELL_SSH_HANDSHAKE_SECRET (Secret-backed) remains.
  • Docs: architecture/gateway.md documents source precedence and the inheritance allowlist; examples/gateway/gateway.example.toml ships a worked example.
  • Inheritance scope (Q4 high-overlap set, per-driver allowlist): default_image, supervisor_image, image_pull_policy, client_tls_secret_name, host_gateway_ip, enable_user_namespaces, guest_tls_ca/cert/key.
  • Follow-up commit removes ssh_handshake_skew_secs / ssh_handshake_secret references from examples and architecture ahead of their planned removal.

Testing

  • mise run pre-commit passes
  • Unit tests added/updated — 10 new tests in config_file.rs (parse, secret rejection, version, unknown field, inheritance merge, override) and 6 new tests in cli.rs (file value applies when defaulted, CLI overrides file, env overrides file, OIDC block, driver inheritance, driver override). Full mise run test passes.
  • E2E tests — test:e2e label applied; the sandbox-infra path should be exercised against the new --config startup mode.

Manual smoke:

  • helm lint . clean, helm template . renders gateway.toml with TLS, with TLS disabled, and with OIDC enabled.
  • TOML loader rejects database_url, ssh_handshake_secret, version = 2, and unknown fields with friendly errors.

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

Deferred (explicit follow-ups)

  • Helm unit tests for the new ConfigMap (separate effort).
  • "Raw ConfigMap contents" escape hatch in values.yaml.
  • --config-dir directory loader (RFC open question Prototype data access layer that can connect to outlook data #2).
  • RFC schema-gap fixes (Kubernetes ssh fields, Podman 6 missing fields, VM 9+ missing fields).

Introduces an opt-in --config / OPENSHELL_GATEWAY_CONFIG flag that loads a
TOML file with gateway-wide settings and per-driver tables. Source
precedence is CLI > env > file > built-in default, implemented via clap's
ValueSource so existing flags and env vars keep their priority.

Driver crates (kubernetes, docker, podman, vm) now derive Deserialize on
their config structs. SupervisorSideloadMethod gains Deserialize with
kebab-case rename. A per-driver inheritance allowlist on the loader side
overlays [openshell.gateway] shared defaults (default_image,
supervisor_image, image_pull_policy, guest_tls_*, ssh_handshake_skew_secs,
client_tls_secret_name, host_gateway_ip, enable_user_namespaces) onto
each [openshell.drivers.<name>] table before deserialization.

The Helm chart renders a new gateway-config ConfigMap and mounts it at
/etc/openshell/gateway.toml. The migrated OPENSHELL_* env entries are
dropped from the StatefulSet — only the Secret-backed
OPENSHELL_SSH_HANDSHAKE_SECRET remains. database_url stays on --db-url.

Adds examples/gateway/gateway.example.toml and updates architecture/gateway.md
with the source precedence and inheritance rules.
…from examples

Both fields are scheduled for removal. Remove the example values and the
env-only note so the gateway.toml example and the architecture doc stop
recommending settings that will not exist much longer.
@TaylorMutch TaylorMutch added the test:e2e Requires end-to-end coverage label May 12, 2026
@github-actions
Copy link
Copy Markdown

Label test:e2e applied for e324f7e. Open the existing run and click Re-run all jobs to execute with the label set. The E2E Gate check on this PR will flip green automatically once the run finishes.

Adds focused single-driver examples next to the comprehensive
gateway.example.toml: kubernetes, docker, podman, and microvm. Each one
demonstrates the realistic settings for that driver plus how shared
[openshell.gateway] defaults inherit into the driver table.

A new unit test (`checked_in_examples_parse`) loads every example through
the config_file loader so schema drift fails CI rather than silently
shipping a broken example.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:e2e Requires end-to-end coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant