* Add windmill-operator crate for Kubernetes CRD-based instance config Introduces a new `windmill-operator` crate that enables declarative management of Windmill instance configuration via a Kubernetes `WindmillInstance` CRD. The operator watches CRD resources and performs full declarative sync of global_settings and worker configs to the database, supporting GitOps workflows for instance-level configuration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add tests for windmill-operator CRD and db_sync - 9 unit tests for CRD serialization, deserialization, metadata, and status field behavior - 15 integration tests for db_sync using #[sqlx::test] with full declarative sync coverage: upsert, delete, protected keys, idempotency, worker config prefix handling, and end-to-end sync Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Replace untyped BTreeMap CRD fields with typed structs for schema validation GlobalSettings, SmtpSettings, IndexerSettings, and WorkerGroupConfig now have explicit typed fields with serde(flatten) catch-all for forward compatibility. The generated CRD YAML includes a full OpenAPI v3 schema that Kubernetes validates on kubectl apply. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Type opaque serde_json::Value CRD fields with real structs Replace most remaining serde_json::Value fields in WindmillInstance CRD with properly typed structs derived from the codebase: - oauths: BTreeMap<String, OAuthClient> - otel: OtelSettings - otel_tracing_proxy: OtelTracingProxySettings with ScriptLang enum - critical_error_channels: Vec<CriticalErrorChannel> (untagged enum) - critical_alerts_on_db_oversize: DbOversizeAlert - ducklake_settings: DucklakeSettings with nested catalog/storage types - custom_instance_pg_databases: CustomInstancePgDatabases - autoscaling (worker config): AutoscalingConfig with integration struct - custom_tags, default_tags_workspaces: Vec<String> - default_tags_per_workspace: bool Still opaque (serde_json::Value): object_store_cache_config (kube-core can't generate schemas for internally-tagged enums), secret_backend (EE-private), slack, teams (no clear struct definitions). Regenerated CRD YAML with full OpenAPI schema (352→703 lines). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Unify instance config types and add bulk GET/PUT API Move all typed settings (GlobalSettings, WorkerGroupConfig, etc.) from windmill-operator/crd.rs into windmill-common/instance_config.rs so both the API server and operator share a single source of truth. Add diff/apply logic (Merge mode for UI, Replace mode for operator) and InstanceConfig::from_db(). Add GET/PUT /settings/instance_config endpoints so the frontend loads all settings in 1 call instead of 42, and saves with a single bulk PUT. The backend handles the diff internally, running pre-write hooks for changed keys. Refactor windmill-operator/db_sync.rs to use the shared diff+apply functions and slim crd.rs down to the CRD wrapper with re-exports. Includes 32 unit tests and 30 integration tests covering serialization, diff logic, DB roundtrips, protected settings, and edge cases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add Form/YAML toggle to instance settings UI Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: show Form/YAML toggle regardless of hideTabs prop Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: replace toggle button group with simple YAML toggle Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: mask sensitive fields in YAML view with show/hide toggle Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: hide internal settings and mask sensitive fields in YAML view Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: hide jwt_secret and min_keep_alive_version from API and config exports Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * all * feat: add secretKeyRef support for sensitive fields in operator CRD Allow sensitive fields (license_key, hub_api_secret, scim_token, smtp_password, OAuthClient.secret, custom PG user_pwd) to reference Kubernetes Secrets via the standard secretKeyRef pattern instead of inlining values as plaintext YAML. The reconciler resolves all refs by reading K8s Secrets before syncing to the database. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * all * all * all * fix: merge main and update dev environment docs Resolve merge conflicts from origin/main, fix duplicate UV_INDEX_STRATEGY_SETTING import, and add Playwright MCP testing instructions to CLAUDE.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * all * fix: init tracing for CLI subcommands and deduplicate setting side-effects Initialize tracing subscriber before early-return CLI paths (sync-config, operator) so tracing calls are not silently dropped. Refactor set_global_setting_internal to call run_setting_pre_write_hook instead of duplicating the side-effect logic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add `wmill instance get-config` CLI command Dumps the current instance config (global settings + worker configs) as YAML. Supports --output-file to write to a file instead of stdout. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * all --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
91 lines
2.3 KiB
YAML
91 lines
2.3 KiB
YAML
version: "3.7"
|
|
|
|
# Example: Windmill with declarative instance configuration via sync-config.
|
|
#
|
|
# Usage:
|
|
# 1. Copy .env.example to .env and fill in your secrets
|
|
# 2. Edit windmill-config.yaml with your desired settings
|
|
# 3. docker compose up -d
|
|
#
|
|
# The windmill_config_sync service runs once at startup, applies the YAML
|
|
# config to the database, then exits. To re-apply after editing the config:
|
|
# docker compose run --rm windmill_config_sync
|
|
|
|
services:
|
|
db:
|
|
image: postgres:16
|
|
shm_size: 1g
|
|
restart: unless-stopped
|
|
volumes:
|
|
- db_data:/var/lib/postgresql/data
|
|
expose:
|
|
- 5432
|
|
environment:
|
|
POSTGRES_PASSWORD: changeme
|
|
POSTGRES_DB: windmill
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
# One-shot init container that syncs the YAML config to the database.
|
|
# Resolves envRef fields from container environment, then exits.
|
|
windmill_config_sync:
|
|
image: ${WM_IMAGE}
|
|
restart: "no"
|
|
command: ["windmill", "sync-config", "/config/windmill-config.yaml"]
|
|
environment:
|
|
- DATABASE_URL=${DATABASE_URL}
|
|
# Secrets are passed as env vars, referenced via envRef in the YAML
|
|
- WM_LICENSE_KEY=${WM_LICENSE_KEY}
|
|
- SMTP_PASSWORD=${SMTP_PASSWORD}
|
|
volumes:
|
|
- ./windmill-config.yaml:/config/windmill-config.yaml:ro
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
|
|
windmill_server:
|
|
image: ${WM_IMAGE}
|
|
restart: unless-stopped
|
|
expose:
|
|
- 8000
|
|
environment:
|
|
- DATABASE_URL=${DATABASE_URL}
|
|
- MODE=server
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
windmill_config_sync:
|
|
condition: service_completed_successfully
|
|
|
|
windmill_worker:
|
|
image: ${WM_IMAGE}
|
|
deploy:
|
|
replicas: 2
|
|
restart: unless-stopped
|
|
environment:
|
|
- DATABASE_URL=${DATABASE_URL}
|
|
- MODE=worker
|
|
- WORKER_GROUP=default
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
|
|
windmill_worker_native:
|
|
image: ${WM_IMAGE}
|
|
restart: unless-stopped
|
|
environment:
|
|
- DATABASE_URL=${DATABASE_URL}
|
|
- MODE=worker
|
|
- WORKER_GROUP=native
|
|
- NUM_WORKERS=8
|
|
- SLEEP_QUEUE=200
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
|
|
volumes:
|
|
db_data: null
|