diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f0d991c5..058b0e96 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -99,6 +99,13 @@ repos: files: ^helm/ language: system pass_filenames: false + - id: make-helm-unittest + name: Make Helm Unittest + entry: make helm-unittest + types: [yaml] + files: ^helm/ + language: system + pass_filenames: false # https://github.com/golangci/golangci-lint/blob/main/.pre-commit-hooks.yaml - id: make-golangci-lint name: make-golangci-lint diff --git a/Makefile b/Makefile index 0b039280..5419922e 100644 --- a/Makefile +++ b/Makefile @@ -211,6 +211,14 @@ helm-validate: helm-dependency-update helm-lint ## Validate Helm charts. helm-docs: helm-docs-bin ## Run helm-docs. $(HELM_DOCS) --chart-search-root=helm +.PHONY: helm-unittest +helm-unittest: ## Run helm-unittest. + @if ! helm plugin list | grep -q "unittest"; then \ + helm plugin install https://github.com/helm-unittest/helm-unittest ;\ + fi + @echo "Running helm unittest for slurm-operator chart" + @helm unittest helm/slurm-operator + .PHONY: helm-lint helm-lint: ## Lint Helm charts. find "helm/" -depth -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0r -n1 helm lint --strict diff --git a/helm/slurm-operator/.helmignore b/helm/slurm-operator/.helmignore index 400036a3..716bd8e6 100644 --- a/helm/slurm-operator/.helmignore +++ b/helm/slurm-operator/.helmignore @@ -23,3 +23,4 @@ .vscode/ # Development files skaffold.yaml +tests/ diff --git a/helm/slurm-operator/tests/__snapshot__/operator_deployment_test.yaml.snap b/helm/slurm-operator/tests/__snapshot__/operator_deployment_test.yaml.snap new file mode 100644 index 00000000..7b28c2f9 --- /dev/null +++ b/helm/slurm-operator/tests/__snapshot__/operator_deployment_test.yaml.snap @@ -0,0 +1,65 @@ +manifest should match snapshot: + 1: | + apiVersion: apps/v1 + kind: Deployment + metadata: + labels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: slurm-operator + app.kubernetes.io/version: 1.2.3 + helm.sh/chart: slurm-operator-1.2.3 + name: slurm-operator + namespace: test-namespace + spec: + replicas: 1 + revisionHistoryLimit: 0 + selector: + matchLabels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/name: slurm-operator + template: + metadata: + labels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: slurm-operator + app.kubernetes.io/version: 1.2.3 + helm.sh/chart: slurm-operator-1.2.3 + spec: + containers: + - args: + - --accounting-workers + - "4" + - --controller-workers + - "4" + - --loginset-workers + - "4" + - --nodeset-workers + - "4" + - --restapi-workers + - "4" + - --token-workers + - "4" + - --slurmclient-workers + - "2" + - --zap-log-level + - info + - --health-addr + - :8081 + - --metrics-addr + - :8080 + image: ghcr.io/slinkyproject/slurm-operator:1.2.3 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: /healthz + port: 8081 + name: slurm-operator + readinessProbe: + httpGet: + path: /readyz + port: 8081 + hostname: slurm-operator + priorityClassName: null + serviceAccountName: test-release-slurm-operator diff --git a/helm/slurm-operator/tests/__snapshot__/operator_rbac_test.yaml.snap b/helm/slurm-operator/tests/__snapshot__/operator_rbac_test.yaml.snap new file mode 100644 index 00000000..307c5372 --- /dev/null +++ b/helm/slurm-operator/tests/__snapshot__/operator_rbac_test.yaml.snap @@ -0,0 +1,140 @@ +manifest should match snapshot: + 1: | + apiVersion: v1 + kind: ServiceAccount + metadata: + labels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: slurm-operator + app.kubernetes.io/version: 1.2.3 + helm.sh/chart: slurm-operator-1.2.3 + name: test-release-slurm-operator + namespace: test-namespace + 2: | + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + name: test-release-slurm-operator + namespace: test-namespace + rules: + - apiGroups: + - "" + resources: + - configmaps + - events + - persistentvolumeclaims + - pods + - secrets + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch + - patch + - apiGroups: + - "" + resources: + - pods/status + verbs: + - get + - patch + - update + - apiGroups: + - apps + resources: + - controllerrevisions + - deployments + - statefulsets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - slinky.slurm.net + resources: + - accountings + - controllers + - loginsets + - nodesets + - restapis + - tokens + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - slinky.slurm.net + resources: + - accountings/finalizers + - controllers/finalizers + - loginsets/finalizers + - nodesets/finalizers + - restapis/finalizers + - tokens/finalizers + verbs: + - update + - apiGroups: + - slinky.slurm.net + resources: + - accountings/status + - controllers/status + - loginsets/status + - nodesets/status + - restapis/status + - tokens/status + verbs: + - get + - patch + - update + 3: | + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + labels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: slurm-operator + app.kubernetes.io/version: 1.2.3 + helm.sh/chart: slurm-operator-1.2.3 + name: test-release-slurm-operator + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: test-release-slurm-operator + subjects: + - kind: ServiceAccount + name: test-release-slurm-operator + namespace: test-namespace diff --git a/helm/slurm-operator/tests/__snapshot__/operator_service_test.yaml.snap b/helm/slurm-operator/tests/__snapshot__/operator_service_test.yaml.snap new file mode 100644 index 00000000..935f808a --- /dev/null +++ b/helm/slurm-operator/tests/__snapshot__/operator_service_test.yaml.snap @@ -0,0 +1,30 @@ +manifest should match snapshot: + 1: | + apiVersion: v1 + kind: Service + metadata: + labels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: slurm-operator + app.kubernetes.io/version: 1.2.3 + helm.sh/chart: slurm-operator-1.2.3 + name: slurm-operator + namespace: test-namespace + spec: + clusterIP: None + ports: + - name: metrics + port: 8080 + protocol: TCP + targetPort: 8080 + - name: health + port: 8081 + protocol: TCP + targetPort: 8081 + selector: + app.kubernetes.io/instance: test-release + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: slurm-operator + app.kubernetes.io/version: 1.2.3 + helm.sh/chart: slurm-operator-1.2.3 diff --git a/helm/slurm-operator/tests/__snapshot__/webhook_deployment_test.yaml.snap b/helm/slurm-operator/tests/__snapshot__/webhook_deployment_test.yaml.snap new file mode 100644 index 00000000..77ba81dc --- /dev/null +++ b/helm/slurm-operator/tests/__snapshot__/webhook_deployment_test.yaml.snap @@ -0,0 +1,62 @@ +manifest should match snapshot: + 1: | + apiVersion: apps/v1 + kind: Deployment + metadata: + labels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: slurm-operator-webhook + app.kubernetes.io/version: 1.2.3 + helm.sh/chart: slurm-operator-1.2.3 + name: slurm-operator-webhook + namespace: test-namespace + spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/name: slurm-operator-webhook + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + type: RollingUpdate + template: + metadata: + labels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: slurm-operator-webhook + app.kubernetes.io/version: 1.2.3 + helm.sh/chart: slurm-operator-1.2.3 + spec: + containers: + - args: + - --zap-log-level + - info + - --health-addr + - :8081 + image: ghcr.io/slinkyproject/slurm-operator-webhook:1.2.3 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: /healthz + port: 8081 + name: webhook + readinessProbe: + httpGet: + path: /readyz + port: 8081 + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs/ + name: certificates + readOnly: true + hostname: slurm-operator-webhook + priorityClassName: null + serviceAccountName: slurm-operator-webhook + volumes: + - name: certificates + secret: + defaultMode: 420 + secretName: slurm-operator-webhook-ca diff --git a/helm/slurm-operator/tests/__snapshot__/webhook_rbac_test.yaml.snap b/helm/slurm-operator/tests/__snapshot__/webhook_rbac_test.yaml.snap new file mode 100644 index 00000000..dba9874e --- /dev/null +++ b/helm/slurm-operator/tests/__snapshot__/webhook_rbac_test.yaml.snap @@ -0,0 +1,68 @@ +manifest should match snapshot: + 1: | + apiVersion: v1 + automountServiceAccountToken: true + kind: ServiceAccount + metadata: + labels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: slurm-operator-webhook + app.kubernetes.io/version: 1.2.3 + helm.sh/chart: slurm-operator-1.2.3 + name: slurm-operator-webhook + namespace: test-namespace + 2: | + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + labels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: slurm-operator-webhook + app.kubernetes.io/version: 1.2.3 + helm.sh/chart: slurm-operator-1.2.3 + name: slurm-operator-webhook + namespace: test-namespace + rules: + - apiGroups: + - slinky.slurm.net + resources: + - accountings + - controllers + - loginsets + - nodesets + - restapis + - tokens + verbs: + - create + - delete + - update + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + 3: | + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + labels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: slurm-operator-webhook + app.kubernetes.io/version: 1.2.3 + helm.sh/chart: slurm-operator-1.2.3 + name: slurm-operator-webhook + namespace: test-namespace + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: slurm-operator-webhook + subjects: + - kind: ServiceAccount + name: slurm-operator-webhook + namespace: test-namespace diff --git a/helm/slurm-operator/tests/__snapshot__/webhook_service_test.yaml.snap b/helm/slurm-operator/tests/__snapshot__/webhook_service_test.yaml.snap new file mode 100644 index 00000000..51c73862 --- /dev/null +++ b/helm/slurm-operator/tests/__snapshot__/webhook_service_test.yaml.snap @@ -0,0 +1,27 @@ +manifest should match snapshot: + 1: | + apiVersion: v1 + kind: Service + metadata: + labels: + app.kubernetes.io/instance: test-release + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: slurm-operator-webhook + app.kubernetes.io/version: 1.2.3 + helm.sh/chart: slurm-operator-1.2.3 + name: slurm-operator-webhook + namespace: test-namespace + spec: + ports: + - name: https + port: 443 + protocol: TCP + targetPort: 9443 + - name: health + port: 8081 + protocol: TCP + targetPort: 8081 + selector: + app.kubernetes.io/instance: test-release + app.kubernetes.io/name: slurm-operator-webhook + type: ClusterIP diff --git a/helm/slurm-operator/tests/operator_deployment_test.yaml b/helm/slurm-operator/tests/operator_deployment_test.yaml new file mode 100644 index 00000000..40ca8f4a --- /dev/null +++ b/helm/slurm-operator/tests/operator_deployment_test.yaml @@ -0,0 +1,103 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json +--- +suite: test operator deployment +templates: +- operator/deployment.yaml +chart: + version: 1.2.3 + appVersion: 1.2.3 +release: + name: test-release + namespace: test-namespace + +tests: +- it: manifest should match snapshot + asserts: + - matchSnapshot: {} + + +- it: should add affinity + set: + operator: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: arch + operator: In + values: + - x86_64 + asserts: + - equal: + path: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].values[0] + value: x86_64 + + +- it: should add tolerations + set: + operator: + tolerations: + - key: test + operator: Exists + effect: NoExecute + tolerationSeconds: 6000 + asserts: + - equal: + path: spec.template.spec.tolerations[0].key + value: test + + +- it: should set imagePullSecrets + set: + imagePullSecrets: + - name: test-docker-secret + asserts: + - equal: + path: spec.template.spec.imagePullSecrets[0].name + value: test-docker-secret + +- it: should set priorityClassName + set: + priorityClassName: test-priority-class + asserts: + - equal: + path: spec.template.spec.priorityClassName + value: test-priority-class + + +- it: should set replica count + set: + operator: + replicas: 42 + asserts: + - equal: + path: spec.replicas + value: 42 + +- it: should set namespace + set: + namespaceOverride: custom-namespace + asserts: + - equal: + path: metadata.namespace + value: custom-namespace + +- it: should set name + set: + nameOverride: custom-name + asserts: + - equal: + path: metadata.name + value: custom-name + + +- it: should set serviceAccount + set: + operator: + serviceAccount: + name: custom-service-account + asserts: + - equal: + path: spec.template.spec.serviceAccountName + value: custom-service-account \ No newline at end of file diff --git a/helm/slurm-operator/tests/operator_rbac_test.yaml b/helm/slurm-operator/tests/operator_rbac_test.yaml new file mode 100644 index 00000000..bcc88487 --- /dev/null +++ b/helm/slurm-operator/tests/operator_rbac_test.yaml @@ -0,0 +1,56 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json +--- +suite: test operator rbac +templates: +- operator/rbac.yaml +chart: + version: 1.2.3 + appVersion: 1.2.3 +release: + name: test-release + namespace: test-namespace + +tests: +- it: manifest should match snapshot + asserts: + - matchSnapshot: {} + +- it: should not render when disabled + set: + operator: + enabled: false + asserts: + - hasDocuments: + count: 0 + +- it: should not render when serviceAccount.create is false + set: + operator: + serviceAccount: + create: false + asserts: + - hasDocuments: + count: 0 + + + +- it: should set namespace + documentSelector: + path: kind + value: ServiceAccount + set: + namespaceOverride: custom-namespace + asserts: + - equal: + path: metadata.namespace + value: custom-namespace + +- it: should set serviceAccount name + set: + operator: + serviceAccount: + name: custom-service-account + asserts: + - equal: + path: metadata.name + value: custom-service-account \ No newline at end of file diff --git a/helm/slurm-operator/tests/operator_service_test.yaml b/helm/slurm-operator/tests/operator_service_test.yaml new file mode 100644 index 00000000..85931013 --- /dev/null +++ b/helm/slurm-operator/tests/operator_service_test.yaml @@ -0,0 +1,41 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json +--- +suite: test operator service +templates: +- operator/service.yaml +chart: + version: 1.2.3 + appVersion: 1.2.3 +release: + name: test-release + namespace: test-namespace + +tests: +- it: manifest should match snapshot + asserts: + - matchSnapshot: {} + +- it: should not render when disabled + set: + operator: + enabled: false + asserts: + - hasDocuments: + count: 0 + +- it: should set namespace + set: + namespaceOverride: custom-namespace + asserts: + - equal: + path: metadata.namespace + value: custom-namespace + + +- it: should set name + set: + nameOverride: custom-name + asserts: + - equal: + path: metadata.name + value: custom-name \ No newline at end of file diff --git a/helm/slurm-operator/tests/webhook_deployment_test.yaml b/helm/slurm-operator/tests/webhook_deployment_test.yaml new file mode 100644 index 00000000..2c69148e --- /dev/null +++ b/helm/slurm-operator/tests/webhook_deployment_test.yaml @@ -0,0 +1,103 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json +--- +suite: test webhook deployment +templates: +- webhook/deployment.yaml +chart: + version: 1.2.3 + appVersion: 1.2.3 +release: + name: test-release + namespace: test-namespace + +tests: +- it: manifest should match snapshot + asserts: + - matchSnapshot: {} + + +- it: should add affinity + set: + webhook: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: arch + operator: In + values: + - x86_64 + asserts: + - equal: + path: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].values[0] + value: x86_64 + + +- it: should add tolerations + set: + webhook: + tolerations: + - key: test + operator: Exists + effect: NoExecute + tolerationSeconds: 6000 + asserts: + - equal: + path: spec.template.spec.tolerations[0].key + value: test + + +- it: should set imagePullSecrets + set: + imagePullSecrets: + - name: test-docker-secret + asserts: + - equal: + path: spec.template.spec.imagePullSecrets[0].name + value: test-docker-secret + +- it: should set priorityClassName + set: + priorityClassName: test-priority-class + asserts: + - equal: + path: spec.template.spec.priorityClassName + value: test-priority-class + + +- it: should set replica count + set: + webhook: + replicas: 42 + asserts: + - equal: + path: spec.replicas + value: 42 + +- it: should set namespace + set: + namespaceOverride: custom-namespace + asserts: + - equal: + path: metadata.namespace + value: custom-namespace + +- it: should set name + set: + nameOverride: custom-name + asserts: + - equal: + path: metadata.name + value: custom-name-webhook + + +- it: should set serviceAccount + set: + webhook: + serviceAccount: + name: custom-service-account + asserts: + - equal: + path: spec.template.spec.serviceAccountName + value: custom-service-account \ No newline at end of file diff --git a/helm/slurm-operator/tests/webhook_rbac_test.yaml b/helm/slurm-operator/tests/webhook_rbac_test.yaml new file mode 100644 index 00000000..60ecf57e --- /dev/null +++ b/helm/slurm-operator/tests/webhook_rbac_test.yaml @@ -0,0 +1,59 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json +--- +suite: test webhook rbac +templates: +- webhook/rbac.yaml +chart: + version: 1.2.3 + appVersion: 1.2.3 +release: + name: test-release + namespace: test-namespace + +tests: +- it: manifest should match snapshot + asserts: + - matchSnapshot: {} + +- it: should not render when disabled + set: + webhook: + enabled: false + asserts: + - hasDocuments: + count: 0 + +- it: should not render when serviceAccount.create is false + set: + webhook: + serviceAccount: + create: false + asserts: + - hasDocuments: + count: 0 + + +- it: should set namespace + documentSelector: + path: kind + value: ServiceAccount + set: + namespaceOverride: custom-namespace + asserts: + - equal: + path: metadata.namespace + value: custom-namespace + + +- it: should set serviceAccount name + documentSelector: + path: kind + value: ServiceAccount + set: + webhook: + serviceAccount: + name: custom-service-account + asserts: + - equal: + path: metadata.name + value: custom-service-account \ No newline at end of file diff --git a/helm/slurm-operator/tests/webhook_service_test.yaml b/helm/slurm-operator/tests/webhook_service_test.yaml new file mode 100644 index 00000000..e40a9aa1 --- /dev/null +++ b/helm/slurm-operator/tests/webhook_service_test.yaml @@ -0,0 +1,41 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json +--- +suite: test webhook service +templates: +- webhook/service.yaml +chart: + version: 1.2.3 + appVersion: 1.2.3 +release: + name: test-release + namespace: test-namespace + +tests: +- it: manifest should match snapshot + asserts: + - matchSnapshot: {} + +- it: should not render when disabled + set: + webhook: + enabled: false + asserts: + - hasDocuments: + count: 0 + +- it: should set namespace + set: + namespaceOverride: custom-namespace + asserts: + - equal: + path: metadata.namespace + value: custom-namespace + + +- it: should set name + set: + nameOverride: custom-name + asserts: + - equal: + path: metadata.name + value: custom-name-webhook \ No newline at end of file