Describe the bug
cozy-lib.network.disableLoadBalancerNodePorts never returns a falsey result to its
callers, so allocateLoadBalancerNodePorts: false is emitted unconditionally — including
on RobotLB clusters, where the Hetzner load balancer requires node ports.
Two independent causes, either of which alone produces the same outcome.
Cause 1 — fromYaml on a scalar is always truthy.
Every caller uses the shape {{- if (include "cozy-lib.network.disableLoadBalancerNodePorts" $ | fromYaml) }}.
The helper renders the scalar true or false, and fromYaml on a scalar does not
produce a boolean — it produces a non-empty map carrying an Error key, which if treats
as true. Both branches are therefore taken.
Cause 2 — the helper reads a _cluster key that is no longer written.
packages/library/cozy-lib/templates/_network.tpl decides by
splitList "," (index $cozyConfig.data "bundle-enable"). Outside cozy-lib itself and
hack/migrate-to-version-1.0.sh (a v0.x migration), nothing in the tree writes
bundle-enable; packages/core/platform/templates/apps.yaml has no such key. So even with
cause 1 fixed the helper would fall through to its default of true on every v1.x cluster.
Environment
- Cozystack:
main (reproduced against the current tree)
- Helm: v4.0.4
- Provider: affects any cluster; the harmful case is Hetzner / RobotLB
To Reproduce
$ mkdir -p fytest/templates && cat > fytest/Chart.yaml <<'YAML'
apiVersion: v2
name: fytest
version: 0.1.0
YAML
$ cat > fytest/templates/probe.yaml <<'YAML'
{{- define "helper.true" }}{{ `true` }}{{ end }}
{{- define "helper.false" }}{{ `false` }}{{ end }}
result_true_branch: {{ if (include "helper.true" . | fromYaml) }}TAKEN{{ else }}not-taken{{ end }}
result_false_branch: {{ if (include "helper.false" . | fromYaml) }}TAKEN{{ else }}not-taken{{ end }}
raw_false: {{ include "helper.false" . | fromYaml | toJson }}
YAML
$ helm template fyt ./fytest
result_true_branch: TAKEN
result_false_branch: TAKEN
raw_false: {"Error":"error unmarshaling JSON: while decoding JSON: json: cannot unmarshal bool into Go value of type map[string]interface {}"}
Expected behaviour
allocateLoadBalancerNodePorts: false is emitted only where node ports are not required,
and omitted when robotlb is in use, which is what the helper's own comment describes:
"Detects whether the current load balancer class requires nodeports to function correctly."
Actual behaviour
It is emitted on every cluster. On RobotLB the resulting Service has no node port for the
Hetzner load balancer to target.
Affected charts
packages/apps/postgres/templates/external-svc.yaml
packages/apps/mongodb/templates/external-svc.yaml
packages/apps/redis/templates/service.yaml
packages/apps/valkey/templates/service.yaml
packages/apps/tcp-balancer/templates/service.yaml
packages/apps/vm-instance/templates/service.yaml
Notes
Two things worth deciding together with the fix:
- The call shape.
include … | fromYaml is the wrong coercion for a scalar; comparing the
rendered string (eq (include … .) "true") or having the helper emit a YAML map both
work, but the callers and the helper have to agree.
- The signal.
_cluster does carry live keys that could answer the same question on v1.x
— load-balancer-class and proxy-protocol are both written by
packages/core/platform/templates/apps.yaml.
Found while checking whether node ports stay open on Services that carry
loadBalancerSourceRanges; they do not on these six charts, but for this reason rather
than by design.
Describe the bug
cozy-lib.network.disableLoadBalancerNodePortsnever returns a falsey result to itscallers, so
allocateLoadBalancerNodePorts: falseis emitted unconditionally — includingon RobotLB clusters, where the Hetzner load balancer requires node ports.
Two independent causes, either of which alone produces the same outcome.
Cause 1 —
fromYamlon a scalar is always truthy.Every caller uses the shape
{{- if (include "cozy-lib.network.disableLoadBalancerNodePorts" $ | fromYaml) }}.The helper renders the scalar
trueorfalse, andfromYamlon a scalar does notproduce a boolean — it produces a non-empty map carrying an
Errorkey, whichiftreatsas true. Both branches are therefore taken.
Cause 2 — the helper reads a
_clusterkey that is no longer written.packages/library/cozy-lib/templates/_network.tpldecides bysplitList "," (index $cozyConfig.data "bundle-enable"). Outsidecozy-libitself andhack/migrate-to-version-1.0.sh(a v0.x migration), nothing in the tree writesbundle-enable;packages/core/platform/templates/apps.yamlhas no such key. So even withcause 1 fixed the helper would fall through to its default of
trueon every v1.x cluster.Environment
main(reproduced against the current tree)To Reproduce
Expected behaviour
allocateLoadBalancerNodePorts: falseis emitted only where node ports are not required,and omitted when
robotlbis in use, which is what the helper's own comment describes:"Detects whether the current load balancer class requires nodeports to function correctly."
Actual behaviour
It is emitted on every cluster. On RobotLB the resulting Service has no node port for the
Hetzner load balancer to target.
Affected charts
Notes
Two things worth deciding together with the fix:
include … | fromYamlis the wrong coercion for a scalar; comparing therendered string (
eq (include … .) "true") or having the helper emit a YAML map bothwork, but the callers and the helper have to agree.
_clusterdoes carry live keys that could answer the same question on v1.x—
load-balancer-classandproxy-protocolare both written bypackages/core/platform/templates/apps.yaml.Found while checking whether node ports stay open on Services that carry
loadBalancerSourceRanges; they do not on these six charts, but for this reason ratherthan by design.