Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions changelog.d/fixed/1074-helm-values-completeness.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
## Helm values completeness (ADR-1074)

- **`nameOverride` / `fullnameOverride` now accepted by `helm lint`**: both keys
were read by `_helpers.tpl` but absent from `values.yaml` and the strict
`additionalProperties: false` root schema, causing immediate validation failures.
- **StatefulSet MCP-state PVC size now configurable** via `statefulSet.statePVCSize`
(default: `1Gi`); previously hardcoded in the template.
- **Node metrics port now configurable** via `node.metricsPort` (default: `9090`);
the hardcoded value appeared in three template locations (node Deployment
containerPort, node-metrics Service port, NetworkPolicy allow rule) and is now
derived from a single values key.
- **`service.extraPorts` items schema added**: malformed port objects (missing `name`,
non-integer `port`, invalid `protocol`) now fail `helm lint` instead of being
silently accepted and rejected later by the Kubernetes apiserver.
1 change: 1 addition & 0 deletions deploy/helm/vmafx/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,5 @@ final UID and that container-scope seccompProfile is also set.
- [ADR-0969](../../../docs/adr/0969-helm-seccomp-default-plus-node-image-helper.md) — seccompProfile default + node image helper fix
- [ADR-1047](../../../docs/adr/1047-helm-schema-bug-fixes.md) — R9 schema correctness fixes
- [ADR-1058](../../../docs/adr/1058-helm-chart-security-hardening.md) — PDB, RBAC split, metrics NetworkPolicy, schema tightening
- [ADR-1074](../../../docs/adr/1074-helm-values-completeness.md) — nameOverride/fullnameOverride, statePVCSize, node.metricsPort, extraPorts items schema
- [ADR-1094](../../../docs/adr/1094-helm-rolling-update-correctness.md) — rolling-update strategy, probe fix, PDB default, grace period
2 changes: 1 addition & 1 deletion deploy/helm/vmafx/templates/networkpolicy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ spec:
{{- end }}
ports:
- protocol: TCP
port: 9090
port: {{ .Values.node.metricsPort | default 9090 }}
{{- end }}

# ----------------------------------------------------------------------------
Expand Down
7 changes: 7 additions & 0 deletions deploy/helm/vmafx/templates/node.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ spec:
- name: grpc
containerPort: {{ .Values.node.grpcPort | default 50052 }}
protocol: TCP
- name: metrics
containerPort: {{ .Values.node.metricsPort | default 9090 }}
protocol: TCP
env:
- name: VMAFX_CONTROLLER_ADDR
value: {{ include "vmafx.controllerAddr" . | quote }}
Expand Down Expand Up @@ -205,4 +208,8 @@ spec:
port: {{ .Values.node.grpcPort | default 50052 }}
targetPort: grpc
protocol: TCP
- name: metrics
port: {{ .Values.node.metricsPort | default 9090 }}
targetPort: metrics
protocol: TCP
{{- end }}
2 changes: 1 addition & 1 deletion deploy/helm/vmafx/templates/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ spec:
{{- end }}
resources:
requests:
storage: 1Gi
storage: {{ .Values.statefulSet.statePVCSize | default "1Gi" }}
---
# Headless Service required for StatefulSet DNS.
apiVersion: v1
Expand Down
39 changes: 38 additions & 1 deletion deploy/helm/vmafx/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
"additionalProperties": false,
"required": ["workload", "image", "gpu"],
"properties": {
"nameOverride": {
"type": "string",
"description": "Replaces only the chart-name component of resource names. Default: chart name."
},
"fullnameOverride": {
"type": "string",
"description": "Replaces the entire resource-name prefix. Default: <release>-<chartName>."
},
"operator": {
"type": "object",
"additionalProperties": false,
Expand Down Expand Up @@ -61,6 +69,11 @@
"podManagementPolicy": {
"type": "string",
"enum": ["OrderedReady", "Parallel"]
},
"statePVCSize": {
"type": "string",
"description": "Size of the per-replica PersistentVolumeClaim for MCP session state (/var/lib/vmafx). Standard Kubernetes quantity string (e.g. 1Gi, 500Mi).",
"pattern": "^[0-9]+(\\.[0-9]+)?(Ki|Mi|Gi|Ti|Pi|Ei|k|M|G|T|P|E|m)?$"
}
}
},
Expand All @@ -79,7 +92,25 @@
{ "type": "string" }
]
},
"extraPorts": { "type": "array" }
"extraPorts": {
"type": "array",
"items": {
"type": "object",
"required": ["name", "port"],
"properties": {
"name": { "type": "string" },
"port": { "type": "integer", "minimum": 1, "maximum": 65535 },
"targetPort": {
"oneOf": [
{ "type": "integer", "minimum": 1, "maximum": 65535 },
{ "type": "string" }
]
},
"protocol": { "type": "string", "enum": ["TCP", "UDP", "SCTP"] }
}
},
"description": "Additional named Service ports beyond the primary HTTP port."
}
}
},
"ingress": {
Expand Down Expand Up @@ -223,6 +254,12 @@
}
},
"controllerAddr": { "type": "string" },
"metricsPort": {
"type": "integer",
"minimum": 1,
"maximum": 65535,
"description": "Prometheus scrape port exposed by vmafx-node. Updates the Deployment containerPort, the node-metrics Service port, and the NetworkPolicy allow rule. Default: 9090."
},
"resources": { "$ref": "#/$defs/resourceSpec" },
"nodeSelector": { "type": "object" },
"tolerations": { "type": "array" },
Expand Down
19 changes: 19 additions & 0 deletions deploy/helm/vmafx/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@
# Operator guide: docs/development/operator.md
# =============================================================================

# ---------------------------------------------------------------------------
# Name overrides (standard Helm convention)
# ---------------------------------------------------------------------------
# nameOverride replaces only the chart name component of resource names.
# fullnameOverride replaces the entire resource name prefix.
# Both are optional; default behaviour is <release>-vmafx.
nameOverride: ""
fullnameOverride: ""

# ---------------------------------------------------------------------------
# Operator — vmafx-operator kubebuilder controller (ADR-0714)
# Disabled by default in Stage 1; enable after CRDs are installed.
Expand Down Expand Up @@ -96,6 +105,10 @@ statefulSet:
maxUnavailable: 1
partition: 0
podManagementPolicy: OrderedReady
# statePVCSize controls the PersistentVolumeClaim created by the StatefulSet
# volumeClaimTemplate for sticky session state (/var/lib/vmafx).
# Size this to fit the MCP server's session state on your storage class.
statePVCSize: 1Gi

# ---------------------------------------------------------------------------
# Pod termination grace period
Expand Down Expand Up @@ -455,6 +468,12 @@ node:
# Defaults to the in-cluster controller Service at <release>-controller:8080.
controllerAddr: ""

# metricsPort is the Prometheus scrape port exposed by vmafx-node.
# Changing this value updates the node Deployment containerPort, the
# node-metrics Service port, and the NetworkPolicy allow rule together.
# The default (9090) matches the vmafx-node binary default.
metricsPort: 9090

# resources overrides for the node pods.
# Falls back to .Values.resources when empty.
resources: {}
Expand Down
90 changes: 90 additions & 0 deletions docs/adr/1074-helm-values-completeness.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<!-- markdownlint-disable MD013 MD041 MD060 -->
# ADR-1074: Helm chart values completeness — missing knobs and schema gaps

- **Status**: Accepted
- **Date**: 2026-06-06
- **Deciders**: Lusoris
- **Tags**: `helm`, `k8s`, `bug`

## Context

A systematic audit of `deploy/helm/vmafx/values.yaml` against `values.schema.json`
and every template under `deploy/helm/vmafx/templates/` revealed four completeness
gaps that cause either silent misconfiguration or a hard `helm lint` failure when
users supply standard Helm override keys:

1. **`nameOverride` / `fullnameOverride` absent from both values.yaml and schema.**
The helpers in `_helpers.tpl` read `{{ .Values.nameOverride }}` and
`{{ .Values.fullnameOverride }}` (lines 10, 18–19, 21). Because the root schema
carries `"additionalProperties": false`, any user who sets `--set nameOverride=foo`
gets an immediate `helm lint` / `helm install` schema validation failure — the
canonical Helm convention is completely blocked.

2. **StatefulSet inline PVC size hardcoded to `1Gi`.**
`templates/statefulset.yaml` line 145 emits `storage: 1Gi` literally. The
StatefulSet `state` volume holds MCP server session state at `/var/lib/vmafx`;
operators with large or long-lived sessions cannot tune this without forking
the template.

3. **`node.metricsPort` absent from values — 9090 hardcoded in three places.**
`templates/node.yaml` lines 82 and 188 and `templates/networkpolicy.yaml`
line 255 all hardcode port 9090. Operators who need to run vmafx-node alongside
another Prometheus-scraped workload on the same port (a common cluster constraint)
have no override path. The NetworkPolicy allow-rule silently opens the wrong port
if the node binary is reconfigured externally.

4. **`service.extraPorts` items schema is untyped.**
The schema emits `"extraPorts": { "type": "array" }` with no `items` definition.
A malformed port object (missing `name`, non-integer `port`) passes `helm lint`
silently and only fails at `kubectl apply` time with an opaque apiserver error.

## Decision

Fix all four gaps:

1. Add `nameOverride: ""` and `fullnameOverride: ""` to values.yaml and to the root
`properties` block in values.schema.json (both `type: string`).
2. Add `statefulSet.statePVCSize: "1Gi"` to values.yaml; wire it into the
`volumeClaimTemplates[0].spec.resources.requests.storage` field in
`templates/statefulset.yaml`; add the key to the `statefulSet` properties block
in the schema with a Kubernetes-quantity `pattern` constraint.
3. Add `node.metricsPort: 9090` to values.yaml; replace all three hardcoded `9090`
occurrences in templates with `{{ .Values.node.metricsPort | default 9090 }}`;
add the key to the `node` properties block in the schema with
`minimum: 1, maximum: 65535`.
4. Replace the bare `"extraPorts": { "type": "array" }` in the `service` schema
with an `items` object that requires `name` and `port` and validates `protocol`
as an enum.

No template logic changes beyond the four targeted substitutions; no new required
fields are introduced; default values preserve existing rendered output byte-for-byte.

## Alternatives considered

| Option | Pros | Cons | Why not chosen |
|---|---|---|---|
| Leave nameOverride/fullnameOverride out of schema; set `additionalProperties: true` at root | No schema change needed | Loses all type-safety on misspelled top-level keys; ADR-1047 explicitly chose strict root schema | Not chosen; strict root `additionalProperties: false` is load-bearing |
| Expose operator ports (8081/8082) as values too | Consistent with node.metricsPort pattern | Operator port conflicts are rare and the operator args would need re-wiring beyond just the port | Deferred; operator port exposure is a separate concern with lower urgency |
| Validate extraPorts items with `unevaluatedProperties: false` | Stricter | JSON Schema 2020-12 `unevaluatedProperties` is not supported by helm's validator (uses draft-07 semantics internally) | Not chosen; `required` + `properties` is the portable subset |

## Consequences

- **Positive**: `helm lint` and `helm install --dry-run` now catch all four classes of
misconfiguration. Standard Helm `nameOverride` / `fullnameOverride` conventions work
without schema rejection. StatefulSet PVC size and node metrics port are documented
operator knobs.
- **Negative**: Users who supplied a custom `extraPorts` item without a `name` field
will now receive a schema validation error. This is intentional — a nameless port
is invalid Kubernetes YAML.
- **Neutral / follow-ups**: The `statePVCSize` default `"1Gi"` and `metricsPort`
default `9090` preserve current rendered output; no migration needed for existing
installs.

## References

- `deploy/helm/vmafx/values.yaml`, `deploy/helm/vmafx/values.schema.json`.
- `deploy/helm/vmafx/templates/statefulset.yaml` (line 145 — hardcoded `1Gi`).
- `deploy/helm/vmafx/templates/node.yaml` (lines 82, 188 — hardcoded `9090`).
- `deploy/helm/vmafx/templates/networkpolicy.yaml` (line 255 — hardcoded `9090`).
- `deploy/helm/vmafx/templates/_helpers.tpl` (lines 10, 18–21 — `nameOverride`/`fullnameOverride`).
- ADR-1047: preceding Helm schema correctness fixes (R9 batch).
1 change: 1 addition & 0 deletions docs/adr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,7 @@ ADRs may exist there for local session continuity, but the tracked
| [ADR-1071](1071-ms-ssim-hip-double-partials.md) | Port ADR-0990 double-precision partial accumulation fix to integer_ms_ssim_hip: accumulate l_partial/c_partial/s_partial in double on device and host; add enable_db and clip_db options. | Accepted | 2026-06-07 | hip, ms_ssim, precision, parity, fork-local |
| [ADR-1072](1072-prev-ref-batch-refcount-leak.md) | Fix PREV_REF refcount leak in threaded batch dispatch: call vmaf_picture_unref before memset on fex->prev_ref after extract() to balance the SWAP's bumped count; zero f->prev_ref to prevent UAF in unref block. Fixes test_picture_pool_basic deadlock, and corrects test fixture size (144→192) and motion debug flag for HIP parity tests. | Accepted | 2026-06-06 | core, threading, memory, picture-pool, bug, fork-local |
| [ADR-1073](1073-mcp-score-at-index-eagain-guard.md) | Fix vmaf_score_at_index EAGAIN-guard misapplication: the ADR-0154 guard `err != -EAGAIN` was applied to the model output score slot, suppressing vmaf_predict_score_at_index for all frames after the first in multi-frame sequences. Change `if (err && err != -EAGAIN)` to `if (err)`; input features are fully written after flush. Fixes vmaf_score_pooled returning -EAGAIN and MCP compute_vmaf JSON-RPC error on 10-bit multi-frame input. | Accepted | 2026-06-06 | mcp, scoring, correctness, core, fork-local |
| [ADR-1074](1074-helm-values-completeness.md) | Helm values completeness audit: add nameOverride/fullnameOverride to values.yaml and schema (blocked by additionalProperties:false); expose statefulSet.statePVCSize (was hardcoded 1Gi); expose node.metricsPort (was hardcoded 9090 in 3 templates); add extraPorts items schema with required name+port and protocol enum. | Accepted | 2026-06-06 | helm, k8s, bug |
| [ADR-1075](1075-mcp-http-score-body-validation.md) | Fix POST /v1/score chunked-body 413 propagation and null-body guard in the HTTP transport layer. | Accepted | 2026-06-07 | mcp, correctness, http, fork-local |
| [ADR-1077](1077-vmaftune-corner-cases-r14.md) | Fix vmaf-tune parse_versions miss for libaom/vvenc and compare --preset=None silent fail. | Accepted | 2026-06-07 | vmaf-tune, correctness, cli, fork-local |
| [ADR-1078](1078-ms-ssim-option-parity.md) | ms_ssim option parity: add `enable_db` + `clip_db` to HIP; add `enable_lcs` + `enable_db` + `clip_db` to SYCL; fix CUDA latent bug (appended raw `msssim` instead of dB-converted `score` when enable_db=true). | Accepted | 2026-06-06 | hip, sycl, cuda, ms_ssim, parity, correctness |
Expand Down
9 changes: 8 additions & 1 deletion docs/rebase-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,14 @@ no rebase impact: single-file change to
`motion_score_pipeline_16_neon`. No public API, no header, no test data,
no upstream-mirrored file is modified. Conflicts only if another branch
edits the same static helper region of that file.

## fix/helm-values-completeness-adr-1074 (ADR-1074, 2026-06-06)

no rebase impact: changes are confined to `deploy/helm/vmafx/values.yaml`,
`deploy/helm/vmafx/values.schema.json`, and three templates
(`templates/statefulset.yaml`, `templates/node.yaml`,
`templates/networkpolicy.yaml`). No C source, public header, upstream-mirrored
file, Python test, or golden-data assertion is touched. Conflict risk exists
only if another branch edits those same Helm files concurrently.
## fix/sanitizer-deselect-tests-and-quality-gates (2026-06-06)

no rebase impact: CI-only change to `.github/workflows/tests-and-quality-gates.yml`
Expand Down
Loading