diff --git a/charts/library/common-test/tests/pod/affinity.yaml b/charts/library/common-test/tests/pod/affinity.yaml new file mode 100644 index 00000000000..22154ff3112 --- /dev/null +++ b/charts/library/common-test/tests/pod/affinity.yaml @@ -0,0 +1,793 @@ +suite: pod affinity test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should pass with configured affinity and default + set: + persistence: + test-pvc-1: + enabled: true + type: pvc + mountPath: /test1 + test-pvc-2: + enabled: true + type: pvc + mountPath: /test2 + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 0 + podAffinityTerm: + topologyKey: kubernetes.io/zone + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - my-zone-app + - my-zone-app-2 + asserts: + - documentIndex: &deploymentDoc 0 + isKind: + of: Deployment + - documentIndex: *deploymentDoc + isSubset: + path: spec.template.metadata.labels + content: + truecharts.org/pvc: test-pvc-1_test-pvc-2 + - documentIndex: *deploymentDoc + equal: + path: spec.template.spec.affinity + value: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 0 + podAffinityTerm: + topologyKey: kubernetes.io/zone + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - my-zone-app + - my-zone-app-2 + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: truecharts.org/pvc + operator: In + values: + - test-pvc-1_test-pvc-2 + + - it: should pass with configured affinity + set: + podOptions: + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + matchLabelKeys: + - app + - tier + mismatchLabelKeys: + - app + - tier + namespaces: + - default + - kube-system + namespaceSelector: + matchExpressions: + - key: app + operator: In + values: + - my-app + - my-app-2 + - key: tier + operator: In + values: + - frontend + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + matchLabelKeys: + - app + - tier + mismatchLabelKeys: + - app + - tier + namespaces: + - default + - kube-system + namespaceSelector: + matchExpressions: + - key: app + operator: In + values: + - my-app + - my-app-2 + - key: tier + operator: In + values: + - frontend + - weight: 0 + podAffinityTerm: + topologyKey: kubernetes.io/zone + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - my-zone-app + - my-zone-app-2 + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - my-app + - my-app-2 + - key: tier + operator: In + values: + - backend + - topologyKey: kubernetes.io/zone + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - my-zone-app + - my-zone-app-2 + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - documentIndex: &deploymentDoc 0 + isKind: + of: Deployment + - documentIndex: *deploymentDoc + equal: + path: spec.template.spec.affinity + value: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + matchLabelKeys: + - app + - tier + mismatchLabelKeys: + - app + - tier + namespaces: + - default + - kube-system + namespaceSelector: + matchExpressions: + - key: app + operator: In + values: + - my-app + - my-app-2 + - key: tier + operator: In + values: + - frontend + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + matchLabelKeys: + - app + - tier + mismatchLabelKeys: + - app + - tier + namespaces: + - default + - kube-system + namespaceSelector: + matchExpressions: + - key: app + operator: In + values: + - my-app + - my-app-2 + - key: tier + operator: In + values: + - frontend + - weight: 0 + podAffinityTerm: + topologyKey: kubernetes.io/zone + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - my-zone-app + - my-zone-app-2 + + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - my-app + - my-app-2 + - key: tier + operator: In + values: + - backend + + - topologyKey: kubernetes.io/zone + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - my-zone-app + - my-zone-app-2 + # Failures + - it: should fail without at least one key under podAffinity + set: + podOptions: + affinity: + podAffinity: + onlyInvalidKey: some-value + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected at least one of requiredDuringSchedulingIgnoredDuringExecution or preferredDuringSchedulingIgnoredDuringExecution in [affinity.podAffinity] + - it: should fail without at least one key under podAntiAffinity + set: + podOptions: + affinity: + podAntiAffinity: + onlyInvalidKey: some-value + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected at least one of requiredDuringSchedulingIgnoredDuringExecution or preferredDuringSchedulingIgnoredDuringExecution in [affinity.podAntiAffinity] + + - it: should fail with invalid requiredDuringSchedulingIgnoredDuringExecution key in podAffinity + set: + podOptions: + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + some-data: {} + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution] to be a slice but got [map] + + - it: should fail with invalid requiredDuringSchedulingIgnoredDuringExecution key in podAntiAffinity + set: + podOptions: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + some-data: {} + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution] to be a slice but got [map] + + - it: should fail with invalid preferredDuringSchedulingIgnoredDuringExecution key in podAffinity + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + some-data: {} + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution] to be a slice but got [map] + + - it: should fail with invalid preferredDuringSchedulingIgnoredDuringExecution key in podAntiAffinity + set: + podOptions: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + some-data: {} + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution] to be a slice but got [map] + + - it: should fail with invalid podAffinityTerm weight in podAffinity + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: "90" + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.weight] to be a number but got [string] + + - it: should fail with invalid podAffinityTerm weight in podAffinity + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 101 + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.weight] to be between 0 and 100 but got [101] + + - it: should fail with invalid podAffinityTerm weight in podAntiAffinity + set: + podOptions: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: "90" + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.weight] to be a number but got [string] + + - it: should fail with invalid podAffinityTerm weight in podAntiAffinity + set: + podOptions: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 101 + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.weight] to be between 0 and 100 but got [101] + + - it: should fail with missing podAffinityTerm in podAffinity + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm] to be defined + + - it: should fail with missing podAffinityTerm in podAntiAffinity + set: + podOptions: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm] to be defined + + - it: should fail with missing topology key in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: {} + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.topologyKey] to be a string but got [invalid] + + - it: should fail with missing podAffinityTerm in podAntiAffinity + set: + podOptions: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: {} + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.topologyKey] to be a string but got [invalid] + + - it: should fail with invalid matchLabelKeys in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + matchLabelKeys: "invalid" + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.matchLabelKeys] to be a slice but got [string] + + - it: should fail with invalid matchLabelKeys value in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + matchLabelKeys: + - 123 + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.matchLabelKeys.0] to be a string but got [float64] + + - it: should fail with invalid mismatchLabelKeys in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + mismatchLabelKeys: "invalid" + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.mismatchLabelKeys] to be a slice but got [string] + + - it: should fail with invalid mismatchLabelKeys value in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + mismatchLabelKeys: + - 123 + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.mismatchLabelKeys.0] to be a string but got [float64] + + - it: should fail with invalid namespaces in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + namespaces: "invalid" + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.namespaces] to be a slice but got [string] + + - it: should fail with invalid namespaces value in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + namespaces: + - 123 + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.namespaces.0] to be a string but got [float64] + + - it: should fail with invalid labelSelector in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: "invalid" + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.labelSelector] to be a map but got [string] + + - it: should fail with invalid labelSelector matchExpressions in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: "invalid" + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.labelSelector.matchExpressions] to be a slice but got [string] + + - it: should fail with invalid labelSelector operator in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: "invalid" + operator: "invalid" + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.labelSelector.matchExpressions.0.operator] to be one of [In, NotIn, Exists, DoesNotExist] but got [invalid] + - it: should fail with invalid labelSelector key in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - operator: In + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.labelSelector.matchExpressions.0.key] to be a string but got [invalid] + - it: should fail with invalid labelSelector values in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: app + operator: Exists + values: ["not-empty"] + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.labelSelector.matchExpressions.0.values] to be empty when operator is Exists or DoesNotExist but got [[not-empty]] + + - it: should fail with invalid labelSelector values in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: app + operator: In + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.labelSelector.matchExpressions.0.values] to be a slice but got [invalid] + + - it: should fail with invalid labelSelector values in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: app + operator: In + values: [] + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.labelSelector.matchExpressions.0.values] to be defined when operator is In or NotIn but got [slice] + + - it: should fail with invalid labelSelector values in podAffinityTerm + set: + podOptions: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - {} + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Affinity - Expected [affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.0.podAffinityTerm.labelSelector.matchExpressions.0.values.0] to be a string but got [map] diff --git a/charts/library/common/Chart.yaml b/charts/library/common/Chart.yaml index 37a6d7252f8..96303b97fe1 100644 --- a/charts/library/common/Chart.yaml +++ b/charts/library/common/Chart.yaml @@ -48,5 +48,5 @@ sources: - https://hub.docker.com/_/ - https://hub.docker.com/r/mikefarah/yq type: library -version: 28.9.2 +version: 28.10.0 diff --git a/charts/library/common/templates/class/_cronjob.tpl b/charts/library/common/templates/class/_cronjob.tpl index 0eeea41cad7..b7b92af00c8 100644 --- a/charts/library/common/templates/class/_cronjob.tpl +++ b/charts/library/common/templates/class/_cronjob.tpl @@ -34,6 +34,7 @@ spec: {{- $labels := (mustMerge ($objectData.podSpec.labels | default dict) (include "tc.v1.common.lib.metadata.allLabels" $rootCtx | fromYaml) (include "tc.v1.common.lib.metadata.podLabels" (dict "rootCtx" $rootCtx "objectData" $objectData) | fromYaml) + (include "tc.v1.common.lib.metadata.volumeLabels" (dict "rootCtx" $rootCtx "objectData" $objectData) | fromYaml) (include "tc.v1.common.lib.metadata.selectorLabels" (dict "rootCtx" $rootCtx "objectType" "pod" "objectName" $objectData.shortName) | fromYaml)) -}} {{- with (include "tc.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "labels" $labels) | trim) }} labels: diff --git a/charts/library/common/templates/class/_deployment.tpl b/charts/library/common/templates/class/_deployment.tpl index d4219186d05..2e6540936c0 100644 --- a/charts/library/common/templates/class/_deployment.tpl +++ b/charts/library/common/templates/class/_deployment.tpl @@ -37,6 +37,7 @@ spec: {{- $labels := (mustMerge ($objectData.podSpec.labels | default dict) (include "tc.v1.common.lib.metadata.allLabels" $rootCtx | fromYaml) (include "tc.v1.common.lib.metadata.podLabels" (dict "rootCtx" $rootCtx "objectData" $objectData) | fromYaml) + (include "tc.v1.common.lib.metadata.volumeLabels" (dict "rootCtx" $rootCtx "objectData" $objectData) | fromYaml) (include "tc.v1.common.lib.metadata.selectorLabels" (dict "rootCtx" $rootCtx "objectType" "pod" "objectName" $objectData.shortName) | fromYaml)) -}} {{- with (include "tc.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "labels" $labels) | trim) }} labels: diff --git a/charts/library/common/templates/class/_job.tpl b/charts/library/common/templates/class/_job.tpl index 6813bdbfbd8..a3e4e9aa3da 100644 --- a/charts/library/common/templates/class/_job.tpl +++ b/charts/library/common/templates/class/_job.tpl @@ -34,6 +34,7 @@ spec: {{- $labels := (mustMerge ($objectData.podSpec.labels | default dict) (include "tc.v1.common.lib.metadata.allLabels" $rootCtx | fromYaml) (include "tc.v1.common.lib.metadata.podLabels" (dict "rootCtx" $rootCtx "objectData" $objectData) | fromYaml) + (include "tc.v1.common.lib.metadata.volumeLabels" (dict "rootCtx" $rootCtx "objectData" $objectData) | fromYaml) (include "tc.v1.common.lib.metadata.selectorLabels" (dict "rootCtx" $rootCtx "objectType" "pod" "objectName" $objectData.shortName) | fromYaml)) -}} {{- with (include "tc.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "labels" $labels) | trim) }} labels: diff --git a/charts/library/common/templates/class/_statefulset.tpl b/charts/library/common/templates/class/_statefulset.tpl index 157bc84868c..8de6c390bbc 100644 --- a/charts/library/common/templates/class/_statefulset.tpl +++ b/charts/library/common/templates/class/_statefulset.tpl @@ -37,6 +37,7 @@ spec: {{- $labels := (mustMerge ($objectData.podSpec.labels | default dict) (include "tc.v1.common.lib.metadata.allLabels" $rootCtx | fromYaml) (include "tc.v1.common.lib.metadata.podLabels" (dict "rootCtx" $rootCtx "objectData" $objectData) | fromYaml) + (include "tc.v1.common.lib.metadata.volumeLabels" (dict "rootCtx" $rootCtx "objectData" $objectData) | fromYaml) (include "tc.v1.common.lib.metadata.selectorLabels" (dict "rootCtx" $rootCtx "objectType" "pod" "objectName" $objectData.shortName) | fromYaml)) -}} {{- with (include "tc.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "labels" $labels) | trim) }} labels: diff --git a/charts/library/common/templates/lib/metadata/_volumeLabels.tpl b/charts/library/common/templates/lib/metadata/_volumeLabels.tpl new file mode 100644 index 00000000000..8a1f50787e6 --- /dev/null +++ b/charts/library/common/templates/lib/metadata/_volumeLabels.tpl @@ -0,0 +1,16 @@ +{{/* Labels that are added to podSpec */}} +{{/* Call this template: +{{ include "tc.v1.common.lib.metadata.volumeLabels" $ }} +*/}} +{{- define "tc.v1.common.lib.metadata.volumeLabels" -}} + {{- $rootCtx := .rootCtx -}} + {{- $objectData := .objectData -}} + {{- $selectedVolumes := (include "tc.v1.common.lib.pod.volumes.selected" (dict "rootCtx" $rootCtx "objectData" $objectData)) | fromJson }} + + {{- $names := list -}} + {{- range $volume := $selectedVolumes.pvc -}} + {{- $names = mustAppend $names $volume.shortName -}} + {{- end }} + +truecharts.org/pvc: {{ $names | join "_" | quote }} +{{- end -}} diff --git a/charts/library/common/templates/lib/pod/_affinity.tpl b/charts/library/common/templates/lib/pod/_affinity.tpl new file mode 100644 index 00000000000..6a761237e3b --- /dev/null +++ b/charts/library/common/templates/lib/pod/_affinity.tpl @@ -0,0 +1,161 @@ +{{/* Returns pod affinity */}} +{{/* Call this template: +{{ include "tc.v1.common.lib.pod.affinity" (dict "rootCtx" $ "objectData" $objectData) }} +rootCtx: The root context of the chart. +objectData: The object data to be used to render the Pod. +*/}} +{{- define "tc.v1.common.lib.pod.affinity" -}} + {{- $rootCtx := .rootCtx -}} + {{- $objectData := .objectData -}} + + {{- $affinity := dict -}} + + {{/* Initialize from the "global" option */}} + {{- with $rootCtx.Values.podOptions.affinity -}} + {{- $affinity = . -}} + {{- end -}} + + {{/* Override with pods option */}} + {{- with $objectData.podSpec.affinity -}} + {{- $affinity = . -}} + {{- end -}} + + {{/* If default affinity is enabled and its one of this types, then merge it with user input */}} + {{- $validTypes := (list "Deployment" "StatefulSet") -}} + {{- if and (mustHas $objectData.type $validTypes) $rootCtx.Values.podOptions.defaultAffinity }} + {{- $defaultAffinity := (include "tc.v1.common.lib.pod.defaultAffinity" (dict "rootCtx" $rootCtx "objectData" $objectData) | fromYaml) -}} + {{- $defaultAffinity = $defaultAffinity | default dict -}} + {{/* Merge user input overwriting the default */}} + {{- $affinity = mustMergeOverwrite $defaultAffinity $affinity -}} + {{- end -}} + + {{- include "tc.v1.common.lib.pod.affinity.validation" (dict "rootCtx" $rootCtx "objectData" $affinity) -}} + + {{- if $affinity.nodeAffinity }} +nodeAffinity: + {{- fail "TODO: not implemented" -}} + {{- end -}} + + {{- if $affinity.podAffinity }} +podAffinity: + {{- include "tc.v1.common.lib.pod.podAffinityOrPodAntiAffinity" (dict "rootCtx" $rootCtx "data" $affinity.podAffinity) | nindent 2 -}} + {{- end -}} + + {{- if $affinity.podAntiAffinity }} +podAntiAffinity: + {{- include "tc.v1.common.lib.pod.podAffinityOrPodAntiAffinity" (dict "rootCtx" $rootCtx "data" $affinity.podAntiAffinity) | nindent 2 -}} + {{- end -}} +{{- end -}} + +{{- define "tc.v1.common.lib.pod.podAffinityOrPodAntiAffinity" -}} + {{- $rootCtx := .rootCtx -}} + {{- $data := .data -}} + + {{- if $data -}} + {{- if $data.requiredDuringSchedulingIgnoredDuringExecution }} + requiredDuringSchedulingIgnoredDuringExecution: + {{- range $term := $data.requiredDuringSchedulingIgnoredDuringExecution }} + - {{ include "tc.v1.common.lib.pod.podAffinityTerm" (dict "rootCtx" $rootCtx "data" $term) | trim | nindent 6 }} + {{- end -}} + {{- end -}} + + {{- if $data.preferredDuringSchedulingIgnoredDuringExecution }} + preferredDuringSchedulingIgnoredDuringExecution: + {{- range $term := $data.preferredDuringSchedulingIgnoredDuringExecution }} + - weight: {{ $term.weight }} + podAffinityTerm: + {{- include "tc.v1.common.lib.pod.podAffinityTerm" (dict "rootCtx" $rootCtx "data" $term.podAffinityTerm) | nindent 10 }} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{- define "tc.v1.common.lib.pod.podAffinityTerm" -}} + {{- $rootCtx := .rootCtx -}} + {{- $data := .data -}} + + {{- if $data }} +topologyKey: {{ $data.topologyKey }} + + {{- if $data.matchLabelKeys }} +matchLabelKeys: + {{- range $data.matchLabelKeys }} + - {{ . }} + {{- end -}} + {{- end -}} + + {{- if $data.mismatchLabelKeys }} +mismatchLabelKeys: + {{- range $data.mismatchLabelKeys }} + - {{ . }} + {{- end -}} + {{- end -}} + + {{- if $data.namespaces }} +namespaces: + {{- range $data.namespaces }} + - {{ . }} + {{- end -}} + {{- end -}} + + {{- if $data.labelSelector }} +labelSelector: + {{- include "tc.v1.common.lib.pod.labelSelector" (dict "rootCtx" $rootCtx "data" $data.labelSelector) | nindent 2 -}} + {{- end -}} + + {{- if $data.namespaceSelector }} +namespaceSelector: + {{- include "tc.v1.common.lib.pod.labelSelector" (dict "rootCtx" $rootCtx "data" $data.namespaceSelector) | nindent 2 -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{- define "tc.v1.common.lib.pod.labelSelector" -}} + {{- $rootCtx := .rootCtx -}} + {{- $data := .data }} + + {{- if $data.matchExpressions -}} +matchExpressions: + {{- range $expression := $data.matchExpressions }} + - key: {{ $expression.key }} + operator: {{ $expression.operator }} + {{- if mustHas $expression.operator (list "In" "NotIn") }} + values: + {{- range $expression.values }} + - {{ . }} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- if $data.matchLabels -}} +matchLabels: + {{- range $key, $value := $data.matchLabels }} + {{ $key }}: {{ $value }} + {{- end -}} + {{- end -}} +{{- end -}} + + +{{- define "tc.v1.common.lib.pod.defaultAffinity" -}} + {{- $rootCtx := .rootCtx -}} + {{- $objectData := .objectData -}} + + {{- $selectedVolumes := (include "tc.v1.common.lib.pod.volumes.selected" (dict "rootCtx" $rootCtx "objectData" $objectData)) | fromJson }} + + {{- $names := list -}} + {{- range $volume := $selectedVolumes.pvc -}} + {{- $names = mustAppend $names $volume.shortName -}} + {{- end }} + + {{- if $names }} +podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: truecharts.org/pvc + operator: In + values: + - {{ $names | join "_" }} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/pod/_affinityValidation.tpl b/charts/library/common/templates/lib/pod/_affinityValidation.tpl new file mode 100644 index 00000000000..6c6b5d6de8a --- /dev/null +++ b/charts/library/common/templates/lib/pod/_affinityValidation.tpl @@ -0,0 +1,174 @@ +{{- define "tc.v1.common.lib.pod.affinity.validation" -}} + {{- $rootCtx := .rootCtx -}} + {{- $objectData := .objectData -}} + + {{- if $objectData.podAffinity -}} + {{- include "tc.v1.common.lib.pod.affinity.validation.podAffinityOrPodAntiAffinity" (dict "rootCtx" $rootCtx "data" $objectData.podAffinity "key" "podAffinity") -}} + {{- end -}} + + {{- if $objectData.podAntiAffinity -}} + {{- include "tc.v1.common.lib.pod.affinity.validation.podAffinityOrPodAntiAffinity" (dict "rootCtx" $rootCtx "data" $objectData.podAntiAffinity "key" "podAntiAffinity") -}} + {{- end -}} +{{- end -}} + +{{- define "tc.v1.common.lib.pod.affinity.validation.podAffinityOrPodAntiAffinity" -}} + {{- $rootCtx := .rootCtx -}} + {{- $data := .data -}} + {{- $key := .key -}} + + {{- if $data -}} + {{- if and (not $data.requiredDuringSchedulingIgnoredDuringExecution) (not $data.preferredDuringSchedulingIgnoredDuringExecution) -}} + {{- fail (printf "Affinity - Expected at least one of requiredDuringSchedulingIgnoredDuringExecution or preferredDuringSchedulingIgnoredDuringExecution in [affinity.%s]" $key) -}} + {{- end -}} + + {{- if $data.requiredDuringSchedulingIgnoredDuringExecution -}} + {{- $itemData := $data.requiredDuringSchedulingIgnoredDuringExecution -}} + {{- if not (kindIs "slice" $itemData) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.requiredDuringSchedulingIgnoredDuringExecution] to be a slice but got [%s]" $key (kindOf $itemData)) -}} + {{- end -}} + + {{- range $idx, $item := $itemData -}} + {{- include "tc.v1.common.lib.pod.affinity.validation.podAffinityTerm" (dict "rootCtx" $rootCtx "data" $item "key" (printf "%s.requiredDuringSchedulingIgnoredDuringExecution.%d" $key $idx)) -}} + {{- end -}} + {{- end -}} + + {{- if $data.preferredDuringSchedulingIgnoredDuringExecution -}} + {{- $itemData := $data.preferredDuringSchedulingIgnoredDuringExecution -}} + + {{- if not (kindIs "slice" $itemData) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.preferredDuringSchedulingIgnoredDuringExecution] to be a slice but got [%s]" $key (kindOf $itemData)) -}} + {{- end -}} + + {{- range $idx, $item := $itemData -}} + {{- if not (mustHas (kindOf $item.weight) (list "int" "int64" "float64")) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.preferredDuringSchedulingIgnoredDuringExecution.%d.weight] to be a number but got [%s]" $key $idx (kindOf $item.weight)) -}} + {{- end -}} + + {{- if or (gt ($item.weight | int) 100) (lt ($item.weight | int) 0) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.preferredDuringSchedulingIgnoredDuringExecution.%d.weight] to be between 0 and 100 but got [%d]" $key $idx ($item.weight | int)) -}} + {{- end -}} + + {{- if not $item.podAffinityTerm -}} + {{- fail (printf "Affinity - Expected [affinity.%s.preferredDuringSchedulingIgnoredDuringExecution.%d.podAffinityTerm] to be defined" $key $idx) -}} + {{- end -}} + + {{- include "tc.v1.common.lib.pod.affinity.validation.podAffinityTerm" (dict "rootCtx" $rootCtx "data" $item.podAffinityTerm "key" (printf "%s.preferredDuringSchedulingIgnoredDuringExecution.%d.podAffinityTerm" $key $idx)) -}} + {{- end -}} + {{- end -}} + + {{- end -}} +{{- end -}} + +{{- define "tc.v1.common.lib.pod.affinity.validation.podAffinityTerm" -}} + {{- $rootCtx := .rootCtx -}} + {{- $data := .data -}} + {{- $key := .key -}} + + {{- if not (kindIs "string" $data.topologyKey) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.topologyKey] to be a string but got [%s]" $key (kindOf $data.topologyKey)) -}} + {{- end -}} + + {{- if $data.matchLabelKeys -}} + {{- if not (kindIs "slice" $data.matchLabelKeys) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.matchLabelKeys] to be a slice but got [%s]" $key (kindOf $data.matchLabelKeys)) -}} + {{- end -}} + + {{- range $idx, $value := $data.matchLabelKeys -}} + {{- if not (kindIs "string" $value) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.matchLabelKeys.%d] to be a string but got [%s]" $key $idx (kindOf $value)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if $data.mismatchLabelKeys -}} + {{- if not (kindIs "slice" $data.mismatchLabelKeys) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.mismatchLabelKeys] to be a slice but got [%s]" $key (kindOf $data.mismatchLabelKeys)) -}} + {{- end -}} + + {{- range $idx, $value := $data.mismatchLabelKeys -}} + {{- if not (kindIs "string" $value) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.mismatchLabelKeys.%d] to be a string but got [%s]" $key $idx (kindOf $value)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if $data.namespaces -}} + {{- if not (kindIs "slice" $data.namespaces) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.namespaces] to be a slice but got [%s]" $key (kindOf $data.namespaces)) -}} + {{- end -}} + + {{- range $idx, $value := $data.namespaces -}} + {{- if not (kindIs "string" $value) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.namespaces.%d] to be a string but got [%s]" $key $idx (kindOf $value)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if $data.labelSelector -}} + {{- include "tc.v1.common.lib.pod.affinity.validation.labelSelector" (dict "rootCtx" $rootCtx "key" (printf "%s.labelSelector" $key) "data" $data.labelSelector) -}} + {{- end -}} + + {{- if $data.namespaceSelector -}} + {{- include "tc.v1.common.lib.pod.affinity.validation.labelSelector" (dict "rootCtx" $rootCtx "key" (printf "%s.namespaceSelector" $key) "data" $data.namespaceSelector) -}} + {{- end -}} +{{- end -}} + +{{- define "tc.v1.common.lib.pod.affinity.validation.labelSelector" -}} + {{- $rootCtx := .rootCtx -}} + {{- $key := .key -}} + {{- $data := .data -}} + + {{- if not (kindIs "map" $data) -}} + {{- fail (printf "Affinity - Expected [affinity.%s] to be a map but got [%s]" $key (kindOf $data)) -}} + {{- end -}} + + {{- if $data.matchLabels -}} + {{- if not (kindIs "map" $data.matchLabels) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.matchLabels] to be a map but got [%s]" $key (kindOf $data.matchLabels)) -}} + {{- end -}} + + {{- range $key, $value := $data.matchLabels -}} + {{- if not (kindIs "string" $value) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.matchLabels.%s] to be a string but got [%s]" $key $key (kindOf $value)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if $data.matchExpressions }} + {{- if not (kindIs "slice" $data.matchExpressions) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.matchExpressions] to be a slice but got [%s]" $key (kindOf $data.matchExpressions)) -}} + {{- end -}} + + {{- $validOperators := list "In" "NotIn" "Exists" "DoesNotExist" -}} + {{- range $idx, $exp := $data.matchExpressions -}} + {{- if not (kindIs "map" $exp) -}} + {{- fail (printf "Affinity - Expected item of [affinity.%s.matchExpressions.%d] to be a map but got [%s]" $key $idx (kindOf $exp)) -}} + {{- end -}} + + {{- if not (mustHas $exp.operator $validOperators) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.matchExpressions.%d.operator] to be one of [%s] but got [%s]" $key $idx (join ", " $validOperators) $exp.operator) -}} + {{- end -}} + + {{- if not (kindIs "string" $exp.key) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.matchExpressions.%d.key] to be a string but got [%s]" $key $idx (kindOf $exp.key)) -}} + {{- end -}} + + {{- if and (mustHas $exp.operator (list "In" "NotIn")) (not (kindIs "slice" $exp.values)) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.matchExpressions.%d.values] to be a slice but got [%s]" $key $idx (kindOf $exp.values)) -}} + {{- end -}} + + {{- if and (mustHas $exp.operator (list "Exists" "DoesNotExist")) $exp.values -}} + {{- fail (printf "Affinity - Expected [affinity.%s.matchExpressions.%d.values] to be empty when operator is Exists or DoesNotExist but got [%v]" $key $idx ($exp.values)) -}} + {{- else if not $exp.values -}} + {{- fail (printf "Affinity - Expected [affinity.%s.matchExpressions.%d.values] to be defined when operator is In or NotIn but got [%s]" $key $idx (kindOf $exp.values)) -}} + {{- end -}} + + {{- range $vIdx, $value := $exp.values -}} + {{- if not (kindIs "string" $value) -}} + {{- fail (printf "Affinity - Expected [affinity.%s.matchExpressions.%d.values.%d] to be a string but got [%s]" $key $idx $vIdx (kindOf $value)) -}} + {{- end -}} + {{- end -}} + + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/pod/_volumes.tpl b/charts/library/common/templates/lib/pod/_volumes.tpl index 12d872c8a6e..1d54621bc67 100644 --- a/charts/library/common/templates/lib/pod/_volumes.tpl +++ b/charts/library/common/templates/lib/pod/_volumes.tpl @@ -8,76 +8,11 @@ objectData: The object data to be used to render the Pod. {{- $rootCtx := .rootCtx -}} {{- $objectData := .objectData -}} - {{- range $name, $persistenceValues := $rootCtx.Values.persistence -}} - {{- $enabled := (include "tc.v1.common.lib.util.enabled" (dict - "rootCtx" $rootCtx "objectData" $persistenceValues - "name" $name "caller" "Volumes" - "key" "persistence")) -}} - {{- if (eq $enabled "true") -}} - {{- $persistence := (mustDeepCopy $persistenceValues) -}} - {{- $_ := set $persistence "shortName" $name -}} - - {{- $selected := false -}} - - {{/* If set to true, define volume */}} - {{- if $persistence.targetSelectAll -}} - {{- $selected = true -}} - - {{/* If the pod is the autopermission */}} - {{- else if eq $objectData.shortName "autopermissions" -}} - {{- if $persistence.autoPermissions -}} - {{- if $persistence.autoPermissions.enabled -}} - {{- $selected = true -}} - {{- end -}} - {{- end -}} - - {{/* If targetSelector is set, check if pod is selected */}} - {{- else if $persistence.targetSelector -}} - {{- if not (kindIs "map" $persistence.targetSelector) -}} - {{- fail (printf "Persistence - Expected [targetSelector] to be [dict], but got [%s]" (kindOf $persistence.targetSelector)) -}} - {{- end -}} - - {{- if (mustHas $objectData.shortName (keys $persistence.targetSelector)) -}} - {{- $selected = true -}} - {{- end -}} - - {{/* If no targetSelector is set or targetSelectAll, check if pod is primary */}} - {{- else if $objectData.primary -}} - {{- $selected = true -}} - {{- end -}} - - {{/* If pod selected */}} - {{- if $selected -}} - {{/* Define the volume based on type */}} - {{- $type := ($persistence.type | default $rootCtx.Values.global.fallbackDefaults.persistenceType) -}} - - {{- include "tc.v1.common.lib.pod.volumes.checkRWO" (dict - "rootCtx" $rootCtx "objectData" $objectData "persistence" $persistence - "type" $type "name" $name) - -}} - - {{- if eq "pvc" $type -}} - {{- include "tc.v1.common.lib.pod.volume.pvc" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} - {{- else if eq "hostPath" $type -}} - {{- include "tc.v1.common.lib.pod.volume.hostPath" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} - {{- else if eq "secret" $type -}} - {{- include "tc.v1.common.lib.pod.volume.secret" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} - {{- else if eq "configmap" $type -}} - {{- include "tc.v1.common.lib.pod.volume.configmap" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} - {{- else if eq "emptyDir" $type -}} - {{- include "tc.v1.common.lib.pod.volume.emptyDir" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} - {{- else if eq "nfs" $type -}} - {{- include "tc.v1.common.lib.pod.volume.nfs" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} - {{- else if eq "iscsi" $type -}} - {{- include "tc.v1.common.lib.pod.volume.iscsi" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} - {{- else if eq "projected" $type -}} - {{- include "tc.v1.common.lib.pod.volume.projected" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} - {{- else if eq "device" $type -}} - {{- include "tc.v1.common.lib.pod.volume.device" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} - {{- end -}} - - {{- end -}} + {{- $selectedVolumes := (include "tc.v1.common.lib.pod.volumes.selected" (dict "rootCtx" $rootCtx "objectData" $objectData)) | fromJson -}} + {{- range $type, $volumes := $selectedVolumes -}} + {{- range $volume := $volumes -}} + {{- include (printf "tc.v1.common.lib.pod.volume.%s" $type) (dict "rootCtx" $rootCtx "objectData" $volume) | trim | nindent 0 -}} {{- end -}} {{- end -}} {{- end -}} @@ -123,3 +58,65 @@ objectData: The object data to be used to render the Pod. {{- end -}} {{- $hasRWO -}} {{- end -}} + +{{- define "tc.v1.common.lib.pod.volumes.selected" -}} + {{- $rootCtx := .rootCtx -}} + {{- $objectData := .objectData -}} + + {{- $selectedVolumes := dict + "pvc" list + "secret" list + "configmap" list + "emptyDir" list + "hostPath" list + "nfs" list + "iscsi" list + "projected" list + "device" list + -}} + + {{- range $name, $persistenceValues := $rootCtx.Values.persistence -}} + {{- $enabled := (include "tc.v1.common.lib.util.enabled" (dict + "rootCtx" $rootCtx "objectData" $persistenceValues + "name" $name "caller" "Volumes" + "key" "persistence")) + -}} + + {{- if (ne $enabled "true") -}}{{- continue -}}{{- end -}} + {{- $persistence := (mustDeepCopy $persistenceValues) -}} + {{- $_ := set $persistence "shortName" $name -}} + + {{- $selected := false -}} + + {{- if $persistence.targetSelectAll -}} + {{- $selected = true -}} + {{- else if eq $objectData.shortName "autopermissions" -}} + {{- if and $persistence.autoPermissions $persistence.autoPermissions.enabled -}} + {{- $selected = true -}} + {{- end -}} + {{- else if $persistence.targetSelector -}} + {{- if not (kindIs "map" $persistence.targetSelector) -}} + {{- fail (printf "Persistence - Expected [targetSelector] to be [dict], but got [%s]" (kindOf $persistence.targetSelector)) -}} + {{- end -}} + + {{- if (mustHas $objectData.shortName (keys $persistence.targetSelector)) -}} + {{- $selected = true -}} + {{- end -}} + {{- else if $objectData.primary -}} + {{- $selected = true -}} + {{- end -}} + + {{- if not $selected -}}{{- continue -}}{{- end -}} + + {{- $type := ($persistence.type | default $rootCtx.Values.global.fallbackDefaults.persistenceType) -}} + {{- if eq $type "vct" -}}{{- continue -}}{{- end -}} + + {{- include "tc.v1.common.lib.pod.volumes.checkRWO" (dict + "rootCtx" $rootCtx "objectData" $objectData "persistence" $persistence "type" $type "name" $name) + -}} + + {{- $_ := set $selectedVolumes $type (mustAppend (index $selectedVolumes $type) $persistence) -}} + {{- end -}} + + {{- $selectedVolumes | toJson -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/workload/_pod.tpl b/charts/library/common/templates/lib/workload/_pod.tpl index 31e414cf77a..cb4b5219814 100644 --- a/charts/library/common/templates/lib/workload/_pod.tpl +++ b/charts/library/common/templates/lib/workload/_pod.tpl @@ -30,6 +30,10 @@ priorityClassName: {{ . }} nodeSelector: {{- . | nindent 2 }} {{- end -}} + {{- with (include "tc.v1.common.lib.pod.affinity" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim) }} +affinity: + {{- . | nindent 2 }} + {{- end -}} {{- with (include "tc.v1.common.lib.pod.topologySpreadConstraints" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim) }} topologySpreadConstraints: {{- . | nindent 2 }} diff --git a/charts/library/common/values.yaml b/charts/library/common/values.yaml index 55490057a4f..86bee44b8af 100644 --- a/charts/library/common/values.yaml +++ b/charts/library/common/values.yaml @@ -143,6 +143,7 @@ podOptions: # If this key exists, takes precedence over the automated calculation # hostUsers: false shareProcessNamespace: false + affinity: {} dnsPolicy: ClusterFirst dnsConfig: options: @@ -153,6 +154,7 @@ podOptions: kubernetes.io/arch: "amd64" # -- Used to enforce a good spread for Deployments and StatefulSets by default defaultSpread: true + defaultAffinity: true topologySpreadConstraints: [] tolerations: [] schedulerName: "" @@ -204,14 +206,14 @@ vpa: # updateMode: auto resourcePolicy: containerPolicies: - - containerName: '*' - minAllowed: - cpu: 50m - memory: 50Mi - maxAllowed: - cpu: 8000m - memory: 20Gi - controlledResources: ["cpu", "memory"] + - containerName: "*" + minAllowed: + cpu: 50m + memory: 50Mi + maxAllowed: + cpu: 8000m + memory: 20Gi + controlledResources: ["cpu", "memory"] # -- Horizontal pod autoscaler hpa: @@ -250,7 +252,6 @@ hpa: # value: 4 # periodSeconds: 60 - # -- (docs/service/README.md) service: main: