From ec63eca5ba514be1205cf4d87313f8875b2998c8 Mon Sep 17 00:00:00 2001 From: OdooSky v3 Date: Wed, 13 May 2026 21:42:33 +0200 Subject: [PATCH] =?UTF-8?q?feat(chart):=20expose=20Odoo=20runtime=20knobs?= =?UTF-8?q?=20(B-1)=20=E2=80=94=20version=200.1.11?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adds odoo.{workers,limitTime*,limitMemory*,maxCronThreads,serverWideModules,dbFilter,extraArgs} knobs - New instance.odooArgs helper renders flags only when set - Empty odoo block byte-identical to previous chart output --- Chart.yaml | 2 +- templates/_helpers.tpl | 53 ++++++++++++++++++++++++++++++++++ templates/odoo-deployment.yaml | 26 ++++++----------- values.yaml | 21 ++++++++++++++ 4 files changed, 84 insertions(+), 18 deletions(-) diff --git a/Chart.yaml b/Chart.yaml index 5fb27a0..c45999a 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -5,7 +5,7 @@ description: | Variation between instances is expressed via values.yaml only. No chart variants. No string-templating in Tower. type: application -version: 0.1.10 +version: 0.1.11 appVersion: "1.0" keywords: - odoo diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index 62e5afd..8a38e1e 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -69,6 +69,59 @@ shouldn't blow up the rendered chart). {{- toYaml (index $cfg .role) -}} {{- end -}} +{{/* +Args list for the Odoo container. + +Hard baseline (-d / --db-filter / --addons-path / --proxy-mode) +encodes invariants the v3 deployment relies on (Traefik termination, +single-DB mode); operators cannot drop these. + +Runtime knobs come from .Values.odoo.* and only render when set — +null leaves Odoo's internal default in place. Overlays without the +extended odoo block render byte-identical to the pre-runtime-knob +chart, so B-1 doesn't disturb any live instance. + +Schema: see values.yaml `odoo:` block + docs/PLAN_INSTANCE_CONFIG_AND_DBTOOLS.md. +*/}} +{{- define "instance.odooArgs" -}} +- "-d" +- {{ .Values.instance.code | quote }} +{{- if .Values.odoo.dbFilter }} +- {{ printf "--db-filter=%s" .Values.odoo.dbFilter | quote }} +{{- else }} +- {{ printf "--db-filter=^%s$" .Values.instance.code | quote }} +{{- end }} +- {{ printf "--addons-path=/usr/lib/python3/dist-packages/odoo/addons,%s" .Values.addonsMountPath | quote }} +- "--proxy-mode" +{{- with .Values.odoo.workers }} +- {{ printf "--workers=%d" (int64 .) | quote }} +{{- end }} +{{- with .Values.odoo.maxCronThreads }} +- {{ printf "--max-cron-threads=%d" (int64 .) | quote }} +{{- end }} +{{- with .Values.odoo.limitTimeCpu }} +- {{ printf "--limit-time-cpu=%d" (int64 .) | quote }} +{{- end }} +{{- with .Values.odoo.limitTimeReal }} +- {{ printf "--limit-time-real=%d" (int64 .) | quote }} +{{- end }} +{{- with .Values.odoo.limitTimeRealCron }} +- {{ printf "--limit-time-real-cron=%d" (int64 .) | quote }} +{{- end }} +{{- with .Values.odoo.limitMemorySoft }} +- {{ printf "--limit-memory-soft=%d" (int64 .) | quote }} +{{- end }} +{{- with .Values.odoo.limitMemoryHard }} +- {{ printf "--limit-memory-hard=%d" (int64 .) | quote }} +{{- end }} +{{- with .Values.odoo.serverWideModules }} +- {{ printf "--load=%s" (join "," .) | quote }} +{{- end }} +{{- range .Values.odoo.extraArgs }} +- {{ . | quote }} +{{- end }} +{{- end -}} + {{/* Storage size for a given layer (`filestore` | `database`). Resolution order, most-specific first: diff --git a/templates/odoo-deployment.yaml b/templates/odoo-deployment.yaml index a76898a..9028d89 100644 --- a/templates/odoo-deployment.yaml +++ b/templates/odoo-deployment.yaml @@ -401,24 +401,16 @@ spec: # for the SaaS UX we want one instance == one DB and never # show the manager. db-init has already created and bootstrapped # this DB, so Odoo opens it cleanly. + # Args list assembled by instance.odooArgs helper: + # * hard baseline (-d, --db-filter, --addons-path, --proxy-mode) + # encodes v3 deployment invariants (Traefik termination, + # single-DB mode) — operators cannot drop these. + # * runtime knobs from .Values.odoo.* (workers, limit_time_*, + # server-wide modules, etc.) render only when set; null + # keeps Odoo's internal defaults. + # See templates/_helpers.tpl and values.yaml `odoo:` block. args: - - "-d" - - "{{ .Values.instance.code }}" - - "--db-filter=^{{ .Values.instance.code }}$" - # addons-path always includes the shared addons mount — - # the platform-shim addon lives there even when the - # tenant has no extra addons. See platform-shim - # initContainer. - - "--addons-path=/usr/lib/python3/dist-packages/odoo/addons,{{ .Values.addonsMountPath }}" - # proxy-mode is mandatory in Tower's architecture — every - # Odoo runs behind Traefik (per-instance IngressRoute → TLS - # termination at the cluster Traefik). Without --proxy-mode - # Odoo ignores X-Forwarded-Proto and generates http:// URLs - # for assets / images / redirects, which the browser blocks - # as Mixed Content on the https:// page. Diagnosed during - # the havari-16 ARM migrate (2026-05-13). Safe default for - # every chart consumer. - - "--proxy-mode" + {{- include "instance.odooArgs" . | nindent 12 }} ports: - name: http containerPort: 8069 diff --git a/values.yaml b/values.yaml index 97e2c25..8f7e648 100644 --- a/values.yaml +++ b/values.yaml @@ -136,6 +136,27 @@ odoo: # Filestore PVC size (Odoo's /var/lib/odoo). filestoreSize: 10Gi + # Runtime knobs — null leaves Odoo's internal default in place + # (chart emits no flag for that knob). All keys optional. Overlays + # without this block render the exact args list the chart emitted + # before runtime-knob support landed. + # + # Operator UX surfaces these on the instance Settings tab. + # Basic group (workers / limit* / maxCronThreads) is editable by + # tenant operators. Advanced (serverWideModules / dbFilter / + # extraArgs) is super-admin only. See + # docs/PLAN_INSTANCE_CONFIG_AND_DBTOOLS.md. + workers: null + maxCronThreads: null + limitTimeCpu: null # seconds + limitTimeReal: null # seconds + limitTimeRealCron: null # seconds + limitMemorySoft: null # bytes + limitMemoryHard: null # bytes + serverWideModules: null # list[string], e.g. ["web", "queue_job"] + dbFilter: null # regex; null → ^$ + extraArgs: [] # list[string], escape hatch + # Addons selected for this instance. Each entry is a tagged image in # the cluster-local registry (deployed by cluster-platform-v3 chart). # The chart renders one initContainer per entry that copies the