Skip to content

fix(builder): keep explicitly-set false/0 values when merging CR templates - #253

Open
AndreyZa wants to merge 1 commit into
SlinkyProject:mainfrom
AndreyZa:fix/keep-explicit-zero-values
Open

fix(builder): keep explicitly-set false/0 values when merging CR templates#253
AndreyZa wants to merge 1 commit into
SlinkyProject:mainfrom
AndreyZa:fix/keep-explicit-zero-values

Conversation

@AndreyZa

@AndreyZa AndreyZa commented Sep 2, 2026

Copy link
Copy Markdown

Summary

removeEmpty() pruned every JSON value equal to the zero value of its Go type, so an explicitly-set false or 0 in a CR pod/container template was dropped from the strategic merge patch and never reached the built workload.

The fields at risk are *bool/*int64 with omitempty in the Kubernetes API types: they are marshalled only when the user set them, so pruning them discarded configuration rather than noise. Nulls, empty strings, empty objects and empty lists are still pruned, so unset non-pointer fields keep their previous behaviour.

Concretely, spec.login.securityContext.allowPrivilegeEscalation: false on a LoginSet is stored in the CR but absent from the Deployment, so the login container runs with NoNewPrivs: 0 and a LoginSet cannot satisfy the restricted Pod Security Standard. The chart's own default (loginsetDefaults.login.securityContext.privileged: false) is lost the same way, as are readOnlyRootFilesystem: false, runAsUser: 0 and terminationGracePeriodSeconds: 0. The helper is shared by BuildContainer and BuildPodTemplate, so every builder is affected.

Closes #252.

Checklist

  • I have read the
    CONTRIBUTING.md
    and the
    Code of Conduct.
  • New or existing tests cover these changes (where applicable).
  • Documentation is updated if user-visible behavior changes. (No documentation change: the fix makes the builders honour values the CRD already documents.)

Breaking Changes

None intended. Values that users set explicitly to false/0 now reach the workload; anything left unset is pruned exactly as before. A deployment that relied on an explicit false being silently ignored would change, but that would be the bug itself.

Testing Notes

  • internal/utils/structutils/kube_test.go gains a subtest that merges a patch carrying container-level privileged: false / allowPrivilegeEscalation: false and pod-level automountServiceAccountToken: false, terminationGracePeriodSeconds: 0, securityContext.runAsUser: 0. It fails on main and passes with this change. make test is green (50 packages).

  • Verified on a cluster (Kubernetes v1.35.8 / k0s, charts slurm-operator-1.2.1 / slurm-1.2.1, one LoginSet declaring all five fields; only the operator image swapped):

    Before (ghcr.io/slinkyproject/slurm-operator:1.2.1):

    container.securityContext: {"capabilities":{"add":[...],"drop":["ALL"]}}
    pod.terminationGracePeriodSeconds: 30
    pod.securityContext: {}
    

    After (this branch):

    container.securityContext: {"allowPrivilegeEscalation":false,"capabilities":{"add":[...],"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":false}
    pod.terminationGracePeriodSeconds: 0
    pod.securityContext: {"runAsUser":0}
    

    and in the login pod: NoNewPrivs: 1.

Additional Context

Found while trying to run a LoginSet under the restricted Pod Security Standard.

…lates

removeEmpty() pruned every JSON value equal to the zero value of its Go
type, so an explicitly-set `false` or `0` in a CR pod/container template
was dropped from the strategic merge patch and never reached the built
workload.

The most visible effect: `spec.login.securityContext.allowPrivilegeEscalation:
false` on a LoginSet is stored in the CR but absent from the Deployment,
so the login container runs with NoNewPrivs=0 and cannot satisfy the
restricted Pod Security Standard. `privileged: false`, `runAsUser: 0`,
`automountServiceAccountToken: false` and `terminationGracePeriodSeconds: 0`
are lost the same way, in every builder that merges a user template.

These fields are pointers with omitempty in the Kubernetes API types, so
they are only present in the marshalled patch when the user set them
explicitly; pruning them discarded configuration rather than noise.
Nulls, empty strings, empty objects and empty lists are still pruned, so
unset non-pointer fields keep their previous behaviour.

Add a regression test covering both container- and pod-level zero values.

Signed-off-by: Andrey Zavilgelsky <zamazo38@gmail.com>
Changelog: Fixed - explicitly-set false/0 values in CR templates (e.g. allowPrivilegeEscalation: false) are no longer dropped from the built workload
@vivian-hafener

Copy link
Copy Markdown
Contributor

Please update this PR to use the provided Pull Request Template: https://github.com/SlinkyProject/slurm-operator/blob/main/.github/pull_request_template.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: explicitly-set false/0 values in CR templates are dropped when building the workload (allowPrivilegeEscalation, privileged, runAsUser: 0, …)

2 participants