suite: Jenkins Controller release: name: my-release namespace: my-namespace templates: - jenkins-controller-statefulset.yaml - config.yaml tests: - it: default values template: jenkins-controller-statefulset.yaml asserts: - isKind: of: StatefulSet - equal: path: apiVersion value: apps/v1beta1 - equal: path: metadata.name value: my-release-jenkins - equal: path: metadata.namespace value: my-namespace - matchRegex: path: metadata.labels.helm\.sh/chart pattern: ^jenkins- - isNull: path: metadata.annotations - equal: path: spec.replicas value: 1 - equal: path: spec.selector value: matchLabels: app.kubernetes.io/component: jenkins-controller app.kubernetes.io/instance: my-release - equal: path: spec value: serviceName: my-release-jenkins replicas: 1 selector: matchLabels: app.kubernetes.io/component: jenkins-controller app.kubernetes.io/instance: my-release template: metadata: annotations: checksum/config: d00c6603a9397bc202be5072a81644630af27fe47c7e542ea6b066073458af83 labels: app.kubernetes.io/component: jenkins-controller app.kubernetes.io/instance: my-release app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: jenkins spec: containers: - args: - --httpPort=8080 env: - name: SECRETS value: /run/secrets/additional - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: JAVA_OPTS value: "-Dcasc.reload.token=$(POD_NAME) " - name: JENKINS_OPTS value: "--webroot=/var/jenkins_cache/war " - name: JENKINS_SLAVE_AGENT_PORT value: "50000" - name: CASC_JENKINS_CONFIG value: /var/jenkins_home/casc_configs image: jenkins/jenkins:2.375.1-jdk11 imagePullPolicy: Always securityContext: runAsUser: 1000 runAsGroup: 1000 readOnlyRootFilesystem: true allowPrivilegeEscalation: false livenessProbe: failureThreshold: 5 httpGet: path: /login port: http periodSeconds: 10 timeoutSeconds: 5 name: jenkins ports: - containerPort: 8080 name: http - containerPort: 50000 name: agent-listener readinessProbe: failureThreshold: 3 httpGet: path: /login port: http periodSeconds: 10 timeoutSeconds: 5 resources: limits: cpu: 2000m memory: 4096Mi requests: cpu: 50m memory: 256Mi startupProbe: httpGet: path: "/login" port: http periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 12 volumeMounts: - mountPath: /var/jenkins_home name: jenkins-home readOnly: false - mountPath: /var/jenkins_config name: jenkins-config readOnly: true - mountPath: /usr/share/jenkins/ref/plugins/ name: plugin-dir readOnly: false - mountPath: /var/jenkins_home/casc_configs name: sc-config-volume - mountPath: /run/secrets/additional name: jenkins-secrets readOnly: true - mountPath: /var/jenkins_cache name: jenkins-cache - mountPath: /tmp name: tmp-volume - env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: LABEL value: my-release-jenkins-jenkins-config - name: FOLDER value: /var/jenkins_home/casc_configs - name: NAMESPACE value: my-namespace - name: REQ_URL value: http://localhost:8080/reload-configuration-as-code/?casc-reload-token=$(POD_NAME) - name: REQ_METHOD value: POST - name: REQ_RETRY_CONNECT value: "10" image: kiwigrid/k8s-sidecar:1.15.0 imagePullPolicy: IfNotPresent securityContext: readOnlyRootFilesystem: true allowPrivilegeEscalation: false name: config-reload resources: {} volumeMounts: - mountPath: /var/jenkins_home/casc_configs name: sc-config-volume - mountPath: /var/jenkins_home name: jenkins-home initContainers: - command: - sh - /var/jenkins_config/apply_config.sh image: jenkins/jenkins:2.375.1-jdk11 imagePullPolicy: Always securityContext: runAsUser: 1000 runAsGroup: 1000 readOnlyRootFilesystem: true allowPrivilegeEscalation: false name: init resources: limits: cpu: 2000m memory: 4096Mi requests: cpu: 50m memory: 256Mi volumeMounts: - mountPath: /var/jenkins_home name: jenkins-home - mountPath: /var/jenkins_config name: jenkins-config - mountPath: /usr/share/jenkins/ref/plugins name: plugins - mountPath: /var/jenkins_plugins name: plugin-dir - mountPath: /tmp name: tmp-volume securityContext: fsGroup: 1000 runAsUser: 1000 runAsNonRoot: true serviceAccountName: my-release-jenkins volumes: - emptyDir: {} name: plugins - configMap: name: my-release-jenkins name: jenkins-config - emptyDir: {} name: plugin-dir - name: jenkins-secrets projected: sources: - secret: name: my-release-jenkins items: - key: jenkins-admin-user path: chart-admin-username - key: jenkins-admin-password path: chart-admin-password - emptyDir: {} name: jenkins-cache - name: jenkins-home persistentVolumeClaim: claimName: my-release-jenkins - emptyDir: {} name: sc-config-volume - emptyDir: {} name: tmp-volume - it: test different values template: jenkins-controller-statefulset.yaml capabilities: apiVersions: - scheduling.k8s.io/v1beta1 set: controller: statefulSetAnnotations: my-annotation: value schedulerName: my-scheduler nodeSelector: nodeLabel: value tolerations: - key: "key" operator: "Equal" value: "value" effect: "NoSchedule" affinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - S1 topologyKey: failure-domain.beta.kubernetes.io/zone terminationGracePeriodSeconds: 120 priorityClassName: important runAsUser: 2000 fsGroup: 4000 securityContextCapabilities: drop: - NET_RAW hostNetworking: true terminationMessagePath: /tmp/termination-log-diff terminationMessagePolicy: FallbackToLogsOnError hostAliases: - ip: 192.168.50.50 hostnames: - something.local updateStrategy: type: OnDelete serviceAccount.name: my-serviceaccount asserts: - equal: path: metadata.annotations value: my-annotation: value - equal: path: spec.template.spec.schedulerName value: my-scheduler - equal: path: spec.template.spec.nodeSelector value: nodeLabel: value - equal: path: spec.template.spec.tolerations value: - key: "key" operator: "Equal" value: "value" effect: "NoSchedule" - equal: path: spec.template.spec.affinity value: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - S1 topologyKey: failure-domain.beta.kubernetes.io/zone - equal: path: spec.template.spec.terminationGracePeriodSeconds value: 120 - equal: path: spec.template.spec.priorityClassName value: important - equal: path: spec.template.spec.securityContext value: runAsUser: 2000 fsGroup: 4000 runAsNonRoot: true capabilities: drop: - NET_RAW - equal: path: spec.template.spec.serviceAccountName value: my-serviceaccount - equal: path: spec.template.spec.hostNetwork value: true - equal: path: spec.template.spec.containers[0].terminationMessagePath value: /tmp/termination-log-diff - equal: path: spec.template.spec.containers[0].terminationMessagePolicy value: FallbackToLogsOnError - equal: path: spec.template.spec.dnsPolicy value: ClusterFirstWithHostNet - equal: path: spec.template.spec.hostAliases value: - ip: 192.168.50.50 hostnames: - something.local - equal: path: spec.updateStrategy.type value: OnDelete - it: configure image tag template: jenkins-controller-statefulset.yaml set: controller.tag: 2.249.1-slim controller.imagePullPolicy: IfNotPresent asserts: - equal: path: spec.template.spec.containers[0].image value: jenkins/jenkins:2.249.1-slim - equal: path: spec.template.spec.containers[0].imagePullPolicy value: IfNotPresent - it: configure image tag label template: jenkins-controller-statefulset.yaml set: controller.tagLabel: alpine asserts: - equal: path: spec.template.spec.containers[0].image value: jenkins/jenkins:2.375.1-alpine - it: configure empty image tag label template: jenkins-controller-statefulset.yaml set: controller.tagLabel: asserts: - equal: path: spec.template.spec.containers[0].image value: jenkins/jenkins:2.375.1 - it: custom image template: jenkins-controller-statefulset.yaml set: controller: image: registry/image tag: my-tag javaOpts: -Dio.jenkins.plugins.kubernetes.disableNoDelayProvisioning=true asserts: - equal: path: spec.template.spec.containers[0].image value: registry/image:my-tag - contains: path: spec.template.spec.containers[0].env content: name: JAVA_OPTS value: >- -Dcasc.reload.token=$(POD_NAME) -Dio.jenkins.plugins.kubernetes.disableNoDelayProvisioning=true - it: disable helm.sh label template: jenkins-controller-statefulset.yaml set: renderHelmLabels: false asserts: - equal: path: metadata.labels value: app.kubernetes.io/component: jenkins-controller app.kubernetes.io/instance: my-release app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: jenkins - it: java & jenkins opts with quotes template: jenkins-controller-statefulset.yaml set: controller: javaOpts: >- -Dhudson.model.DirectoryBrowserSupport.CSP="default-src 'self';" jenkinsOpts: >- -Dtest="custom: 'true'" asserts: - contains: path: spec.template.spec.containers[0].env content: name: JAVA_OPTS value: >- -Dcasc.reload.token=$(POD_NAME) -Dhudson.model.DirectoryBrowserSupport.CSP="default-src 'self';" - contains: path: spec.template.spec.containers[0].env content: name: JENKINS_OPTS value: >- --webroot=/var/jenkins_cache/war -Dtest="custom: 'true'" - it: test empty controller.podSecurityContextOverride template: jenkins-controller-statefulset.yaml set: controller: podSecurityContextOverride: {} asserts: - equal: path: spec.template.spec.securityContext value: {} - it: test controller.podSecurityContextOverride template: jenkins-controller-statefulset.yaml set: controller: podSecurityContextOverride: runAsNonRoot: true runAsUser: 4444 supplementalGroups: [5555] asserts: - equal: path: spec.template.spec.securityContext value: runAsNonRoot: true runAsUser: 4444 supplementalGroups: - 5555 - it: test 2 additional secrets template: jenkins-controller-statefulset.yaml set: controller.additionalSecrets: - name: something value: secret - name: anotherthing value: anothersecret asserts: - equal: path: spec.template.spec.containers[0].volumeMounts[4] value: mountPath: /run/secrets/additional name: jenkins-secrets readOnly: true - equal: path: spec.template.spec.volumes[3] value: name: jenkins-secrets projected: sources: - secret: name: my-release-jenkins-additional-secrets - secret: name: my-release-jenkins items: - key: jenkins-admin-user path: chart-admin-username - key: jenkins-admin-password path: chart-admin-password - it: test existing secret without additionalExistingSecrets template: jenkins-controller-statefulset.yaml set: controller.existingSecret: my-exisiting-credentials asserts: - equal: path: spec.template.spec.containers[0].volumeMounts[4] value: mountPath: /run/secrets/additional name: jenkins-secrets readOnly: true - equal: path: spec.template.spec.volumes[3] value: name: jenkins-secrets projected: sources: - secret: name: my-release-jenkins items: - key: jenkins-admin-user path: chart-admin-username - key: jenkins-admin-password path: chart-admin-password - secret: name: my-exisiting-credentials - it: test existing secret with additionalExistingSecrets template: jenkins-controller-statefulset.yaml set: controller.existingSecret: my-exisiting-credentials controller.additionalExistingSecrets: - name: my-exisiting-credentials keyName: github-username - name: my-exisiting-credentials keyName: github-password asserts: - equal: path: spec.template.spec.containers[0].volumeMounts[4] value: mountPath: /run/secrets/additional name: jenkins-secrets readOnly: true - equal: path: spec.template.spec.volumes[3] value: name: jenkins-secrets projected: sources: - secret: items: - key: github-username path: my-exisiting-credentials-github-username name: my-exisiting-credentials - secret: items: - key: github-password path: my-exisiting-credentials-github-password name: my-exisiting-credentials - secret: name: my-release-jenkins items: - key: jenkins-admin-user path: chart-admin-username - key: jenkins-admin-password path: chart-admin-password - secret: name: my-exisiting-credentials - it: test templated environment variables template: jenkins-controller-statefulset.yaml set: testValue: some-value controller.initContainerEnv: - name: "TEST_ENV_VAR_INIT" value: "test-env-var-init" - name: "TEST_ENV_VAR_INIT_TEMPLATED" value: "{{ .Values.testValue }}" controller.sidecars.configAutoReload.env: - name: "TEST_ENV_VAR_CONFIG" value: "test-env-var-config" - name: "TEST_ENV_VAR_CONFIG_TEMPLATED" value: "{{ .Values.testValue }}" controller.containerEnv: - name: "TEST_ENV_VAR_CONTAINER" value: "test-env-var-container" - name: "TEST_ENV_VAR__CONTAINER_TEMPLATED" value: "{{ .Values.testValue }}" controller.initContainerEnvFrom: - configMapRef: name: special-config controller.sidecars.configAutoReload.envFrom: - configMapRef: name: special-config controller.containerEnvFrom: - configMapRef: name: special-config asserts: - contains: path: spec.template.spec.initContainers[0].env content: name: "TEST_ENV_VAR_INIT" value: "test-env-var-init" - contains: path: spec.template.spec.initContainers[0].env content: name: "TEST_ENV_VAR_INIT_TEMPLATED" value: "some-value" - contains: path: spec.template.spec.containers[1].env content: name: "TEST_ENV_VAR_CONFIG" value: "test-env-var-config" - contains: path: spec.template.spec.containers[1].env content: name: "TEST_ENV_VAR_CONFIG_TEMPLATED" value: "some-value" - contains: path: spec.template.spec.containers[0].env content: name: "TEST_ENV_VAR_CONTAINER" value: "test-env-var-container" - contains: path: spec.template.spec.containers[0].env content: name: "TEST_ENV_VAR__CONTAINER_TEMPLATED" value: "some-value" - contains: path: spec.template.spec.initContainers[0].envFrom content: configMapRef: name: special-config - contains: path: spec.template.spec.containers[0].envFrom content: configMapRef: name: special-config - contains: path: spec.template.spec.containers[1].envFrom content: configMapRef: name: special-config - it: overrides container args template: jenkins-controller-statefulset.yaml set: controller.overrideArgs: - --httpPort=8080 - --requestHeaderSize=32768 asserts: - equal: path: spec.template.spec.containers[0].args value: - --httpPort=8080 - --requestHeaderSize=32768 - it: allows templating in container args overrides template: jenkins-controller-statefulset.yaml set: controller.overrideArgs: - --httpPort={{.Values.controller.targetPort}} - --requestHeaderSize=32768 asserts: - equal: path: spec.template.spec.containers[0].args value: - --httpPort=8080 - --requestHeaderSize=32768 - it: render pod annotations template: jenkins-controller-statefulset.yaml set: controller: podAnnotations: templated-annotations: "{{ .Release.Name }}" fixed-annotation: some-fixed-annotation asserts: - matchSnapshot: path: spec.template.metadata.annotations - it: template: jenkins-controller-statefulset.yaml set: controller: installPlugins: false asserts: - notContains: path: spec.template.spec.volumes content: name: plugins emptyDir: {} - notContains: path: spec.template.spec.initContainers[0].volumeMounts content: name: plugins - it: template: jenkins-controller-statefulset.yaml set: controller: JCasC: configUrls: - https://acme.org/jenkins.yaml asserts: - contains: path: spec.template.spec.containers[0].env content: name: "CASC_JENKINS_CONFIG" value: "/var/jenkins_home/casc_configs,https://acme.org/jenkins.yaml" - it: template: jenkins-controller-statefulset.yaml set: controller: JCasC: configUrls: - https://acme.org/jenkins.yaml - https://foobar.org/jenkins.yaml asserts: - contains: path: spec.template.spec.containers[0].env content: name: "CASC_JENKINS_CONFIG" value: "/var/jenkins_home/casc_configs,https://acme.org/jenkins.yaml,https://foobar.org/jenkins.yaml" - it: template: jenkins-controller-statefulset.yaml set: controller: JCasC: configUrls: [] asserts: - contains: path: spec.template.spec.containers[0].env content: name: "CASC_JENKINS_CONFIG" value: "/var/jenkins_home/casc_configs"