Addon initContainer materialization: per-addon image runs as initContainer + copies content into shared emptyDir mounted at /mnt/extra-addons

This commit is contained in:
Tower Deploy
2026-04-27 00:59:51 +03:00
parent 9dace864d8
commit bad53c4636
2 changed files with 72 additions and 0 deletions

View File

@@ -20,11 +20,44 @@ spec:
labels:
{{- include "instance.labels" . | nindent 8 }}
odoosky.io/role: odoo
annotations:
# Bumping this hash whenever the addons list changes forces
# Helm/ArgoCD to roll the Deployment, which re-runs the init
# containers and re-materializes the shared volume from the
# current image set. Without this, changing only `addons:` in
# values.yaml would leave the existing pod alone.
odoosky.io/addons-hash: {{ .Values.addons | toJson | sha256sum | trunc 16 }}
spec:
{{- if .Values.addons }}
# One initContainer per selected addon. Each addon image's
# ENTRYPOINT/CMD copies its bundled content into /target/<code>,
# which is the shared volume the Odoo container reads from.
# Init containers run in order, but each writes to its own
# subdir, so order doesn't matter.
initContainers:
{{- range $i, $a := .Values.addons }}
- name: addon-{{ $a.code | replace "_" "-" | lower }}
image: {{ $a.image }}:{{ $a.version }}
imagePullPolicy: IfNotPresent
volumeMounts:
- name: addons
mountPath: /target
{{- end }}
{{- end }}
containers:
- name: odoo
image: "{{ .Values.odoo.image }}:{{ .Values.odoo.tag }}"
imagePullPolicy: IfNotPresent
{{- if .Values.addons }}
# Pass --addons-path explicitly so the official Odoo image's
# entrypoint appends our extra-addons dir to the default
# addons_path. Args after the entrypoint that start with --
# are passed through to `odoo` directly. We list our path
# AFTER the default so built-in modules still take priority
# on name collisions.
args:
- "--addons-path=/usr/lib/python3/dist-packages/odoo/addons,{{ .Values.addonsMountPath }}"
{{- end }}
ports:
- name: http
containerPort: 8069
@@ -46,6 +79,11 @@ spec:
volumeMounts:
- name: filestore
mountPath: /var/lib/odoo
{{- if .Values.addons }}
- name: addons
mountPath: {{ .Values.addonsMountPath }}
readOnly: true
{{- end }}
resources:
{{- include "instance.resources" (dict "Values" .Values "role" "odoo") | nindent 12 }}
# /web/login is the most stable health endpoint across Odoo
@@ -67,3 +105,12 @@ spec:
- name: filestore
persistentVolumeClaim:
claimName: {{ include "instance.fullname" . }}-odoo
{{- if .Values.addons }}
# Shared scratch volume that init containers populate with
# addon content. emptyDir is fine — the source of truth is
# the registry's images; if the volume is wiped (pod
# recreate) the init containers re-materialize from the
# cached images.
- name: addons
emptyDir: {}
{{- end }}

View File

@@ -63,6 +63,31 @@ odoo:
# Filestore PVC size (Odoo's /var/lib/odoo).
filestoreSize: 10Gi
# 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
# addon's content into a shared volume; the Odoo container reads from
# /mnt/extra-addons/<code>.
#
# Tower owns this list — it commits new entries to the tenant overlay
# AFTER ensuring the corresponding image exists in the destination
# cluster's registry (spawning a build Job from Gitea source if not).
#
# Schema:
# addons:
# - code: odoosky_demo
# version: "18.0.1.0.0"
# source: platform # platform | tenant
# image: registry.odoosky-system.svc.cluster.local:5000/addons/odoosky_demo
#
# Empty list = no extra addons; only Odoo's built-in modules.
addons: []
# Path inside the Odoo container where addons are materialized.
# Odoo's addons_path includes this dir; one folder per addon code.
# Override only if you need a non-standard layout.
addonsMountPath: /mnt/extra-addons
postgres:
image: postgres
tag: "16-alpine"