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"
