diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000000000000000000000000000000000..929023b75883833d9e99e2cf8ad00650d20d223a --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,252 @@ +pipeline { + agent { + node { + label 'ozgcloud-jenkins-build-agent' + } + } + + environment { + BLUE_OCEAN_URL = "https://jenkins.infra.ozg-cloud.systems/job/ozgcloud-app-elster-transfer/job/${env.BRANCH_NAME}/${env.BUILD_NUMBER}/" + RELEASE_REGEX = /\d+.\d+.\d+/ + SNAPSHOT_REGEX = /\d+.\d+.\d+-SNAPSHOT/ + FAILED_STAGE = "" + SH_SUCCESS_STATUS_CODE = 0 + } + + options { + timeout(time: 1, unit: 'HOURS') + disableConcurrentBuilds() + buildDiscarder(logRotator(numToKeepStr: '5')) + } + + stages { + stage('Check Version') { + steps { + script { + FAILED_STAGE = env.STAGE_NAME + def helmChartVersion = getHelmChartVersion() + + if(isReleaseBranch()){ + if ( !(helmChartVersion ==~ RELEASE_REGEX) ) { + error("Keine Release Version für Branch ${env.BRANCH_NAME}.") + } + } else { + if ( !(helmChartVersion ==~ SNAPSHOT_REGEX) ) { + error("Keine Snapshot Version für Branch ${env.BRANCH_NAME}.") + } + } + } + } + } + + stage('Test HelmChart') { + steps { + script { + FAILED_STAGE=env.STAGE_NAME + + sh "./run_helm_test.sh" + } + } + } + + stage('Build HelmChart') { + steps { + script { + FAILED_STAGE=env.STAGE_NAME + HELM_CHART_VERSION = generateHelmChartBuildVersion() + + dir('elster-transfer') { + sh "helm package --version=${HELM_CHART_VERSION} ." + } + } + } + } + + stage('Deploy HelmChart') { + steps { + script { + FAILED_STAGE=env.STAGE_NAME + + dir('elster-transfer') { + deployHelmChart("elster-transfer", HELM_CHART_VERSION) + } + } + } + } + + stage('Trigger Dev rollout') { + when { + branch 'master' + } + steps { + script { + FAILED_STAGE = env.STAGE_NAME + + cloneGitopsRepo() + + setNewDevVersion() + + pushDevGitopsRepo() + } + } + } + stage('Trigger Test rollout') { + when { + branch 'release' + } + + steps { + script { + FAILED_STAGE = env.STAGE_NAME + + cloneGitopsRepo() + + setNewTestVersion() + + pushTestGitopsRepo() + } + } + } + } + + post { + failure { + script { + if (isMasterBranch() || isReleaseBranch()) { + sendFailureMessage() + } + } + } + } +} + + +Boolean isReleaseBranch() { + return env.BRANCH_NAME == 'release' +} + +Boolean isMasterBranch() { + return env.BRANCH_NAME == 'master' +} + +void deployHelmChart(String helmChartName, String helmChartVersion) { + withCredentials([usernamePassword(credentialsId: 'jenkins-nexus-login', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]){ + if (isReleaseBranch()) { + result = sh script: '''curl -u $USERNAME:$PASSWORD https://nexus.ozg-sh.de/service/rest/v1/components?repository=ozg-base-apps -F file=@'''+helmChartName+'''-'''+helmChartVersion+'''.tgz''', returnStdout: true + } + else { + result = sh script: '''curl -u $USERNAME:$PASSWORD https://nexus.ozg-sh.de/service/rest/v1/components?repository=ozg-base-apps-snapshot -F file=@'''+helmChartName+'''-'''+helmChartVersion+'''.tgz''', returnStdout: true + } + + if (result != '') { + error(result) + } + } +} + +String generateHelmChartBuildVersion() { + def chartVersion = getHelmChartVersion() + + if (isMasterBranch()) { + chartVersion += "-${env.GIT_COMMIT.take(7)}" + } + else if (!isReleaseBranch()) { + chartVersion += "-${env.BRANCH_NAME}" + } + + return chartVersion.replaceAll("_", "-") +} + + +Void configureGit() { + final email = "jenkins@ozg-sh.de" + final name = "jenkins" + + dir("gitops") { + sh "git config user.email '${email}'" + sh "git config user.name '${name}'" + } +} + +Void cloneGitopsRepo() { + withCredentials([usernamePassword(credentialsId: 'jenkins-gitea-access-token', passwordVariable: 'TOKEN', usernameVariable: 'USER')]) { + sh 'git clone https://${USER}:${TOKEN}@git.ozg-sh.de/ozgcloud-devops/gitops.git' + } + + configureGit() +} + +Void setNewDevVersion() { + setNewElsterTransferGitopsVersion("dev") +} + +Void setNewTestVersion() { + setNewElsterTransferGitopsVersion("test") +} + +Void setNewElsterTransferGitopsVersion(String environment) { + dir("gitops") { + def envFile = "${environment}/application/values/elster-transfer-values.yaml" + def envVersions = readYaml file: envFile + + envVersions.elster_transfer.helm.version = HELM_CHART_VERSION + + writeYaml file: envFile, data: envVersions, overwrite: true + } +} + +Void pushDevGitopsRepo() { + pushNewGitopsVersion('dev') +} + +Void pushTestGitopsRepo() { + pushNewGitopsVersion('test') +} + +Void pushNewGitopsVersion(String environment) { + dir('gitops') { + if (!hasGitopsValuesFileChanged(environment)) { + return + } + + withCredentials([usernamePassword(credentialsId: 'jenkins-gitea-access-token', passwordVariable: 'TOKEN', usernameVariable: 'USER')]) { + sh "git add ${environment}/application/values/elster-transfer-values.yaml" + + sh "git commit -m 'jenkins rollout ${environment} elster-transfer version ${HELM_CHART_VERSION}'" + sh 'git push https://${USER}:${TOKEN}@git.ozg-sh.de/ozgcloud-devops/gitops.git' + } + } +} + +Boolean hasGitopsValuesFileChanged(String environment) { + return sh (script: "git status | grep '${environment}/application/values/elster-transfer-values.yaml'", returnStatus: true) == env.SH_SUCCESS_STATUS_CODE as Integer +} + +Void sendFailureMessage() { + def room = '' + def data = """{"msgtype":"m.text", \ + "body":"Elster-Transfer: Build Failed. Stage: ${FAILED_STAGE} Build-ID: ${env.BUILD_NUMBER} Link: ${BLUE_OCEAN_URL}", \ + "format": "org.matrix.custom.html", \ + "formatted_body":"Elster-Transfer: Build Failed. Stage: ${FAILED_STAGE} Build-ID: <a href='${BLUE_OCEAN_URL}'>${env.BUILD_NUMBER}</a>"}""" + + if (isMasterBranch()) { + room = "!iQPAvQIiRwRpNOszjw:matrix.ozg-sh.de" + } + else if (isReleaseBranch()) { + room = "!oWZpUGTFsxkJIYNfYg:matrix.ozg-sh.de" + } + + sh "curl -XPOST -H 'authorization: Bearer ${getElementAccessToken()}' -d '${data}' https://matrix.ozg-sh.de/_matrix/client/v3/rooms/$room/send/m.room.message" +} + +String getElementAccessToken() { + withCredentials([string(credentialsId: 'element-login-json', variable: 'LOGIN_JSON')]) { + return readJSON ( text: sh (script: '''curl -XPOST -d \"$LOGIN_JSON\" https://matrix.ozg-sh.de/_matrix/client/v3/login''', returnStdout: true)).access_token + } +} + +String getHelmChartVersion() { + def chartEnv = readYaml file: "elster-transfer/Chart.yaml" + + return chartEnv.version +} \ No newline at end of file diff --git a/elster-transfer/Chart.yaml b/elster-transfer/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f3e654bdb334f305e3e48fc243ec55c1df1b931f --- /dev/null +++ b/elster-transfer/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: elster-transfer +description: A Helm chart for Elster-Transfer +type: application +version: 0.1.0-SNAPSHOT +appVersion: "24.04.0" diff --git a/elster-transfer/lint-values.yaml b/elster-transfer/lint-values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..af06854a7559b44c9c85df9fed88c52e6d61a974 --- /dev/null +++ b/elster-transfer/lint-values.yaml @@ -0,0 +1,4 @@ +imagePullSecret: ozgcloud-image-pull-secret + +networkPolicy: + dnsServerNamespace: test-dns-namespace \ No newline at end of file diff --git a/elster-transfer/templates/_helpers.tpl b/elster-transfer/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..3a13fe3d710ea586853571c198c99d941661b23e --- /dev/null +++ b/elster-transfer/templates/_helpers.tpl @@ -0,0 +1,55 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* Chart: Name + Version */}} +{{- define "app.chart" -}} +{{- if gt (len (printf "%s-%s" .Chart.Name .Chart.Version)) 63 -}} +{{- fail (printf ".Chart.Name-.Chart.Version %s-%s ist zu lang (max. 63 Zeichen)" .Chart.Name .Chart.Version) -}} +{{- end -}} +{{ printf "%s-%s" .Chart.Name .Chart.Version }} +{{- end -}} + +{{/* Managed-by -> On Helm, this value is always Helm */}} +{{- define "app.managedBy" -}} +{{- if gt (len (.Release.Service)) 63 -}} +{{- fail (printf ".Release.Service %s ist zu lang (max. 63 Zeichen)" .Release.Service) -}} +{{- end -}} +{{ printf "%s" .Release.Service }} +{{- end -}} + +{{/* Default Labels: Helm recommended best-practice labels https://helm.sh/docs/chart_best_practices/labels/ */}} +{{- define "app.defaultLabels" }} +app.kubernetes.io/instance: elster-transfer +app.kubernetes.io/managed-by: {{ include "app.managedBy" . }} +app.kubernetes.io/name: {{ .Release.Name }} +app.kubernetes.io/namespace: {{ .Release.Namespace }} +app.kubernetes.io/part-of: ozgcloud +app.kubernetes.io/version: {{ .Chart.Version }} +helm.sh/chart: {{ include "app.chart" . }} +{{- end -}} + +{{- define "app.matchLabels" }} +app.kubernetes.io/name: {{ .Release.Name }} +app.kubernetes.io/namespace: {{ .Release.Namespace }} +{{- end -}} + +{{- define "app.serviceAccountName" -}} +{{ printf "%s" ( (.Values.serviceAccount).name | default "elster-transfer-service-account" ) }} +{{- end -}} + +{{- define "app.getCustomList" -}} +{{- with (.Values.env).customList -}} +{{- if kindIs "map" . -}} +{{ include "app.dictToList" . }} +{{- else if kindIs "slice" . -}} +{{ . | toYaml }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{- define "app.dictToList" -}} +{{- $customList := list -}} +{{- range $key, $value := . -}} +{{- $customList = append $customList (dict "name" $key "value" $value) }} +{{- end -}} +{{- $customList | toYaml -}} +{{- end -}} \ No newline at end of file diff --git a/elster-transfer/templates/deployment.yaml b/elster-transfer/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5bb04063b5a784c2d9caea016b1c835a48ac1bbe --- /dev/null +++ b/elster-transfer/templates/deployment.yaml @@ -0,0 +1,83 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "app.defaultLabels" . | indent 4 }} +spec: + progressDeadlineSeconds: 600 + replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: 10 + selector: + matchLabels: + {{- include "app.matchLabels" . | indent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "app.defaultLabels" . | indent 8 }} + component: elster-transfer + spec: + {{- if (.Values.serviceAccount).create }} + serviceAccountName: {{ include "app.serviceAccountName" . }} + {{- end }} + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/name: {{ .Release.Name }} + containers: + - image: "{{ .Values.image.repo }}/{{ .Values.image.name }}:{{ .Values.image.tag }}" + env: + {{- with include "app.getCustomList" . }} +{{ . | indent 8 }} + {{- end }} + imagePullPolicy: Always + name: etr + ports: + - containerPort: 8081 + name: etr-port + protocol: TCP + resources: + {{- with .Values.resources }} +{{ toYaml . | indent 10 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + privileged: false + readOnlyRootFilesystem: false + runAsNonRoot: true + {{- with (.Values.securityContext).runAsUser }} + runAsUser: {{ . }} + {{- end }} + {{- with (.Values.securityContext).runAsGroup }} + runAsGroup: {{ . }} + {{- end }} + {{- with (.Values.securityContext).capabilities }} + capabilities: +{{ toYaml . | indent 12 }} + {{- end }} + stdin: true + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + tty: true + volumeMounts: + - name: etr-home + mountPath: "/home/etr" + volumes: + - name: etr-home + persistentVolumeClaim: + claimName: {{ .Release.Name }}-home-pvc + + imagePullSecrets: + - name: {{ required "imagePullSecret must be set" .Values.imagePullSecret }} + restartPolicy: Always + {{- with .Values.podSecurityContext }} + securityContext: +{{ toYaml . | indent 8 }} + {{- end }} + terminationGracePeriodSeconds: 30 diff --git a/elster-transfer/templates/etr_home_pvc.yaml b/elster-transfer/templates/etr_home_pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4ba0373f65cd070703817f43d2851feaa5c01864 --- /dev/null +++ b/elster-transfer/templates/etr_home_pvc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Release.Name }}-home-pvc + namespace: {{ .Release.Namespace }} +spec: + storageClassName: {{ (.Values.storage).className | default "ssd-retain" }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ (.Values.storage).size | default "20Gi" }} \ No newline at end of file diff --git a/elster-transfer/templates/network_policy.yaml b/elster-transfer/templates/network_policy.yaml new file mode 100644 index 0000000000000000000000000000000000000000..35cc5185dbd4edf14cf84ef3c21c679de28e532a --- /dev/null +++ b/elster-transfer/templates/network_policy.yaml @@ -0,0 +1,49 @@ +{{- if not (.Values.networkPolicy).disabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ .Release.Name }}-network-policy + namespace: {{ .Release.Namespace }} +spec: + podSelector: + matchLabels: + component: elster-transfer + policyTypes: + - Ingress + - Egress + ingress: + - ports: + - port: 8081 + from: + - namespaceSelector: {} + podSelector: + matchLabels: + component: vorgang-manager +{{- with (.Values.networkPolicy).additionalIngressConfigLocal }} +{{ toYaml . | indent 2 }} +{{- end }} +{{- with (.Values.networkPolicy).additionalIngressConfigGlobal }} +{{ toYaml . | indent 2 }} +{{- end }} + egress: + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: {{ required "networkPolicy.dnsServerNamespace must be set" (.Values.networkPolicy).dnsServerNamespace }} + ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + - port: 5353 + protocol: UDP + - port: 5353 + protocol: TCP +{{- with (.Values.networkPolicy).additionalEgressConfigLocal }} +{{ toYaml . | indent 2 }} +{{- end }} +{{- with (.Values.networkPolicy).additionalEgressConfigGlobal }} +{{ toYaml . | indent 2 }} +{{- end }} + +{{- end }} \ No newline at end of file diff --git a/elster-transfer/templates/service.yaml b/elster-transfer/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..91d6d0b780158c09e0e4a8baa2fd87e564c6de69 --- /dev/null +++ b/elster-transfer/templates/service.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "app.defaultLabels" . | indent 4 }} + component: elster-transfer +spec: + type: ClusterIP + ports: + - name: etr-port + port: 8081 + protocol: TCP + selector: + {{- include "app.matchLabels" . | indent 4 }} + component: elster-transfer diff --git a/elster-transfer/templates/service_account.yaml b/elster-transfer/templates/service_account.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e391b60b64fa865ffa5ab9ec4364e060be1fc0ff --- /dev/null +++ b/elster-transfer/templates/service_account.yaml @@ -0,0 +1,7 @@ +{{- if (.Values.serviceAccount).create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "app.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} \ No newline at end of file diff --git a/elster-transfer/unit-tests/deployment_basic_spec_test.yaml b/elster-transfer/unit-tests/deployment_basic_spec_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b54c2edc58465b33ad263cdc742883b7f157321f --- /dev/null +++ b/elster-transfer/unit-tests/deployment_basic_spec_test.yaml @@ -0,0 +1,85 @@ +suite: test deployment general values +release: + name: etr + namespace: by-helm-test +templates: + - templates/deployment.yaml +set: + imagePullSecret: test-image-pull-secret +tests: + - it: should have apiVersion + asserts: + - isAPIVersion: + of: "apps/v1" + - isKind: + of: Deployment + + - it: should have deployment metadata + asserts: + - equal: + path: metadata.name + value: etr + - equal: + path: metadata.namespace + value: by-helm-test + - equal: + path: metadata.labels["app.kubernetes.io/instance"] + value: elster-transfer + - equal: + path: metadata.labels["app.kubernetes.io/managed-by"] + value: Helm + - equal: + path: metadata.labels["app.kubernetes.io/name"] + value: etr + - equal: + path: metadata.labels["app.kubernetes.io/namespace"] + value: by-helm-test + - equal: + path: metadata.labels["app.kubernetes.io/part-of"] + value: ozgcloud + + - it: should have deyployment general spec values + asserts: + - equal: + path: spec.progressDeadlineSeconds + value: 600 + - equal: + path: spec.replicas + value: 1 + - equal: + path: spec.revisionHistoryLimit + value: 10 + + - it: should have deployment strategy values + asserts: + - equal: + path: spec.strategy + value: + type: Recreate + + - it: should have deployment selector + asserts: + - equal: + path: spec.selector.matchLabels["app.kubernetes.io/name"] + value: etr + - equal: + path: spec.selector.matchLabels["app.kubernetes.io/namespace"] + value: by-helm-test + + - it: should have template metadata + asserts: + - equal: + path: spec.template.metadata.labels["app.kubernetes.io/name"] + value: etr + - equal: + path: spec.template.metadata.labels["app.kubernetes.io/namespace"] + value: by-helm-test + - equal: + path: spec.template.metadata.labels.component + value: elster-transfer + + - it: should have default image + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: docker.ozg-sh.de/etr:24.04.0 \ No newline at end of file diff --git a/elster-transfer/unit-tests/deployment_container_security_context_test.yaml b/elster-transfer/unit-tests/deployment_container_security_context_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9c9230e8999f608dc121432d62870be10303eedd --- /dev/null +++ b/elster-transfer/unit-tests/deployment_container_security_context_test.yaml @@ -0,0 +1,64 @@ +suite: test deployment security context +release: + name: etr + namespace: by-helm-test +templates: + - templates/deployment.yaml +set: + imagePullSecret: test-image-pull-secret +tests: + - it: check default values + asserts: + - equal: + path: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation + value: false + - equal: + path: spec.template.spec.containers[0].securityContext.privileged + value: false + - equal: + path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem + value: false + - equal: + path: spec.template.spec.containers[0].securityContext.runAsNonRoot + value: true + - isNull: + path: spec.template.spec.containers[0].securityContext.runAsUser + - isNull: + path: spec.template.spec.containers[0].securityContext.runAsGroup + - isNull: + path: spec.template.spec.containers[0].securityContext.capabilities + - isNull: + path: spec.template.spec.securityContext.fsGroup + - it: check runAsUser + set: + securityContext.runAsUser: 1000 + asserts: + - equal: + path: spec.template.spec.containers[0].securityContext.runAsUser + value: 1000 + - it: check runAsGroup + set: + securityContext.runAsGroup: 1000 + asserts: + - equal: + path: spec.template.spec.containers[0].securityContext.runAsGroup + value: 1000 + - it: check fsGroup + set: + podSecurityContext.fsGroup: 1000 + asserts: + - equal: + path: spec.template.spec.securityContext.fsGroup + value: 1000 + - it: check capabilities + set: + securityContext: + capabilities: + drop: + - ALL + asserts: + - equal: + path: spec.template.spec.containers[0].securityContext.capabilities + value: + drop: + - ALL \ No newline at end of file diff --git a/elster-transfer/unit-tests/deployment_env_test.yaml b/elster-transfer/unit-tests/deployment_env_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..37a67d1c0e2b38c6e305c4adccd0a71356079352 --- /dev/null +++ b/elster-transfer/unit-tests/deployment_env_test.yaml @@ -0,0 +1,48 @@ +suite: test environments +release: + name: etr + namespace: by-helm-test +templates: + - templates/deployment.yaml +set: + imagePullSecret: test-image-pull-secret +tests: + - it: check customList as list + set: + env.customList: + - name: my_test_environment_name + value: "A test value" + - name: test_environment + value: "B test value" + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: my_test_environment_name + value: "A test value" + - contains: + path: spec.template.spec.containers[0].env + content: + name: test_environment + value: "B test value" + - it: check customList as dict + set: + env.customList: + my_test_environment_name: "A test value" + test_environment: "B test value" + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: my_test_environment_name + value: "A test value" + - contains: + path: spec.template.spec.containers[0].env + content: + name: test_environment + value: "B test value" + + - it: check env is not set by default + asserts: + - isNullOrEmpty: + path: spec.template.spec.containers[0].env diff --git a/elster-transfer/unit-tests/deployment_imagepull_secret_test.yaml b/elster-transfer/unit-tests/deployment_imagepull_secret_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..066c007ce5f2a3d6e06a2b609ee11a53548a26f5 --- /dev/null +++ b/elster-transfer/unit-tests/deployment_imagepull_secret_test.yaml @@ -0,0 +1,18 @@ +suite: test deployment image pull secret +release: + name: etr + namespace: by-helm-test +templates: + - templates/deployment.yaml +tests: + - it: should set the imagePull secret + set: + imagePullSecret: image-pull-secret + asserts: + - equal: + path: spec.template.spec.imagePullSecrets[0].name + value: image-pull-secret + - it: should fail if the imagePull secret not set + asserts: + - failedTemplate: + errorMessage: imagePullSecret must be set \ No newline at end of file diff --git a/elster-transfer/unit-tests/deployment_resources_test.yaml b/elster-transfer/unit-tests/deployment_resources_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c845a2c7c00cc9adee1b0fa292986bba71efddbb --- /dev/null +++ b/elster-transfer/unit-tests/deployment_resources_test.yaml @@ -0,0 +1,36 @@ +suite: test deployment resources +release: + name: etr + namespace: by-helm-test +templates: + - templates/deployment.yaml +set: + imagePullSecret: test-image-pull-secret +tests: + - it: test resources + set: + resources: + limits: + cpu: 11m + memory: 22Mi + requests: + cpu: 33m + memory: 44Mi + asserts: + - equal: + path: spec.template.spec.containers[0].resources.limits.cpu + value: 11m + - equal: + path: spec.template.spec.containers[0].resources.limits.memory + value: 22Mi + - equal: + path: spec.template.spec.containers[0].resources.requests.cpu + value: 33m + - equal: + path: spec.template.spec.containers[0].resources.requests.memory + value: 44Mi + - it: no resources defined by default + asserts: + - isEmpty: + path: spec.template.spec.containers[0].resources + diff --git a/elster-transfer/unit-tests/deployment_service_account_test.yaml b/elster-transfer/unit-tests/deployment_service_account_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6be510a0c8aac61d8bd6e85c83fe5ddc5c4f9eb6 --- /dev/null +++ b/elster-transfer/unit-tests/deployment_service_account_test.yaml @@ -0,0 +1,30 @@ +suite: deployment service account +release: + name: etr + namespace: by-helm-test +templates: + - templates/deployment.yaml +set: + imagePullSecret: test-image-pull-secret +tests: + - it: should use service account with default name + set: + serviceAccount: + create: true + asserts: + - equal: + path: spec.template.spec.serviceAccountName + value: elster-transfer-service-account + - it: should use service account with name + set: + serviceAccount: + create: true + name: helm-service-account + asserts: + - equal: + path: spec.template.spec.serviceAccountName + value: helm-service-account + - it: should use default service account + asserts: + - isNull: + path: spec.template.spec.serviceAccountName \ No newline at end of file diff --git a/elster-transfer/unit-tests/deployment_volume_mount_test.yaml b/elster-transfer/unit-tests/deployment_volume_mount_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..82805822b7cc51520716ec8e10b63b0a791d5b09 --- /dev/null +++ b/elster-transfer/unit-tests/deployment_volume_mount_test.yaml @@ -0,0 +1,24 @@ +suite: deployment volume mount +release: + name: etr + namespace: by-helm-test +templates: + - templates/deployment.yaml +set: + imagePullSecret: test-image-pull-secret +tests: + - it: should have etr-home volume mount + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: etr-home + mountPath: "/home/etr" + - it: should have etr-home volume + asserts: + - contains: + path: spec.template.spec.volumes + content: + name: etr-home + persistentVolumeClaim: + claimName: etr-home-pvc \ No newline at end of file diff --git a/elster-transfer/unit-tests/etr_home_pvc_test.yaml b/elster-transfer/unit-tests/etr_home_pvc_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fb125ac7c8f2e7c982d3a5ada57eeb2d731f436a --- /dev/null +++ b/elster-transfer/unit-tests/etr_home_pvc_test.yaml @@ -0,0 +1,57 @@ +suite: test pvc +release: + name: etr + namespace: by-helm-test +templates: + - templates/etr_home_pvc.yaml +tests: + - it: should have correct apiVersion + asserts: + - isAPIVersion: + of: v1 + - isKind: + of: PersistentVolumeClaim + + - it: should have metadata + asserts: + - equal: + path: metadata.name + value: etr-home-pvc + - equal: + path: metadata.namespace + value: by-helm-test + + - it: should default storageClassName + asserts: + - equal: + path: spec.storageClassName + value: ssd-retain + + - it: should set storageClassName + set: + storage.className: ssd-delete + asserts: + - equal: + path: spec.storageClassName + value: ssd-delete + + - it: should have accessMode + asserts: + - equal: + path: spec.accessModes + value: + - ReadWriteOnce + + - it: should have default storage size + asserts: + - equal: + path: spec.resources.requests.storage + value: 20Gi + + - it: should set storage size + set: + storage.size: 10Gi + asserts: + - equal: + path: spec.resources.requests.storage + value: 10Gi diff --git a/elster-transfer/unit-tests/network_policy_test.yaml b/elster-transfer/unit-tests/network_policy_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c894864df61555eea45cb4080829ba8602fb7ad5 --- /dev/null +++ b/elster-transfer/unit-tests/network_policy_test.yaml @@ -0,0 +1,194 @@ +suite: network policy test +release: + name: etr + namespace: by-helm-test +templates: + - templates/network_policy.yaml +tests: + - it: should match apiVersion + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace + asserts: + - isAPIVersion: + of: networking.k8s.io/v1 + - isKind: + of: NetworkPolicy + + - it: validate metadata + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace + asserts: + - equal: + path: metadata + value: + name: etr-network-policy + namespace: by-helm-test + + - it: validate podSelector + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace + asserts: + - equal: + path: spec.podSelector + value: + matchLabels: + component: elster-transfer + + - it: validate policyTypes + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace + asserts: + - equal: + path: spec.policyTypes + value: + - Ingress + - Egress + + - it: should add ingress rule for vorgang-manager + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace + asserts: + - equal: + path: spec.ingress + value: + - ports: + - port: 8081 + from: + - namespaceSelector: {} + podSelector: + matchLabels: + component: vorgang-manager + + - it: should add egress rule to dns service + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace + asserts: + - equal: + path: spec.egress + value: + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: test-dns-namespace + ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + - port: 5353 + protocol: UDP + - port: 5353 + protocol: TCP + + - it: test network policy disabled + set: + networkPolicy: + disabled: true + dnsServerNamespace: test-dns-namespace + asserts: + - hasDocuments: + count: 0 + + - it: test network policy unset should be disabled + set: + networkPolicy: + disabled: false + dnsServerNamespace: test-dns-namespace + asserts: + - hasDocuments: + count: 1 + + + - it: add ingress rule local by values + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace + additionalIngressConfigGlobal: + - from: + - podSelector: + matchLabels: + component: client2 + asserts: + - contains: + path: spec.ingress + content: + from: + - podSelector: + matchLabels: + component: client2 + - it: add ingress rule global by values + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace + additionalIngressConfigLocal: + - from: + - podSelector: + matchLabels: + component: client2 + asserts: + - contains: + path: spec.ingress + content: + from: + - podSelector: + matchLabels: + component: client2 + + - it: add egress rules local by values + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace + additionalEgressConfigGlobal: + - to: + - ipBlock: + cidr: 1.2.3.4/32 + - to: + - podSelector: + matchLabels: + component: ozg-testservice + ports: + - port: 12345 + protocol: TCP + asserts: + - contains: + path: spec.egress + content: + to: + - ipBlock: + cidr: 1.2.3.4/32 + - contains: + path: spec.egress + content: + to: + - podSelector: + matchLabels: + component: ozg-testservice + ports: + - port: 12345 + protocol: TCP + - it: add egress rules global by values + set: + networkPolicy: + dnsServerNamespace: test-dns-namespace + additionalEgressConfigLocal: + - to: + - ipBlock: + cidr: 1.2.3.4/32 + - to: + - podSelector: + matchLabels: + additionalEgressConfigLocal: yes + asserts: + - contains: + path: spec.egress + content: + to: + - podSelector: + matchLabels: + additionalEgressConfigLocal: yes \ No newline at end of file diff --git a/elster-transfer/unit-tests/service_account_test.yaml b/elster-transfer/unit-tests/service_account_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cad4d5e0d5ee31854d7a393152c6f3a2c2f697bf --- /dev/null +++ b/elster-transfer/unit-tests/service_account_test.yaml @@ -0,0 +1,40 @@ +suite: test service account +release: + name: etr + namespace: by-helm-test +templates: + - templates/service_account.yaml +tests: + - it: should create service account with default name + set: + serviceAccount: + create: true + asserts: + - isKind: + of: ServiceAccount + - isAPIVersion: + of: v1 + - equal: + path: metadata.name + value: elster-transfer-service-account + - equal: + path: metadata.namespace + value: by-helm-test + - it: should create service account with name + set: + serviceAccount: + create: true + name: helm-service-account + asserts: + - isKind: + of: ServiceAccount + - equal: + path: metadata.name + value: helm-service-account + - equal: + path: metadata.namespace + value: by-helm-test + - it: should not create service account + asserts: + - hasDocuments: + count: 0 \ No newline at end of file diff --git a/elster-transfer/unit-tests/service_test.yaml b/elster-transfer/unit-tests/service_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..236b245f3a1b0bca442a81d7f6ccb645366ada30 --- /dev/null +++ b/elster-transfer/unit-tests/service_test.yaml @@ -0,0 +1,69 @@ +suite: test service +release: + name: etr + namespace: by-helm-test +templates: + - templates/service.yaml +tests: + - it: should have correct apiVersion + asserts: + - isKind: + of: Service + - isAPIVersion: + of: v1 + + - it: should have metadata + asserts: + - equal: + path: metadata.name + value: etr + - equal: + path: metadata.namespace + value: by-helm-test + - equal: + path: metadata.labels["component"] + value: elster-transfer + - equal: + path: metadata.labels["app.kubernetes.io/instance"] + value: elster-transfer + - equal: + path: metadata.labels["app.kubernetes.io/managed-by"] + value: Helm + - equal: + path: metadata.labels["app.kubernetes.io/name"] + value: etr + - equal: + path: metadata.labels["app.kubernetes.io/namespace"] + value: by-helm-test + - equal: + path: metadata.labels["app.kubernetes.io/part-of"] + value: ozgcloud + + - it: should be of type ClusterIP + asserts: + - equal: + path: spec.type + value: ClusterIP + + - it: ports should contain the etr port + asserts: + - contains: + path: spec.ports + content: + name: etr-port + port: 8081 + protocol: TCP + count: 1 + any: true + + - it: should have selector + asserts: + - equal: + path: spec.selector["component"] + value: elster-transfer + - equal: + path: spec.selector["app.kubernetes.io/name"] + value: etr + - equal: + path: spec.selector["app.kubernetes.io/namespace"] + value: by-helm-test diff --git a/elster-transfer/values.yaml b/elster-transfer/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4cf57a21745aa2181e6a00c7b3e555a79f6d4452 --- /dev/null +++ b/elster-transfer/values.yaml @@ -0,0 +1,6 @@ +replicaCount: 1 + +image: + repo: docker.ozg-sh.de + name: etr + tag: "24.04.0" \ No newline at end of file diff --git a/run_helm_test.sh b/run_helm_test.sh new file mode 100755 index 0000000000000000000000000000000000000000..f62dcabe3f432a2620fe57cde5242b2ccffaff4f --- /dev/null +++ b/run_helm_test.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e +set -x + +helm template ./elster-transfer -f elster-transfer/lint-values.yaml + +helm lint -f elster-transfer/lint-values.yaml ./elster-transfer +helm unittest -f "unit-tests/**/*.yaml" ./elster-transfer \ No newline at end of file