From 84133ef2d306cb53e76a016df92a27979dd8eb96 Mon Sep 17 00:00:00 2001 From: IvanHunters Date: Wed, 19 Nov 2025 16:01:52 +0300 Subject: [PATCH 1/5] [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 --- .../library/cozy-lib/templates/_resources.tpl | 179 ++++++++++-------- 1 file changed, 105 insertions(+), 74 deletions(-) diff --git a/packages/library/cozy-lib/templates/_resources.tpl b/packages/library/cozy-lib/templates/_resources.tpl index f402ee02..fcaac29a 100644 --- a/packages/library/cozy-lib/templates/_resources.tpl +++ b/packages/library/cozy-lib/templates/_resources.tpl @@ -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 }} From c5b117714915ac5d65460f9493f62b38438e36cd Mon Sep 17 00:00:00 2001 From: IvanHunters Date: Wed, 19 Nov 2025 16:08:30 +0300 Subject: [PATCH 2/5] fix flatten with rabbit recomendation Signed-off-by: IvanHunters --- .../library/cozy-lib/templates/_resources.tpl | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/library/cozy-lib/templates/_resources.tpl b/packages/library/cozy-lib/templates/_resources.tpl index fcaac29a..82fd2391 100644 --- a/packages/library/cozy-lib/templates/_resources.tpl +++ b/packages/library/cozy-lib/templates/_resources.tpl @@ -177,7 +177,6 @@ resource maps. {{- $input := index . 0 -}} {{- $ctx := index . 1 -}} -{{- /* List of keys that should NOT be placed under limits.* / requests.* */ -}} {{- $rawQuotaKeys := list "pods" "services" @@ -191,19 +190,26 @@ resource maps. "resourcequotas" -}} -{{- /* Detect if this is a ResourceQuota map */ -}} -{{- $isQuota := true -}} +{{- $computeKeys := list +"cpu" +"memory" +"ephemeral-storage" +-}} + +{{- $hasCompute := false -}} {{- range $k, $v := $input }} -{{- if not (has $k $rawQuotaKeys) }} -{{- $isQuota = false -}} +{{- if or (has $k $computeKeys) +(hasPrefix "limits." $k) +(hasPrefix "requests." $k) }} +{{- $hasCompute = true -}} {{- end }} {{- end }} +{{- $isQuota := not $hasCompute -}} + {{- 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 }} @@ -216,4 +222,5 @@ resource maps. {{- end }} {{- $out | toYaml }} {{- end }} + {{- end }} From 23e6cf735afae56f97f28bc1251a50a36211d737 Mon Sep 17 00:00:00 2001 From: IvanHunters Date: Wed, 19 Nov 2025 16:23:51 +0300 Subject: [PATCH 3/5] fix flatten with rabbit recomendation Signed-off-by: IvanHunters --- packages/library/cozy-lib/templates/_resources.tpl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/library/cozy-lib/templates/_resources.tpl b/packages/library/cozy-lib/templates/_resources.tpl index 82fd2391..daeee1a5 100644 --- a/packages/library/cozy-lib/templates/_resources.tpl +++ b/packages/library/cozy-lib/templates/_resources.tpl @@ -174,6 +174,16 @@ resource maps. {{- end }} {{- define "cozy-lib.resources.flatten" -}} +{{- /* +This helper either outputs raw ResourceQuota fields (e.g., services.loadbalancers) +as-is, or flattens sanitized resource maps into limits.* / requests.* keys. + +If ALL keys in the input are recognized quota keys (pods, services.*, etc.), +the input is output directly as YAML. Otherwise, the input is treated as a +resource map and processed through sanitize + flatten. + +Do not mix quota keys and resource keys in a single call. +*/ -}} {{- $input := index . 0 -}} {{- $ctx := index . 1 -}} From 492aef93f55ae32bc8eab862a07e509094d5d69b Mon Sep 17 00:00:00 2001 From: IvanHunters Date: Wed, 19 Nov 2025 16:25:44 +0300 Subject: [PATCH 4/5] fix flatten with rabbit recomendation Signed-off-by: IvanHunters --- .../library/cozy-lib/templates/_resources.tpl | 136 +++++++++--------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/packages/library/cozy-lib/templates/_resources.tpl b/packages/library/cozy-lib/templates/_resources.tpl index daeee1a5..7ea15c97 100644 --- a/packages/library/cozy-lib/templates/_resources.tpl +++ b/packages/library/cozy-lib/templates/_resources.tpl @@ -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 @@ devices.com/nvidia: "1" # = limit {{- 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 @@ memory: 128Mi # memory request == limit {{- 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 }} From a070573af939ec61777add0e26a76dc5428d9013 Mon Sep 17 00:00:00 2001 From: IvanHunters Date: Thu, 20 Nov 2025 12:01:49 +0300 Subject: [PATCH 5/5] fix flatten for tests Signed-off-by: IvanHunters --- .../library/cozy-lib/templates/_resources.tpl | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/packages/library/cozy-lib/templates/_resources.tpl b/packages/library/cozy-lib/templates/_resources.tpl index 7ea15c97..3976f442 100644 --- a/packages/library/cozy-lib/templates/_resources.tpl +++ b/packages/library/cozy-lib/templates/_resources.tpl @@ -206,22 +206,22 @@ Do not mix quota keys and resource keys in a single call. "ephemeral-storage" -}} -{{- $hasCompute := false -}} -{{- range $k, $v := $input }} -{{- if or (has $k $computeKeys) -(hasPrefix "limits." $k) -(hasPrefix "requests." $k) }} -{{- $hasCompute = true -}} -{{- end }} -{{- end }} - -{{- $isQuota := not $hasCompute -}} - -{{- if $isQuota }} -{{- $input | toYaml }} -{{- else }} {{- $out := dict -}} -{{- $res := include "cozy-lib.resources.sanitize" . | fromYaml -}} +{{- $computeResources := dict -}} +{{- $quotaResources := dict -}} + +{{- range $k, $v := $input }} +{{- if or (has $k $computeKeys) (hasPrefix "limits." $k) (hasPrefix "requests." $k) }} +{{- $_ := set $computeResources $k $v }} +{{- else if has $k $rawQuotaKeys }} +{{- $_ := set $quotaResources $k $v }} +{{- else }} +{{- $_ := set $computeResources $k $v }} +{{- end }} +{{- end }} + +{{- if $computeResources }} +{{- $res := include "cozy-lib.resources.sanitize" (list $computeResources (index . 1)) | fromYaml -}} {{- range $section, $values := $res }} {{- range $k, $v := $values }} {{- $key := printf "%s.%s" $section $k }} @@ -230,7 +230,12 @@ Do not mix quota keys and resource keys in a single call. {{- end }} {{- end }} {{- end }} -{{- $out | toYaml }} {{- end }} +{{- range $k, $v := $quotaResources }} +{{- $_ := set $out $k $v }} +{{- end }} + +{{- $out | toYaml }} + {{- end }}