[cozy-lib] Fix malformed ResourceQuota rendering for LoadBalancer services

This patch adds special handling for raw Kubernetes ResourceQuota fields,
such as `services.loadbalancers`, preventing them from being wrapped as
`limits.*` or `requests.*` keys by the flatten helper. This ensures that
LoadBalancer quotas render correctly in tenant specifications.

```release-note
[cozy-lib] Correctly render services.loadbalancers in ResourceQuota without limits.* or requests.* prefixes.
```

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
This commit is contained in:
IvanHunters
2025-11-19 16:01:52 +03:00
parent 1c9ae2bec5
commit 84133ef2d3

View File

@@ -40,49 +40,49 @@
{{- define "cozy-lib.resources.toFloat" -}}
{{- $value := . -}}
{{- $unit := 1.0 -}}
{{- if typeIs "string" . -}}
{{- $base2 := dict "Ki" 0x1p10 "Mi" 0x1p20 "Gi" 0x1p30 "Ti" 0x1p40 "Pi" 0x1p50 "Ei" 0x1p60 -}}
{{- $base10 := dict "m" 1e-3 "k" 1e3 "M" 1e6 "G" 1e9 "T" 1e12 "P" 1e15 "E" 1e18 -}}
{{- range $k, $v := merge $base2 $base10 -}}
{{- if hasSuffix $k $ -}}
{{- $value = trimSuffix $k $ -}}
{{- $unit = $v -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- mulf (float64 $value) $unit | toString -}}
{{- $value := . -}}
{{- $unit := 1.0 -}}
{{- if typeIs "string" . -}}
{{- $base2 := dict "Ki" 0x1p10 "Mi" 0x1p20 "Gi" 0x1p30 "Ti" 0x1p40 "Pi" 0x1p50 "Ei" 0x1p60 -}}
{{- $base10 := dict "m" 1e-3 "k" 1e3 "M" 1e6 "G" 1e9 "T" 1e12 "P" 1e15 "E" 1e18 -}}
{{- range $k, $v := merge $base2 $base10 -}}
{{- if hasSuffix $k $ -}}
{{- $value = trimSuffix $k $ -}}
{{- $unit = $v -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- mulf (float64 $value) $unit | toString -}}
{{- end -}}
{{- /*
A sanitized resource map is a dict with resource-name to resource-quantity.
All resources are returned with equal **requests** and **limits**, except for
**cpu**, whose *request* is reduced by the CPU-allocation ratio obtained from
`cozy-lib.resources.cpuAllocationRatio`.
A sanitized resource map is a dict with resource-name to resource-quantity.
All resources are returned with equal **requests** and **limits**, except for
**cpu**, whose *request* is reduced by the CPU-allocation ratio obtained from
`cozy-lib.resources.cpuAllocationRatio`.
The template now expects **one flat map** as input (no nested `requests:` /
`limits:` sections). Each value in that map is taken as the *limit* for the
corresponding resource. Usage example:
The template now expects **one flat map** as input (no nested `requests:` /
`limits:` sections). Each value in that map is taken as the *limit* for the
corresponding resource. Usage example:
{{ include "cozy-lib.resources.sanitize" list (.Values.resources $) }}
{{ include "cozy-lib.resources.sanitize" list (.Values.resources $) }}
Example input:
==============
cpu: "2"
memory: 256Mi
devices.com/nvidia: "1"
Example input:
==============
cpu: "2"
memory: 256Mi
devices.com/nvidia: "1"
Example output (cpuAllocationRatio = 10):
=========================================
limits:
cpu: "2"
memory: 256Mi
devices.com/nvidia: "1"
requests:
cpu: 200m # 2 / 10
memory: 256Mi # = limit
devices.com/nvidia: "1" # = limit
Example output (cpuAllocationRatio = 10):
=========================================
limits:
cpu: "2"
memory: 256Mi
devices.com/nvidia: "1"
requests:
cpu: 200m # 2 / 10
memory: 256Mi # = limit
devices.com/nvidia: "1" # = limit
*/}}
{{- define "cozy-lib.resources.sanitize" }}
{{- $cpuAllocationRatio := include "cozy-lib.resources.cpuAllocationRatio" . | float64 }}
@@ -118,36 +118,36 @@
{{- end }}
{{- /*
The defaultingSanitize helper takes a 3-element list as its argument:
{{- include "cozy-lib.resources.defaultingSanitize" list (
.Values.resourcesPreset
.Values.resources
$
) }}
and returns the same result as
{{- include "cozy-lib.resources.sanitize" list (
.Values.resources
$
) }}, however if cpu, memory, or ephemeral storage is not specified in
.Values.resources, it is filled from the resource presets.
The defaultingSanitize helper takes a 3-element list as its argument:
{{- include "cozy-lib.resources.defaultingSanitize" list (
.Values.resourcesPreset
.Values.resources
$
) }}
and returns the same result as
{{- include "cozy-lib.resources.sanitize" list (
.Values.resources
$
) }}, however if cpu, memory, or ephemeral storage is not specified in
.Values.resources, it is filled from the resource presets.
Example input (cpuAllocationRatio = 10):
========================================
resources:
cpu: "1"
resourcesPreset: "nano"
Example input (cpuAllocationRatio = 10):
========================================
resources:
cpu: "1"
resourcesPreset: "nano"
Example output:
===============
resources:
limits:
cpu: "1" # == user input
ephemeral-storage: 2Gi # == default ephemeral storage limit
memory: 128Mi # from "nano"
requests:
cpu: 100m # == 1 / 10
ephemeral-storage: 50Mi # == default ephemeral storage request
memory: 128Mi # memory request == limit
Example output:
===============
resources:
limits:
cpu: "1" # == user input
ephemeral-storage: 2Gi # == default ephemeral storage limit
memory: 128Mi # from "nano"
requests:
cpu: 100m # == 1 / 10
ephemeral-storage: 50Mi # == default ephemeral storage request
memory: 128Mi # memory request == limit
*/}}
{{- define "cozy-lib.resources.defaultingSanitize" }}
{{- $preset := index . 0 }}
@@ -159,10 +159,10 @@
{{- end }}
{{- /*
javaHeap takes a .Values.resources and returns Java heap settings based on
memory requests and limits. -Xmx is set to 75% of memory limits, -Xms is
set to the lesser of requests or 25% of limits. Accepts only sanitized
resource maps.
javaHeap takes a .Values.resources and returns Java heap settings based on
memory requests and limits. -Xmx is set to 75% of memory limits, -Xms is
set to the lesser of requests or 25% of limits. Accepts only sanitized
resource maps.
*/}}
{{- define "cozy-lib.resources.javaHeap" }}
{{- $memoryRequestInt := include "cozy-lib.resources.toFloat" .requests.memory | float64 | int64 }}
@@ -174,15 +174,46 @@
{{- end }}
{{- define "cozy-lib.resources.flatten" -}}
{{- $input := index . 0 -}}
{{- $ctx := index . 1 -}}
{{- /* List of keys that should NOT be placed under limits.* / requests.* */ -}}
{{- $rawQuotaKeys := list
"pods"
"services"
"services.loadbalancers"
"services.nodeports"
"services.clusterip"
"configmaps"
"secrets"
"persistentvolumeclaims"
"replicationcontrollers"
"resourcequotas"
-}}
{{- /* Detect if this is a ResourceQuota map */ -}}
{{- $isQuota := true -}}
{{- range $k, $v := $input }}
{{- if not (has $k $rawQuotaKeys) }}
{{- $isQuota = false -}}
{{- end }}
{{- end }}
{{- if $isQuota }}
{{- /* Output as plain resource quotas */ -}}
{{- $input | toYaml }}
{{- else }}
{{- /* Old behavior: flatten sanitized limits.* + requests.* */ -}}
{{- $out := dict -}}
{{- $res := include "cozy-lib.resources.sanitize" . | fromYaml -}}
{{- range $section, $values := $res }}
{{- range $k, $v := $values }}
{{- $key := printf "%s.%s" $section $k }}
{{- if ne $key "limits.storage" }}
{{- $_ := set $out $key $v }}
{{- end }}
{{- end }}
{{- range $k, $v := $values }}
{{- $key := printf "%s.%s" $section $k }}
{{- if ne $key "limits.storage" }}
{{- $_ := set $out $key $v }}
{{- end }}
{{- end }}
{{- end }}
{{- $out | toYaml }}
{{- end }}
{{- end }}