{{/* Returns Resources */}} {{/* Call this template: {{ include "tc.v1.common.lib.container.resources" (dict "rootCtx" $ "objectData" $objectData) }} rootCtx: The root context of the chart. objectData: The object data to be used to render the container. */}} {{- define "tc.v1.common.lib.container.resources" -}} {{- $rootCtx := .rootCtx -}} {{- $objectData := .objectData -}} {{- $resources := mustDeepCopy $rootCtx.Values.resources -}} {{- if $objectData.resources -}} {{- $resources = mustMergeOverwrite $resources $objectData.resources -}} {{- end -}} {{/* We use the objectData instead of $resources, as we only allow this flag on the container level */}} {{- if not (hasKey $objectData "resources") -}} {{- $_ := set $objectData "resources" dict -}} {{- end -}} {{- if not (hasKey $objectData.resources "excludeExtra") -}} {{- $_ := set $objectData.resources "excludeExtra" false -}} {{- end -}} {{- include "tc.v1.common.lib.container.resources.validation" (dict "resources" $resources) }} requests: cpu: {{ $resources.requests.cpu }} memory: {{ $resources.requests.memory }} {{- if $resources.limits }} limits: {{- with $resources.limits.cpu }} {{/* Passing 0, will not render it, meaning unlimited */}} cpu: {{ . }} {{- end -}} {{- with $resources.limits.memory }} {{/* Passing 0, will not render it, meaning unlimited */}} memory: {{ . }} {{- end -}} {{- if not $objectData.resources.excludeExtra -}} {{- range $k, $v := (omit $resources.limits "cpu" "memory") }} {{/* Omit cpu and memory, as they are handled above */}} {{- if or (not $v) (eq (toString $v) "0") -}} {{- continue -}} {{- end }} {{ $k }}: {{ $v }} {{- end -}} {{- end -}} {{- end -}} {{- end -}} {{- define "tc.v1.common.lib.resources.validation.data" -}} {{/* CPU: https://regex101.com/r/D4HouI/1 */}} {{/* MEM: https://regex101.com/r/NNPV2D/1 */}} {{- $regex := (dict "cpu" "^(0\\.[1-9]|[1-9][0-9]*)(\\.[0-9]|m?)$" "memory" "^[1-9][0-9]*([EPTGMK]i?|e[0-9]+)?$" ) -}} {{- $errorMsg := (dict "cpu" "(Plain Integer - eg. 1), (Float - eg. 0.5), (Milicpu - eg. 500m)" "memory" "(Suffixed with E/P/T/G/M/K - eg. 1G), (Suffixed with Ei/Pi/Ti/Gi/Mi/Ki - eg. 1Gi), (Plain Integer in bytes - eg. 1024), (Exponent - eg. 134e6)" ) -}} {{- $data := (dict "regex" $regex "errorMsg" $errorMsg) -}} {{- $data | toJson -}} {{- end -}} {{/* Validates resources to match a pattern */}} {{/* Call this template: {{ include "tc.v1.common.lib.container.resources.validation" (dict "resources" $resources) }} rootCtx: The root context of the chart. resources: The resources object */}} {{- define "tc.v1.common.lib.container.resources.validation" -}} {{- $resources := .resources -}} {{- $data := (include "tc.v1.common.lib.resources.validation.data" .) | fromJson -}} {{- $regex := $data.regex -}} {{- $errorMsg := $data.errorMsg -}} {{- $resourceTypes := (list "cpu" "memory") -}} {{- range $category := (list "requests") -}} {{/* We can also add "limits" here if we want to require them */}} {{- if not (get $resources $category) -}} {{- fail (printf "Container - Expected non-empty [resources.%s]" $category) -}} {{- end -}} {{- range $type := $resourceTypes -}} {{- if not (get (get $resources $category) $type) -}} {{- fail (printf "Container - Expected non-empty [resources.%s.%s]" $category $type) -}} {{- end -}} {{- end -}} {{- end -}} {{- range $key := (list "requests" "limits") -}} {{- $resourceCategory := (get $resources $key) -}} {{- if $resourceCategory -}} {{- range $type := $resourceTypes -}} {{- $resourceValue := (get $resourceCategory $type) -}} {{- if $resourceValue -}} {{/* Only try to match defined values */}} {{- if not (mustRegexMatch (get $regex $type) (toString $resourceValue)) -}} {{- fail (printf "Container - Expected [resources.%s.%s] to have one of the following formats [%s], but got [%s]" $key $type (get $errorMsg $type) $resourceValue) -}} {{- end -}} {{- end -}} {{- end -}} {{- end -}} {{- end -}} {{- end -}} {{- define "tc.v1.common.lib.pod.resources.hasGPU" -}} {{- $rootCtx := .rootCtx -}} {{- $objectData := .objectData -}} {{- $gpuType := .gpuType -}} {{- $types := (list "nvidia.com/gpu" "amd.com/gpu" "gpu.intel.com/i915") -}} {{- if $gpuType -}} {{- $types = (list $gpuType) -}} {{- end -}} {{- $gpu := false -}} {{- if and ($rootCtx.Values.resources) ($rootCtx.Values.resources.limits) -}} {{- range $t := $types -}} {{- if gt ((get $rootCtx.Values.resources.limits $t) | int) 0 -}} {{- $gpu = true -}} {{- break -}} {{- end -}} {{- end -}} {{- end -}} {{- if $objectData.podSpec -}} {{- range $k, $v := $objectData.podSpec.containers -}} {{- if not $v.enabled -}} {{- continue -}} {{- end -}} {{- range $t := $types -}} {{- if eq (include "tc.v1.common.lib.container.resources.hasGPU" (dict "rootCtx" $rootCtx "objectData" $v "gpuType" $t)) "true" -}} {{- $gpu = true -}} {{- break -}} {{- end -}} {{- end -}} {{- end -}} {{- end -}} {{- $gpu | toString -}} {{- end -}} {{- define "tc.v1.common.lib.container.resources.hasGPU" -}} {{- $rootCtx := .rootCtx -}} {{- $objectData := .objectData -}} {{- $gpuType := .gpuType -}} {{- $gpu := false -}} {{- if and ($objectData.resources) ($objectData.resources.limits) -}} {{- if gt ((get $objectData.resources.limits $gpuType) | int) 0 -}} {{- $gpu = true -}} {{- end -}} {{- end -}} {{- $gpu | toString -}} {{- end -}}