diff --git a/charts/helm_lib/Chart.yaml b/charts/helm_lib/Chart.yaml index c51e620..5f7ea4e 100644 --- a/charts/helm_lib/Chart.yaml +++ b/charts/helm_lib/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 type: library name: deckhouse_lib_helm -version: 1.68.2 +version: 1.69.0 description: "Helm utils template definitions for Deckhouse modules." diff --git a/charts/helm_lib/README.md b/charts/helm_lib/README.md index 8ab2707..825aeb5 100644 --- a/charts/helm_lib/README.md +++ b/charts/helm_lib/README.md @@ -45,6 +45,10 @@ | [helm_lib_ha_enabled](#helm_lib_ha_enabled) | | **Kube Rbac Proxy** | | [helm_lib_kube_rbac_proxy_ca_certificate](#helm_lib_kube_rbac_proxy_ca_certificate) | +| **Module Controller** | +| [helm_lib_module_controller_resources](#helm_lib_module_controller_resources) | +| [helm_lib_module_webhooks_resources](#helm_lib_module_webhooks_resources) | +| [helm_lib_module_controller_log_level](#helm_lib_module_controller_log_level) | | **Module Documentation Uri** | | [helm_lib_module_documentation_uri](#helm_lib_module_documentation_uri) | | **Module Ephemeral Storage** | @@ -568,6 +572,37 @@ list: - Template context with .Values, .Chart, etc - Namespace where CA configmap will be created +## Module Controller + +### helm_lib_module_controller_resources + + Returns default controller resources + +#### Usage + +`{{ include "helm_lib_module_controller_resources" . }} ` + + + +### helm_lib_module_webhooks_resources + + Returns default webhooks resources + +#### Usage + +`{{ include "helm_lib_module_webhooks_resources" . }} ` + + + +### helm_lib_module_controller_log_level + + Returns numeric log level from module values + +#### Usage + +`{{ include "helm_lib_module_controller_log_level" (list . "csiHpe") }} ` + + ## Module Documentation Uri ### helm_lib_module_documentation_uri diff --git a/charts/helm_lib/templates/_module_controller.tpl b/charts/helm_lib/templates/_module_controller.tpl new file mode 100644 index 0000000..e09c709 --- /dev/null +++ b/charts/helm_lib/templates/_module_controller.tpl @@ -0,0 +1,512 @@ +{{- /* Usage: {{ include "helm_lib_module_controller_resources" . }} */ -}} +{{- /* Returns default controller resources */ -}} +{{- define "helm_lib_module_controller_resources" }} +cpu: 10m +memory: 25Mi +{{- end }} + +{{- /* Usage: {{ include "helm_lib_module_webhooks_resources" . }} */ -}} +{{- /* Returns default webhooks resources */ -}} +{{- define "helm_lib_module_webhooks_resources" }} +cpu: 10m +memory: 50Mi +{{- end }} + +{{- /* Usage: {{ include "helm_lib_module_controller_manifests" (list . $config) }} */ -}} +{{- /* + Generates controller Deployment, VPA and PDB manifests. + + $config parameters: + - fullname: name for the deployment (default: "controller") + - valuesKey: key to access module values (e.g., "csiHpe", "csiS3") + - webhookEnabled: whether to include webhook container (default: false) + - webhookCertPath: path to webhook cert in values (e.g., "internal.customWebhookCert") + - onMasterNode: use master node selector and tolerations (default: true) + - priorityClass: priority class name (default: "system-cluster-critical") + - podSecurityContext: "deckhouse" or "nobody" (default: "nobody") + - additionalLabels: additional labels for VPA + - controllerMaxCpu: max CPU for controller VPA (default: "200m") + - controllerMaxMemory: max memory for controller VPA (default: "100Mi") + - webhooksMaxCpu: max CPU for webhooks VPA (default: "20m") + - webhooksMaxMemory: max memory for webhooks VPA (default: "100Mi") + - additionalContainers: additional containers to add to the pod + - additionalVolumes: additional volumes to add to the pod + - additionalControllerVolumeMounts: additional volume mounts for controller + - additionalControllerEnvs: additional environment variables for controller + - controllerImage: custom controller image (default: uses helm_lib_module_image) + - controllerImageName: image name for helm_lib_module_image (default: "controller") + - webhooksImageName: image name for webhooks (default: "webhooks") + - webhooksPort: port for webhooks container (default: 8443) + - webhooksCertMountPath: mount path for webhook certs (default: "/etc/webhook/certs") + - webhooksCommand: command for webhooks container + - controllerPort: port for controller probes (default: 8081) +*/ -}} +{{- define "helm_lib_module_controller_manifests" }} + {{- $context := index . 0 }} + {{- $config := index . 1 }} + + {{- $fullname := $config.fullname | default "controller" }} + {{- $valuesKey := $config.valuesKey | required "$config.valuesKey is required" }} + {{- $webhookEnabled := dig "webhookEnabled" false $config }} + {{- $webhookCertPath := $config.webhookCertPath | default "internal.customWebhookCert" }} + {{- $onMasterNode := dig "onMasterNode" true $config }} + {{- $priorityClass := $config.priorityClass | default "system-cluster-critical" }} + {{- $podSecurityContext := $config.podSecurityContext | default "nobody" }} + {{- $additionalLabels := $config.additionalLabels | default dict }} + {{- $controllerMaxCpu := $config.controllerMaxCpu | default "200m" }} + {{- $controllerMaxMemory := $config.controllerMaxMemory | default "100Mi" }} + {{- $webhooksMaxCpu := $config.webhooksMaxCpu | default "20m" }} + {{- $webhooksMaxMemory := $config.webhooksMaxMemory | default "100Mi" }} + {{- $additionalContainers := $config.additionalContainers }} + {{- $additionalVolumes := $config.additionalVolumes }} + {{- $additionalControllerVolumeMounts := $config.additionalControllerVolumeMounts }} + {{- $additionalControllerEnvs := $config.additionalControllerEnvs }} + {{- $controllerImage := $config.controllerImage }} + {{- $controllerImageName := $config.controllerImageName | default "controller" }} + {{- $webhooksImageName := $config.webhooksImageName | default "webhooks" }} + {{- $webhooksPort := $config.webhooksPort | default 8443 }} + {{- $webhooksCertMountPath := $config.webhooksCertMountPath | default "/etc/webhook/certs" }} + {{- $webhooksCommand := $config.webhooksCommand }} + {{- $controllerPort := $config.controllerPort | default 8081 }} + + {{- /* Get module values */ -}} + {{- $moduleValues := index $context.Values $valuesKey }} + + {{- /* Build VPA labels */ -}} + {{- $vpaLabels := dict "app" $fullname }} + {{- if $onMasterNode }} + {{- $vpaLabels = merge $vpaLabels (dict "workload-resource-policy.deckhouse.io" "master") }} + {{- end }} + {{- $vpaLabels = merge $vpaLabels $additionalLabels }} + + {{- if ($context.Values.global.enabledModules | has "vertical-pod-autoscaler-crd") }} +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{ $fullname }} + namespace: d8-{{ $context.Chart.Name }} + {{- include "helm_lib_module_labels" (list $context $vpaLabels) | nindent 2 }} +spec: + targetRef: + apiVersion: "apps/v1" + kind: Deployment + name: {{ $fullname }} + updatePolicy: + updateMode: "Initial" + resourcePolicy: + containerPolicies: + - containerName: "controller" + minAllowed: + {{- include "helm_lib_module_controller_resources" $context | nindent 8 }} + maxAllowed: + cpu: {{ $controllerMaxCpu }} + memory: {{ $controllerMaxMemory }} + {{- if $webhookEnabled }} + - containerName: "webhooks" + minAllowed: + {{- include "helm_lib_module_webhooks_resources" $context | nindent 8 }} + maxAllowed: + cpu: {{ $webhooksMaxCpu }} + memory: {{ $webhooksMaxMemory }} + {{- end }} + {{- end }} +--- +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ $fullname }} + namespace: d8-{{ $context.Chart.Name }} + {{- include "helm_lib_module_labels" (list $context (dict "app" $fullname)) | nindent 2 }} +spec: + minAvailable: {{ include "helm_lib_is_ha_to_value" (list $context 1 0) }} + selector: + matchLabels: + app: {{ $fullname }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ $fullname }} + namespace: d8-{{ $context.Chart.Name }} + {{- include "helm_lib_module_labels" (list $context (dict "app" $fullname)) | nindent 2 }} +spec: + revisionHistoryLimit: 2 + {{- if $onMasterNode }} + {{- include "helm_lib_deployment_on_master_strategy_and_replicas_for_ha" $context | nindent 2 }} + {{- else }} + {{- include "helm_lib_deployment_strategy_and_replicas_for_ha" $context | nindent 2 }} + {{- end }} + selector: + matchLabels: + app: {{ $fullname }} + template: + metadata: + {{- if $webhookEnabled }} + {{- $certPath := printf "%s.ca" $webhookCertPath }} + {{- $certValue := $moduleValues }} + {{- range $part := (split "." $certPath) }} + {{- $certValue = index $certValue $part }} + {{- end }} + annotations: + checksum/ca: {{ $certValue | sha256sum | quote }} + {{- end }} + labels: + app: {{ $fullname }} + spec: + {{- include "helm_lib_priority_class" (tuple $context $priorityClass) | nindent 6 }} + {{- if $onMasterNode }} + {{- include "helm_lib_tolerations" (tuple $context "any-node" "with-uninitialized" "with-cloud-provider-uninitialized") | nindent 6 }} + {{- include "helm_lib_node_selector" (tuple $context "master") | nindent 6 }} + {{- else }} + {{- include "helm_lib_node_selector" (tuple $context "system") | nindent 6 }} + {{- include "helm_lib_tolerations" (tuple $context "system") | nindent 6 }} + {{- end }} + {{- include "helm_lib_pod_anti_affinity_for_ha" (list $context (dict "app" $fullname)) | nindent 6 }} + {{- if eq $podSecurityContext "deckhouse" }} + {{- include "helm_lib_module_pod_security_context_run_as_user_deckhouse" $context | nindent 6 }} + {{- else }} + {{- include "helm_lib_module_pod_security_context_run_as_user_nobody" $context | nindent 6 }} + {{- end }} + imagePullSecrets: + - name: {{ $context.Chart.Name }}-module-registry + serviceAccountName: {{ $fullname }} + containers: + - name: controller + {{- include "helm_lib_module_container_security_context_pss_restricted_flexible" (dict "ro" true "seccompProfile" true) | nindent 10 }} + {{- if $controllerImage }} + image: {{ $controllerImage | quote }} + {{- else }} + image: {{ include "helm_lib_module_image" (list $context $controllerImageName) }} + {{- end }} + imagePullPolicy: IfNotPresent + readinessProbe: + httpGet: + path: /readyz + port: {{ $controllerPort }} + scheme: HTTP + initialDelaySeconds: 5 + failureThreshold: 2 + periodSeconds: 1 + livenessProbe: + httpGet: + path: /healthz + port: {{ $controllerPort }} + scheme: HTTP + periodSeconds: 1 + failureThreshold: 3 + resources: + requests: + {{- include "helm_lib_module_ephemeral_storage_only_logs" $context | nindent 14 }} +{{- if not ($context.Values.global.enabledModules | has "vertical-pod-autoscaler-crd") }} + {{- include "helm_lib_module_controller_resources" $context | nindent 14 }} +{{- end }} + env: + - name: LOG_LEVEL + value: {{ include "helm_lib_module_controller_log_level" (list $context $valuesKey) | quote }} + - name: CONTROLLER_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if $additionalControllerEnvs }} + {{- $additionalControllerEnvs | toYaml | nindent 12 }} + {{- end }} + {{- if $additionalControllerVolumeMounts }} + volumeMounts: + {{- $additionalControllerVolumeMounts | toYaml | nindent 12 }} + {{- end }} + {{- if $webhookEnabled }} + - name: webhooks + {{- include "helm_lib_module_container_security_context_pss_restricted_flexible" (dict "ro" true "seccompProfile" true) | nindent 10 }} + {{- if $webhooksCommand }} + command: + {{- $webhooksCommand | toYaml | nindent 12 }} + {{- else }} + command: + - /webhooks + - -tls-cert-file={{ $webhooksCertMountPath }}/tls.crt + - -tls-key-file={{ $webhooksCertMountPath }}/tls.key + {{- end }} + image: {{ include "helm_lib_module_image" (list $context $webhooksImageName) }} + imagePullPolicy: IfNotPresent + volumeMounts: + - name: webhook-certs + mountPath: {{ $webhooksCertMountPath }} + readOnly: true + readinessProbe: + httpGet: + path: /healthz + port: {{ $webhooksPort }} + scheme: HTTPS + initialDelaySeconds: 5 + failureThreshold: 2 + periodSeconds: 1 + livenessProbe: + httpGet: + path: /healthz + port: {{ $webhooksPort }} + scheme: HTTPS + periodSeconds: 1 + failureThreshold: 3 + ports: + - name: https + containerPort: {{ $webhooksPort }} + protocol: TCP + resources: + requests: + {{- include "helm_lib_module_ephemeral_storage_only_logs" $context | nindent 14 }} +{{- if not ($context.Values.global.enabledModules | has "vertical-pod-autoscaler-crd") }} + {{- include "helm_lib_module_webhooks_resources" $context | nindent 14 }} +{{- end }} + {{- end }} + {{- if $additionalContainers }} + {{- $additionalContainers | toYaml | nindent 8 }} + {{- end }} + {{- if or $webhookEnabled $additionalVolumes }} + volumes: + {{- if $webhookEnabled }} + - name: webhook-certs + secret: + secretName: webhooks-https-certs + {{- end }} + {{- if $additionalVolumes }} + {{- $additionalVolumes | toYaml | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} + + +{{- /* Usage: {{ include "helm_lib_module_controller_log_level" (list . "csiHpe") }} */ -}} +{{- /* Returns numeric log level from module values */ -}} +{{- define "helm_lib_module_controller_log_level" }} + {{- $context := index . 0 }} + {{- $valuesKey := index . 1 }} + {{- $moduleValues := index $context.Values $valuesKey }} + {{- $logLevel := $moduleValues.logLevel | default "INFO" }} + {{- if eq $logLevel "ERROR" -}} +0 + {{- else if eq $logLevel "WARN" -}} +1 + {{- else if eq $logLevel "INFO" -}} +2 + {{- else if eq $logLevel "DEBUG" -}} +3 + {{- else if eq $logLevel "TRACE" -}} +4 + {{- else -}} +2 + {{- end -}} +{{- end }} + + +{{- /* Usage: {{ include "helm_lib_module_webhook_service" (list . $config) }} */ -}} +{{- /* + Generates webhook Service manifest. + + $config parameters: + - fullname: name of the service (default: "webhooks") + - selectorApp: app label for selector (default: "controller") + - targetPort: target port name or number (default: "https") +*/ -}} +{{- define "helm_lib_module_webhook_service" }} + {{- $context := index . 0 }} + {{- $config := index . 1 | default dict }} + + {{- $fullname := $config.fullname | default "webhooks" }} + {{- $selectorApp := $config.selectorApp | default "controller" }} + {{- $targetPort := $config.targetPort | default "https" }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ $fullname }} + namespace: d8-{{ $context.Chart.Name }} + {{- include "helm_lib_module_labels" (list $context (dict "app" $selectorApp)) | nindent 2 }} +spec: + type: ClusterIP + ports: + - port: 443 + targetPort: {{ $targetPort }} + protocol: TCP + name: https + selector: + app: {{ $selectorApp }} +{{- end }} + + +{{- /* Usage: {{ include "helm_lib_module_validating_webhook_configuration" (list . $config) }} */ -}} +{{- /* + Generates ValidatingWebhookConfiguration manifest. + + $config parameters: + - name: webhook configuration name (required, e.g., "sc-validation") + - webhookName: webhook name suffix (required, e.g., "sc-validation") + - valuesKey: key to access module values (required, e.g., "csiHpe") + - webhookCertPath: path to webhook cert in values (default: "internal.customWebhookCert") + - serviceName: service name (default: "webhooks") + - path: webhook path (required, e.g., "/sc-validate") + - rules: webhook rules (required) + - matchConditions: optional match conditions + - sideEffects: side effects (default: "None") + - timeoutSeconds: timeout (default: 5) +*/ -}} +{{- define "helm_lib_module_validating_webhook_configuration" }} + {{- $context := index . 0 }} + {{- $config := index . 1 }} + + {{- $name := $config.name | required "$config.name is required" }} + {{- $webhookName := $config.webhookName | required "$config.webhookName is required" }} + {{- $valuesKey := $config.valuesKey | required "$config.valuesKey is required" }} + {{- $webhookCertPath := $config.webhookCertPath | default "internal.customWebhookCert" }} + {{- $serviceName := $config.serviceName | default "webhooks" }} + {{- $path := $config.path | required "$config.path is required" }} + {{- $rules := $config.rules | required "$config.rules is required" }} + {{- $matchConditions := $config.matchConditions }} + {{- $sideEffects := $config.sideEffects | default "None" }} + {{- $timeoutSeconds := $config.timeoutSeconds | default 5 }} + + {{- /* Get module values and cert */ -}} + {{- $moduleValues := index $context.Values $valuesKey }} + {{- $certPath := printf "%s.ca" $webhookCertPath }} + {{- $certValue := $moduleValues }} + {{- range $part := (split "." $certPath) }} + {{- $certValue = index $certValue $part }} + {{- end }} +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: "d8-{{ $context.Chart.Name }}-{{ $name }}" + {{- include "helm_lib_module_labels" (list $context) | nindent 2 }} +webhooks: + - name: "d8-{{ $context.Chart.Name }}-{{ $webhookName }}.deckhouse.io" + rules: + {{- $rules | toYaml | nindent 6 }} + clientConfig: + service: + namespace: "d8-{{ $context.Chart.Name }}" + name: {{ $serviceName | quote }} + path: {{ $path | quote }} + caBundle: {{ $certValue | b64enc | quote }} + admissionReviewVersions: ["v1", "v1beta1"] + sideEffects: {{ $sideEffects }} + timeoutSeconds: {{ $timeoutSeconds }} + {{- if $matchConditions }} + matchConditions: + {{- $matchConditions | toYaml | nindent 6 }} + {{- end }} +{{- end }} + + +{{- /* Usage: {{ include "helm_lib_module_webhook_certs_secret" (list . $config) }} */ -}} +{{- /* + Generates webhook TLS certificates Secret manifest. + + $config parameters: + - fullname: name of the secret (default: "webhooks-https-certs") + - valuesKey: key to access module values (required, e.g., "csiHpe", "csiS3") + - webhookCertPath: path to webhook cert in values (default: "internal.customWebhookCert") + - appLabel: app label for the secret (default: "webhooks") +*/ -}} +{{- define "helm_lib_module_webhook_certs_secret" }} + {{- $context := index . 0 }} + {{- $config := index . 1 }} + + {{- $fullname := $config.fullname | default "webhooks-https-certs" }} + {{- $valuesKey := $config.valuesKey | required "$config.valuesKey is required" }} + {{- $webhookCertPath := $config.webhookCertPath | default "internal.customWebhookCert" }} + {{- $appLabel := $config.appLabel | default "webhooks" }} + + {{- /* Get module values and certs */ -}} + {{- $moduleValues := index $context.Values $valuesKey }} + {{- $certValue := $moduleValues }} + {{- range $part := (split "." $webhookCertPath) }} + {{- $certValue = index $certValue $part }} + {{- end }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $fullname }} + namespace: d8-{{ $context.Chart.Name }} + {{- include "helm_lib_module_labels" (list $context (dict "app" $appLabel)) | nindent 2 }} +type: kubernetes.io/tls +data: + ca.crt: {{ $certValue.ca | b64enc | quote }} + tls.crt: {{ $certValue.crt | b64enc | quote }} + tls.key: {{ $certValue.key | b64enc | quote }} +{{- end }} + + +{{- /* Usage: {{ include "helm_lib_module_controller_rbac" (list . $config) }} */ -}} +{{- /* + Generates controller RBAC manifests (ServiceAccount, Role, ClusterRole, RoleBinding, ClusterRoleBinding). + + $config parameters: + - fullname: name for the resources (default: "controller") + - roleRules: rules for namespaced Role (required) + - clusterRoleRules: rules for ClusterRole (required) +*/ -}} +{{- define "helm_lib_module_controller_rbac" -}} + {{- $context := index . 0 -}} + {{- $config := index . 1 -}} + {{- $fullname := $config.fullname | default "controller" -}} + {{- $roleRules := $config.roleRules | required "$config.roleRules is required" -}} + {{- $clusterRoleRules := $config.clusterRoleRules | required "$config.clusterRoleRules is required" }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ $fullname }} + namespace: d8-{{ $context.Chart.Name }} + {{- include "helm_lib_module_labels" (list $context (dict "app" $fullname)) | nindent 2 }} +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ $fullname }} + namespace: d8-{{ $context.Chart.Name }} + {{- include "helm_lib_module_labels" (list $context (dict "app" $fullname)) | nindent 2 }} +rules: + {{- $roleRules | toYaml | nindent 2 }} +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: d8:{{ $context.Chart.Name }}:{{ $fullname }} + {{- include "helm_lib_module_labels" (list $context (dict "app" $fullname)) | nindent 2 }} +rules: + {{- $clusterRoleRules | toYaml | nindent 2 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ $fullname }} + namespace: d8-{{ $context.Chart.Name }} + {{- include "helm_lib_module_labels" (list $context (dict "app" $fullname)) | nindent 2 }} +subjects: + - kind: ServiceAccount + name: {{ $fullname }} + namespace: d8-{{ $context.Chart.Name }} +roleRef: + kind: Role + name: {{ $fullname }} + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: d8:{{ $context.Chart.Name }}:{{ $fullname }} + {{- include "helm_lib_module_labels" (list $context (dict "app" $fullname)) | nindent 2 }} +subjects: + - kind: ServiceAccount + name: {{ $fullname }} + namespace: d8-{{ $context.Chart.Name }} +roleRef: + kind: ClusterRole + name: d8:{{ $context.Chart.Name }}:{{ $fullname }} + apiGroup: rbac.authorization.k8s.io +{{- end }} + + + diff --git a/tests/templates/helm_lib_module_controller_log_level.yaml b/tests/templates/helm_lib_module_controller_log_level.yaml new file mode 100644 index 0000000..5abda1a --- /dev/null +++ b/tests/templates/helm_lib_module_controller_log_level.yaml @@ -0,0 +1,5 @@ +{{- if hasKey .Values "_testvalues" -}} +{{- if and (kindIs "map" .Values._testvalues) .Values._testvalues.valuesKey -}} +logLevel: {{ include "helm_lib_module_controller_log_level" (list . .Values._testvalues.valuesKey) | quote }} +{{- end -}} +{{- end -}} diff --git a/tests/templates/helm_lib_module_controller_manifests.yaml b/tests/templates/helm_lib_module_controller_manifests.yaml new file mode 100644 index 0000000..0897dce --- /dev/null +++ b/tests/templates/helm_lib_module_controller_manifests.yaml @@ -0,0 +1,5 @@ +{{- if hasKey .Values "_testvalues" -}} +{{- if and (kindIs "map" .Values._testvalues) .Values._testvalues.valuesKey -}} +{{- include "helm_lib_module_controller_manifests" (list . .Values._testvalues) -}} +{{- end -}} +{{- end -}} diff --git a/tests/templates/helm_lib_module_controller_rbac.yaml b/tests/templates/helm_lib_module_controller_rbac.yaml new file mode 100644 index 0000000..4bc8e20 --- /dev/null +++ b/tests/templates/helm_lib_module_controller_rbac.yaml @@ -0,0 +1,5 @@ +{{- if hasKey .Values "_testvalues" -}} +{{- if and (kindIs "map" .Values._testvalues) .Values._testvalues.roleRules .Values._testvalues.clusterRoleRules -}} +{{- include "helm_lib_module_controller_rbac" (list . .Values._testvalues) -}} +{{- end -}} +{{- end -}} diff --git a/tests/templates/helm_lib_module_validating_webhook_configuration.yaml b/tests/templates/helm_lib_module_validating_webhook_configuration.yaml new file mode 100644 index 0000000..66970ba --- /dev/null +++ b/tests/templates/helm_lib_module_validating_webhook_configuration.yaml @@ -0,0 +1,5 @@ +{{- if hasKey .Values "_testvalues" -}} +{{- if and (kindIs "map" .Values._testvalues) .Values._testvalues.name .Values._testvalues.valuesKey .Values._testvalues.path .Values._testvalues.rules -}} +{{- include "helm_lib_module_validating_webhook_configuration" (list . .Values._testvalues) -}} +{{- end -}} +{{- end -}} diff --git a/tests/templates/helm_lib_module_webhook_certs_secret.yaml b/tests/templates/helm_lib_module_webhook_certs_secret.yaml new file mode 100644 index 0000000..58044d3 --- /dev/null +++ b/tests/templates/helm_lib_module_webhook_certs_secret.yaml @@ -0,0 +1,5 @@ +{{- if hasKey .Values "_testvalues" -}} +{{- if and (kindIs "map" .Values._testvalues) .Values._testvalues.valuesKey .Values._testvalues.webhookCertPath -}} +{{- include "helm_lib_module_webhook_certs_secret" (list . .Values._testvalues) -}} +{{- end -}} +{{- end -}} diff --git a/tests/templates/helm_lib_module_webhook_service.yaml b/tests/templates/helm_lib_module_webhook_service.yaml new file mode 100644 index 0000000..f5d7864 --- /dev/null +++ b/tests/templates/helm_lib_module_webhook_service.yaml @@ -0,0 +1,5 @@ +{{- if hasKey .Values "_testvalues" }} +{{- if kindIs "map" .Values._testvalues }} +{{ include "helm_lib_module_webhook_service" (list . .Values._testvalues) }} +{{- end }} +{{- end }} diff --git a/tests/tests/helm_lib_module_controller_log_level_test.yaml b/tests/tests/helm_lib_module_controller_log_level_test.yaml new file mode 100644 index 0000000..e19791c --- /dev/null +++ b/tests/tests/helm_lib_module_controller_log_level_test.yaml @@ -0,0 +1,86 @@ +suite: helm_lib_module_controller_log_level definition +templates: + - helm_lib_module_controller_log_level.yaml +tests: + - it: returns 0 for ERROR log level + set: + testModule: + logLevel: ERROR + _testvalues: + valuesKey: testModule + + asserts: + - equal: + path: logLevel + value: "0" + + - it: returns 1 for WARN log level + set: + testModule: + logLevel: WARN + _testvalues: + valuesKey: testModule + + asserts: + - equal: + path: logLevel + value: "1" + + - it: returns 2 for INFO log level + set: + testModule: + logLevel: INFO + _testvalues: + valuesKey: testModule + + asserts: + - equal: + path: logLevel + value: "2" + + - it: returns 3 for DEBUG log level + set: + testModule: + logLevel: DEBUG + _testvalues: + valuesKey: testModule + + asserts: + - equal: + path: logLevel + value: "3" + + - it: returns 4 for TRACE log level + set: + testModule: + logLevel: TRACE + _testvalues: + valuesKey: testModule + + asserts: + - equal: + path: logLevel + value: "4" + + - it: returns 2 (INFO) as default when logLevel is not set + set: + testModule: {} + _testvalues: + valuesKey: testModule + + asserts: + - equal: + path: logLevel + value: "2" + + - it: returns 2 (INFO) for unknown log level + set: + testModule: + logLevel: UNKNOWN + _testvalues: + valuesKey: testModule + + asserts: + - equal: + path: logLevel + value: "2" diff --git a/tests/tests/helm_lib_module_controller_manifests_test.yaml b/tests/tests/helm_lib_module_controller_manifests_test.yaml new file mode 100644 index 0000000..6d0b9ab --- /dev/null +++ b/tests/tests/helm_lib_module_controller_manifests_test.yaml @@ -0,0 +1,155 @@ +suite: helm_lib_module_controller_manifests definition +templates: + - helm_lib_module_controller_manifests.yaml +tests: + - it: renders PDB manifest + set: + global: + enabledModules: [] + modules: + placement: {} + modulesImages: + registry: + base: "deckhouse.io/deckhouse/ce" + digests: + testModule: + controller: sha256:abc123 + discovery: + d8SpecificNodeCountByRole: + master: 3 + highAvailability: true + testModule: + logLevel: INFO + _testvalues: + valuesKey: testModule + webhookEnabled: false + onMasterNode: true + + asserts: + - hasDocuments: + count: 2 + + - isKind: + of: PodDisruptionBudget + documentIndex: 0 + + - equal: + path: metadata.name + value: controller + documentIndex: 0 + + - equal: + path: spec.minAvailable + value: 1 + documentIndex: 0 + + - isKind: + of: Deployment + documentIndex: 1 + + - it: renders VPA when vertical-pod-autoscaler-crd is enabled + set: + global: + enabledModules: + - vertical-pod-autoscaler-crd + modules: + placement: {} + modulesImages: + registry: + base: "deckhouse.io/deckhouse/ce" + digests: + testModule: + controller: sha256:abc123 + discovery: + d8SpecificNodeCountByRole: + master: 3 + testModule: + logLevel: INFO + _testvalues: + valuesKey: testModule + webhookEnabled: false + onMasterNode: true + + asserts: + - hasDocuments: + count: 3 + + - isKind: + of: VerticalPodAutoscaler + documentIndex: 0 + + - equal: + path: metadata.name + value: controller + documentIndex: 0 + + - equal: + path: spec.updatePolicy.updateMode + value: Initial + documentIndex: 0 + + - equal: + path: spec.resourcePolicy.containerPolicies[0].containerName + value: controller + documentIndex: 0 + + - isKind: + of: PodDisruptionBudget + documentIndex: 1 + + - isKind: + of: Deployment + documentIndex: 2 + + - it: renders VPA with webhooks container policy when webhook is enabled + set: + global: + enabledModules: + - vertical-pod-autoscaler-crd + modules: + placement: {} + modulesImages: + registry: + base: "deckhouse.io/deckhouse/ce" + digests: + testModule: + controller: sha256:abc123 + webhooks: sha256:def456 + discovery: + d8SpecificNodeCountByRole: + master: 3 + testModule: + logLevel: INFO + internal: + customWebhookCert: + ca: test-ca-cert + crt: test-crt + key: test-key + _testvalues: + valuesKey: testModule + webhookEnabled: true + webhookCertPath: internal.customWebhookCert + onMasterNode: true + + asserts: + - hasDocuments: + count: 3 + + - isKind: + of: VerticalPodAutoscaler + documentIndex: 0 + + - lengthEqual: + path: spec.resourcePolicy.containerPolicies + count: 2 + documentIndex: 0 + + - equal: + path: spec.resourcePolicy.containerPolicies[0].containerName + value: controller + documentIndex: 0 + + - equal: + path: spec.resourcePolicy.containerPolicies[1].containerName + value: webhooks + documentIndex: 0 diff --git a/tests/tests/helm_lib_module_controller_rbac_test.yaml b/tests/tests/helm_lib_module_controller_rbac_test.yaml new file mode 100644 index 0000000..1864697 --- /dev/null +++ b/tests/tests/helm_lib_module_controller_rbac_test.yaml @@ -0,0 +1,123 @@ +suite: helm_lib_module_controller_rbac definition +templates: + - helm_lib_module_controller_rbac.yaml +tests: + - it: renders RBAC resources with ServiceAccount + set: + _testvalues: + roleRules: + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "list"] + clusterRoleRules: + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["create", "delete", "list", "get", "watch"] + + asserts: + - hasDocuments: + count: 5 + + - matchRegex: + path: metadata.name + pattern: "^controller$" + documentIndex: 0 + + - isKind: + of: ServiceAccount + documentIndex: 0 + + - isKind: + of: Role + documentIndex: 1 + + - isKind: + of: ClusterRole + documentIndex: 2 + + - isKind: + of: RoleBinding + documentIndex: 3 + + - isKind: + of: ClusterRoleBinding + documentIndex: 4 + + - it: renders RBAC resources with custom fullname + set: + _testvalues: + fullname: my-controller + roleRules: + - apiGroups: [""] + resources: ["events"] + verbs: ["create"] + clusterRoleRules: + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["list"] + + asserts: + - hasDocuments: + count: 5 + + - equal: + path: metadata.name + value: my-controller + documentIndex: 0 + + - equal: + path: metadata.name + value: d8:test-module:my-controller + documentIndex: 2 + + - it: renders Role with correct rules + set: + _testvalues: + roleRules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "create", "update"] + clusterRoleRules: + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get"] + + asserts: + - lengthEqual: + path: rules + count: 2 + documentIndex: 1 + + - equal: + path: rules[0].resources[0] + value: secrets + documentIndex: 1 + + - it: renders ClusterRole with correct rules + set: + _testvalues: + roleRules: + - apiGroups: [""] + resources: ["events"] + verbs: ["create"] + clusterRoleRules: + - apiGroups: ["storage.deckhouse.io"] + resources: ["s3storageclasses", "s3storageclasses/status"] + verbs: ["get", "list", "create", "watch", "update"] + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["create", "delete", "list", "get", "watch", "update"] + + asserts: + - lengthEqual: + path: rules + count: 2 + documentIndex: 2 + + - contains: + path: rules[0].resources + content: s3storageclasses + documentIndex: 2 diff --git a/tests/tests/helm_lib_module_validating_webhook_configuration_test.yaml b/tests/tests/helm_lib_module_validating_webhook_configuration_test.yaml new file mode 100644 index 0000000..00cc047 --- /dev/null +++ b/tests/tests/helm_lib_module_validating_webhook_configuration_test.yaml @@ -0,0 +1,150 @@ +suite: helm_lib_module_validating_webhook_configuration definition +templates: + - helm_lib_module_validating_webhook_configuration.yaml +tests: + - it: renders validating webhook configuration for storageclasses + set: + testModule: + internal: + customWebhookCert: + ca: my-ca-certificate + crt: crt + key: key + _testvalues: + name: sc-validation + webhookName: sc-validation + valuesKey: testModule + webhookCertPath: internal.customWebhookCert + path: /sc-validate + rules: + - apiGroups: ["storage.k8s.io"] + apiVersions: ["v1"] + operations: ["*"] + resources: ["storageclasses"] + scope: Cluster + + asserts: + - containsDocument: + kind: ValidatingWebhookConfiguration + apiVersion: admissionregistration.k8s.io/v1 + name: d8-test-module-sc-validation + + - equal: + path: webhooks[0].name + value: d8-test-module-sc-validation.deckhouse.io + + - equal: + path: webhooks[0].clientConfig.service.namespace + value: d8-test-module + + - equal: + path: webhooks[0].clientConfig.service.name + value: webhooks + + - equal: + path: webhooks[0].clientConfig.service.path + value: /sc-validate + + - equal: + path: webhooks[0].clientConfig.caBundle + value: bXktY2EtY2VydGlmaWNhdGU= + + - equal: + path: webhooks[0].sideEffects + value: None + + - equal: + path: webhooks[0].timeoutSeconds + value: 5 + + - it: renders validating webhook configuration for moduleconfigs with matchConditions + set: + testModule: + internal: + customWebhookCert: + ca: ca-cert + crt: crt + key: key + _testvalues: + name: mc-validation + webhookName: mc-validation + valuesKey: testModule + webhookCertPath: internal.customWebhookCert + path: /mc-validate + rules: + - apiGroups: ["deckhouse.io"] + apiVersions: ["v1alpha1"] + operations: ["CREATE", "UPDATE"] + resources: ["moduleconfigs"] + scope: Cluster + matchConditions: + - name: match-csi-s3 + expression: 'request.name == "csi-s3"' + + asserts: + - containsDocument: + kind: ValidatingWebhookConfiguration + apiVersion: admissionregistration.k8s.io/v1 + name: d8-test-module-mc-validation + + - equal: + path: webhooks[0].matchConditions[0].name + value: match-csi-s3 + + - equal: + path: webhooks[0].matchConditions[0].expression + value: 'request.name == "csi-s3"' + + - it: renders validating webhook configuration with custom service name + set: + testModule: + internal: + customWebhookCert: + ca: ca + crt: crt + key: key + _testvalues: + name: validation + webhookName: validation + valuesKey: testModule + webhookCertPath: internal.customWebhookCert + serviceName: custom-webhooks + path: /validate + rules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE"] + resources: ["pods"] + scope: Namespaced + + asserts: + - equal: + path: webhooks[0].clientConfig.service.name + value: custom-webhooks + + - it: renders validating webhook configuration with custom timeout + set: + testModule: + internal: + customWebhookCert: + ca: ca + crt: crt + key: key + _testvalues: + name: validation + webhookName: validation + valuesKey: testModule + webhookCertPath: internal.customWebhookCert + path: /validate + timeoutSeconds: 10 + rules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE"] + resources: ["pods"] + scope: Namespaced + + asserts: + - equal: + path: webhooks[0].timeoutSeconds + value: 10 diff --git a/tests/tests/helm_lib_module_webhook_certs_secret_test.yaml b/tests/tests/helm_lib_module_webhook_certs_secret_test.yaml new file mode 100644 index 0000000..dfe9e6f --- /dev/null +++ b/tests/tests/helm_lib_module_webhook_certs_secret_test.yaml @@ -0,0 +1,76 @@ +suite: helm_lib_module_webhook_certs_secret definition +templates: + - helm_lib_module_webhook_certs_secret.yaml +tests: + - it: renders webhook certs secret with defaults + set: + testModule: + internal: + customWebhookCert: + ca: my-ca-certificate + crt: my-tls-certificate + key: my-tls-key + _testvalues: + valuesKey: testModule + webhookCertPath: internal.customWebhookCert + + asserts: + - containsDocument: + kind: Secret + apiVersion: v1 + name: webhooks-https-certs + namespace: d8-test-module + + - equal: + path: type + value: kubernetes.io/tls + + - equal: + path: data["ca.crt"] + value: bXktY2EtY2VydGlmaWNhdGU= + + - equal: + path: data["tls.crt"] + value: bXktdGxzLWNlcnRpZmljYXRl + + - equal: + path: data["tls.key"] + value: bXktdGxzLWtleQ== + + - it: renders webhook certs secret with custom fullname + set: + testModule: + internal: + customWebhookCert: + ca: ca + crt: crt + key: key + _testvalues: + valuesKey: testModule + webhookCertPath: internal.customWebhookCert + fullname: custom-certs + + asserts: + - containsDocument: + kind: Secret + apiVersion: v1 + name: custom-certs + namespace: d8-test-module + + - it: renders webhook certs secret with custom app label + set: + testModule: + internal: + customWebhookCert: + ca: ca + crt: crt + key: key + _testvalues: + valuesKey: testModule + webhookCertPath: internal.customWebhookCert + appLabel: my-app + + asserts: + - equal: + path: metadata.labels.app + value: my-app diff --git a/tests/tests/helm_lib_module_webhook_service_test.yaml b/tests/tests/helm_lib_module_webhook_service_test.yaml new file mode 100644 index 0000000..b3cfcc7 --- /dev/null +++ b/tests/tests/helm_lib_module_webhook_service_test.yaml @@ -0,0 +1,62 @@ +suite: helm_lib_module_webhook_service definition +templates: + - helm_lib_module_webhook_service.yaml +tests: + - it: renders webhook service with defaults + set: + _testvalues: {} + + asserts: + - containsDocument: + kind: Service + apiVersion: v1 + name: webhooks + namespace: d8-test-module + + - equal: + path: spec.type + value: ClusterIP + + - equal: + path: spec.ports[0].port + value: 443 + + - equal: + path: spec.ports[0].targetPort + value: https + + - equal: + path: spec.selector.app + value: controller + + - it: renders webhook service with custom fullname + set: + _testvalues: + fullname: my-webhooks + + asserts: + - containsDocument: + kind: Service + apiVersion: v1 + name: my-webhooks + namespace: d8-test-module + + - it: renders webhook service with custom selector + set: + _testvalues: + selectorApp: my-controller + + asserts: + - equal: + path: spec.selector.app + value: my-controller + + - it: renders webhook service with custom targetPort + set: + _testvalues: + targetPort: 8443 + + asserts: + - equal: + path: spec.ports[0].targetPort + value: 8443