From 91ddbb06efb5c5cfbfc795a94501cc578879819b Mon Sep 17 00:00:00 2001 From: Timofei Larkin Date: Fri, 21 Nov 2025 17:41:16 +0300 Subject: [PATCH] [cozy-lib] Improve flatten function This patch breaks introduces a helper function in cozy-lib to correctly handle special case resources when transforming a nested map of limits and requests to a flat map suitable for use in resourceQuotas. As a result, admins can now specify any types of resources as resource quotas for tenants, and they will be correctly transformed to the correct format for the underlying kubernetes ResourceQuota. In addition to the previously supported compute resources, such as CPU, memory, and custom resources, like GPUs, special quota strings such as "services.loadbalancers" are now correctly handled. ```release-note [cozy-lib,platform] Support resource quotas for special kubernetes quotas, such as service.loadbalncer count and others. ``` Signed-off-by: Timofei Larkin --- .../library/cozy-lib/templates/_resources.tpl | 102 +++++++----------- .../cozy-lib-tests/tests/quota_test.yaml | 24 ++++- .../cozy-lib-tests/tests/quota_values.yaml | 4 +- 3 files changed, 65 insertions(+), 65 deletions(-) diff --git a/packages/library/cozy-lib/templates/_resources.tpl b/packages/library/cozy-lib/templates/_resources.tpl index 3976f442..cb055ea1 100644 --- a/packages/library/cozy-lib/templates/_resources.tpl +++ b/packages/library/cozy-lib/templates/_resources.tpl @@ -174,68 +174,46 @@ {{- 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. +{{- $out := dict -}} +{{- $res := include "cozy-lib.resources.sanitize" . | fromYaml -}} +{{- range $section, $values := $res }} +{{- range $k, $v := $values }} +{{- with include "cozy-lib.resources.flattenResource" (list $section $k) }} +{{- $_ := set $out . $v }} +{{- end }} +{{- end }} +{{- end }} +{{- $out | toYaml }} +{{- end }} -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 -}} - -{{- $rawQuotaKeys := list -"pods" -"services" -"services.loadbalancers" -"services.nodeports" -"services.clusterip" -"configmaps" -"secrets" -"persistentvolumeclaims" -"replicationcontrollers" -"resourcequotas" +{{/* + This is a helper function that takes an argument like `list "limits" "services.loadbalancers"` + or `list "limits" "storage"` or `list "requests" "cpu"` and returns "services.loadbalancers", + "", and "requests.cpu", respectively, thus transforming them to an acceptable format for k8s + ResourceQuotas objects. +*/}} +{{- define "cozy-lib.resources.flattenResource" }} +{{- $rawQuotaKeys := list + "pods" + "services" + "services.loadbalancers" + "services.nodeports" + "services.clusterip" + "configmaps" + "secrets" + "persistentvolumeclaims" + "replicationcontrollers" + "resourcequotas" -}} - -{{- $computeKeys := list -"cpu" -"memory" -"ephemeral-storage" --}} - -{{- $out := dict -}} -{{- $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 }} -{{- if ne $key "limits.storage" }} -{{- $_ := set $out $key $v }} -{{- end }} -{{- end }} -{{- end }} -{{- end }} - -{{- range $k, $v := $quotaResources }} -{{- $_ := set $out $k $v }} -{{- end }} - -{{- $out | toYaml }} - +{{- $section := index . 0 }} +{{- $type := index . 1 }} +{{- $out := "" }} +{{- if and (eq $section "limits") (eq $type "storage") }} +{{- $out = "" }} +{{- else if and (eq $section "limits") (has $type $rawQuotaKeys) }} +{{- $out = $type }} +{{- else if not (has $type $rawQuotaKeys) }} +{{- $out = printf "%s.%s" $section $type }} +{{- end }} +{{- $out -}} {{- end }} diff --git a/packages/tests/cozy-lib-tests/tests/quota_test.yaml b/packages/tests/cozy-lib-tests/tests/quota_test.yaml index cbc6fcb7..0ba2260c 100644 --- a/packages/tests/cozy-lib-tests/tests/quota_test.yaml +++ b/packages/tests/cozy-lib-tests/tests/quota_test.yaml @@ -18,13 +18,33 @@ tests: asserts: - equal: path: spec.hard["limits.cpu"] - value: "2" + value: "20" - equal: path: spec.hard["requests.cpu"] - value: "0.2" + value: "2" + + - equal: + path: spec.hard["limits.foobar"] + value: "3" + + - equal: + path: spec.hard["requests.foobar"] + value: "3" - equal: path: spec.hard["services.loadbalancers"] value: "2" + - equal: + path: spec.hard["requests.storage"] + value: "5Gi" + + - notExists: + path: spec.hard["limits.storage"] + + - notExists: + path: spec.hard["limits.services.loadbalancers"] + + - notExists: + path: spec.hard["requests.services.loadbalancers"] diff --git a/packages/tests/cozy-lib-tests/tests/quota_values.yaml b/packages/tests/cozy-lib-tests/tests/quota_values.yaml index f2ed3a03..bcf6a21e 100644 --- a/packages/tests/cozy-lib-tests/tests/quota_values.yaml +++ b/packages/tests/cozy-lib-tests/tests/quota_values.yaml @@ -1,3 +1,5 @@ quota: services.loadbalancers: "2" - cpu: "2" + cpu: "20" + storage: "5Gi" + foobar: "3"