suite: CoreDNS Configmap
templates:
  - coredns-configmap.yaml

tests:
  - it: should create configmap
    release:
      name: my-release
      namespace: my-namespace
    asserts:
      - hasDocuments:
          count: 1
      - equal:
          path: metadata.name
          value: vc-coredns-my-release
      - equal:
          path: metadata.namespace
          value: my-namespace

  - it: should create correct external coredns config
    asserts:
      - hasDocuments:
          count: 1
      - notExists:
          path: data.Corefile
      - equal:
          path: data["coredns.yaml"]
          value: |-
            apiVersion: v1
            kind: ServiceAccount
            metadata:
              name: coredns
              namespace: kube-system
            ---
            apiVersion: rbac.authorization.k8s.io/v1
            kind: ClusterRole
            metadata:
              labels:
                kubernetes.io/bootstrapping: rbac-defaults
              name: system:coredns
            rules:
              - apiGroups:
                  - ""
                resources:
                  - endpoints
                  - services
                  - pods
                  - namespaces
                verbs:
                  - list
                  - watch
              - apiGroups:
                  - discovery.k8s.io
                resources:
                  - endpointslices
                verbs:
                  - list
                  - watch
            ---
            apiVersion: rbac.authorization.k8s.io/v1
            kind: ClusterRoleBinding
            metadata:
              annotations:
                rbac.authorization.kubernetes.io/autoupdate: "true"
              labels:
                kubernetes.io/bootstrapping: rbac-defaults
              name: system:coredns
            roleRef:
              apiGroup: rbac.authorization.k8s.io
              kind: ClusterRole
              name: system:coredns
            subjects:
              - kind: ServiceAccount
                name: coredns
                namespace: kube-system
            ---
            apiVersion: v1
            kind: ConfigMap
            metadata:
              name: coredns
              namespace: kube-system
            data:
              Corefile: |-
                .:1053 {
                    errors
                    health
                    ready
                    rewrite name regex .*\.nodes\.vcluster\.com kubernetes.default.svc.cluster.local
                    kubernetes cluster.local in-addr.arpa ip6.arpa {
                        pods insecure
                        fallthrough in-addr.arpa ip6.arpa
                    }
                    hosts /etc/NodeHosts {
                        ttl 60
                        reload 15s
                        fallthrough
                    }
                    prometheus :9153
                    forward . /etc/resolv.conf
                    cache 30
                    loop
                    loadbalance
                }

                import /etc/coredns/custom/*.server
              NodeHosts: ""
            ---
            apiVersion: apps/v1
            kind: Deployment
            metadata:
              name: coredns
              namespace: kube-system
              labels:
                k8s-app: kube-dns
                kubernetes.io/name: "CoreDNS"
            spec:
              replicas: 1
              strategy:
                type: RollingUpdate
                rollingUpdate:
                  maxUnavailable: 1
              selector:
                matchLabels:
                  k8s-app: kube-dns
              template:
                metadata:
                  labels:
                    k8s-app: kube-dns
                spec:
                  priorityClassName: ""
                  serviceAccountName: coredns
                  nodeSelector:
                    kubernetes.io/os: linux
                  topologySpreadConstraints:
                    - labelSelector:
                        matchLabels:
                          k8s-app: kube-dns
                      maxSkew: 1
                      topologyKey: kubernetes.io/hostname
                      whenUnsatisfiable: DoNotSchedule
                  containers:
                    - name: coredns
                      image: {{.IMAGE}}
                      imagePullPolicy: IfNotPresent
                      resources:
                        limits:
                          cpu: 1000m
                          memory: 170Mi
                        requests:
                          cpu: 20m
                          memory: 64Mi
                      args: [ "-conf", "/etc/coredns/Corefile" ]
                      volumeMounts:
                        - name: config-volume
                          mountPath: /etc/coredns
                          readOnly: true
                        - name: custom-config-volume
                          mountPath: /etc/coredns/custom
                          readOnly: true
                      securityContext:
                        runAsNonRoot: true
                        runAsUser: {{.RUN_AS_USER}}
                        runAsGroup: {{.RUN_AS_GROUP}}
                        allowPrivilegeEscalation: false
                        capabilities:
                          add:
                            - NET_BIND_SERVICE
                          drop:
                            - ALL
                        readOnlyRootFilesystem: true
                      livenessProbe:
                        httpGet:
                          path: /health
                          port: 8080
                          scheme: HTTP
                        initialDelaySeconds: 60
                        periodSeconds: 10
                        timeoutSeconds: 1
                        successThreshold: 1
                        failureThreshold: 3
                      readinessProbe:
                        httpGet:
                          path: /ready
                          port: 8181
                          scheme: HTTP
                        initialDelaySeconds: 0
                        periodSeconds: 2
                        timeoutSeconds: 1
                        successThreshold: 1
                        failureThreshold: 3
                  dnsPolicy: Default
                  volumes:
                    - name: config-volume
                      configMap:
                        name: coredns
                        items:
                          - key: Corefile
                            path: Corefile
                          - key: NodeHosts
                            path: NodeHosts
                    - name: custom-config-volume
                      configMap:
                        name: coredns-custom
                        optional: true
            ---
            apiVersion: v1
            kind: Service
            metadata:
              name: kube-dns
              namespace: kube-system
              annotations:
                prometheus.io/port: "9153"
                prometheus.io/scrape: "true"
              labels:
                k8s-app: kube-dns
                kubernetes.io/cluster-service: "true"
                kubernetes.io/name: "CoreDNS"
            spec:
              type: ClusterIP
              selector:
                k8s-app: kube-dns
              ports:
                - name: dns
                  port: 53
                  targetPort: 1053
                  protocol: UDP
                - name: dns-tcp
                  port: 53
                  targetPort: 1053
                  protocol: TCP
                - name: metrics
                  port: 9153
                  protocol: TCP

  - it: should create correct custom configmap
    set:
      controlPlane:
        coredns:
          embedded: true
          overwriteManifests: |-
            abc
    asserts:
      - hasDocuments:
          count: 1
      - equal:
          path: data["coredns.yaml"]
          value: |-
            abc

  - it: should create correct custom configmap
    set:
      controlPlane:
        coredns:
          embedded: true
          overwriteConfig: |-
            abc
    asserts:
      - hasDocuments:
          count: 1
      - equal:
          path: data.Corefile
          value: |-
            abc

  - it: should create correct embedded configmap
    set:
      controlPlane:
        coredns:
          embedded: true
    asserts:
      - hasDocuments:
          count: 1
      - equal:
          path: data.Corefile
          value: |-
            .:1053 {
                errors
                health
                ready
                rewrite name regex .*\.nodes\.vcluster\.com kubernetes.default.svc.cluster.local
                kubernetes cluster.local in-addr.arpa ip6.arpa {
                    kubeconfig /data/vcluster/admin.conf
                    pods insecure
                    fallthrough in-addr.arpa ip6.arpa
                }
                hosts /etc/NodeHosts {
                    ttl 60
                    reload 15s
                    fallthrough
                }
                prometheus :9153
                forward . /etc/resolv.conf
                cache 30
                loop
                loadbalance
            }

            import /etc/coredns/custom/*.server
      - equal:
          path: data["coredns.yaml"]
          value: |-
            apiVersion: v1
            kind: ConfigMap
            metadata:
              name: coredns
              namespace: kube-system
            data:
              NodeHosts: ""
            ---
            apiVersion: v1
            kind: Service
            metadata:
              name: kube-dns
              namespace: kube-system
              annotations:
                prometheus.io/port: "9153"
                prometheus.io/scrape: "true"
              labels:
                k8s-app: kube-dns
                kubernetes.io/cluster-service: "true"
                kubernetes.io/name: "CoreDNS"
            spec:
              type: ClusterIP
              ports:
                - name: dns
                  port: 53
                  targetPort: 1053
                  protocol: UDP
                - name: dns-tcp
                  port: 53
                  targetPort: 1053
                  protocol: TCP
                - name: metrics
                  port: 9153
                  protocol: TCP
  - it: should correctly apply affinity and tolerations
    set:
      controlPlane:
        coredns:
          deployment:
            affinity:
              podAntiAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                  - labelSelector:
                      matchExpressions:
                        - key: app
                          operator: In
                          values:
                            - coredns
                    topologyKey: kubernetes.io/hostname
            tolerations:
              - effect: NoSchedule
                key: node-role.kubernetes.io/master
                operator: Exists
    asserts:
      - equal:
          path: data["coredns.yaml"]
          value: |-
            apiVersion: v1
            kind: ServiceAccount
            metadata:
              name: coredns
              namespace: kube-system
            ---
            apiVersion: rbac.authorization.k8s.io/v1
            kind: ClusterRole
            metadata:
              labels:
                kubernetes.io/bootstrapping: rbac-defaults
              name: system:coredns
            rules:
              - apiGroups:
                  - ""
                resources:
                  - endpoints
                  - services
                  - pods
                  - namespaces
                verbs:
                  - list
                  - watch
              - apiGroups:
                  - discovery.k8s.io
                resources:
                  - endpointslices
                verbs:
                  - list
                  - watch
            ---
            apiVersion: rbac.authorization.k8s.io/v1
            kind: ClusterRoleBinding
            metadata:
              annotations:
                rbac.authorization.kubernetes.io/autoupdate: "true"
              labels:
                kubernetes.io/bootstrapping: rbac-defaults
              name: system:coredns
            roleRef:
              apiGroup: rbac.authorization.k8s.io
              kind: ClusterRole
              name: system:coredns
            subjects:
              - kind: ServiceAccount
                name: coredns
                namespace: kube-system
            ---
            apiVersion: v1
            kind: ConfigMap
            metadata:
              name: coredns
              namespace: kube-system
            data:
              Corefile: |-
                .:1053 {
                    errors
                    health
                    ready
                    rewrite name regex .*\.nodes\.vcluster\.com kubernetes.default.svc.cluster.local
                    kubernetes cluster.local in-addr.arpa ip6.arpa {
                        pods insecure
                        fallthrough in-addr.arpa ip6.arpa
                    }
                    hosts /etc/NodeHosts {
                        ttl 60
                        reload 15s
                        fallthrough
                    }
                    prometheus :9153
                    forward . /etc/resolv.conf
                    cache 30
                    loop
                    loadbalance
                }

                import /etc/coredns/custom/*.server
              NodeHosts: ""
            ---
            apiVersion: apps/v1
            kind: Deployment
            metadata:
              name: coredns
              namespace: kube-system
              labels:
                k8s-app: kube-dns
                kubernetes.io/name: "CoreDNS"
            spec:
              replicas: 1
              strategy:
                type: RollingUpdate
                rollingUpdate:
                  maxUnavailable: 1
              selector:
                matchLabels:
                  k8s-app: kube-dns
              template:
                metadata:
                  labels:
                    k8s-app: kube-dns
                spec:
                  priorityClassName: ""
                  serviceAccountName: coredns
                  nodeSelector:
                    kubernetes.io/os: linux
                  affinity:
                    podAntiAffinity:
                      requiredDuringSchedulingIgnoredDuringExecution:
                      - labelSelector:
                          matchExpressions:
                          - key: app
                            operator: In
                            values:
                            - coredns
                        topologyKey: kubernetes.io/hostname
                  tolerations:
                    - effect: NoSchedule
                      key: node-role.kubernetes.io/master
                      operator: Exists
                  topologySpreadConstraints:
                    - labelSelector:
                        matchLabels:
                          k8s-app: kube-dns
                      maxSkew: 1
                      topologyKey: kubernetes.io/hostname
                      whenUnsatisfiable: DoNotSchedule
                  containers:
                    - name: coredns
                      image: {{.IMAGE}}
                      imagePullPolicy: IfNotPresent
                      resources:
                        limits:
                          cpu: 1000m
                          memory: 170Mi
                        requests:
                          cpu: 20m
                          memory: 64Mi
                      args: [ "-conf", "/etc/coredns/Corefile" ]
                      volumeMounts:
                        - name: config-volume
                          mountPath: /etc/coredns
                          readOnly: true
                        - name: custom-config-volume
                          mountPath: /etc/coredns/custom
                          readOnly: true
                      securityContext:
                        runAsNonRoot: true
                        runAsUser: {{.RUN_AS_USER}}
                        runAsGroup: {{.RUN_AS_GROUP}}
                        allowPrivilegeEscalation: false
                        capabilities:
                          add:
                            - NET_BIND_SERVICE
                          drop:
                            - ALL
                        readOnlyRootFilesystem: true
                      livenessProbe:
                        httpGet:
                          path: /health
                          port: 8080
                          scheme: HTTP
                        initialDelaySeconds: 60
                        periodSeconds: 10
                        timeoutSeconds: 1
                        successThreshold: 1
                        failureThreshold: 3
                      readinessProbe:
                        httpGet:
                          path: /ready
                          port: 8181
                          scheme: HTTP
                        initialDelaySeconds: 0
                        periodSeconds: 2
                        timeoutSeconds: 1
                        successThreshold: 1
                        failureThreshold: 3
                  dnsPolicy: Default
                  volumes:
                    - name: config-volume
                      configMap:
                        name: coredns
                        items:
                          - key: Corefile
                            path: Corefile
                          - key: NodeHosts
                            path: NodeHosts
                    - name: custom-config-volume
                      configMap:
                        name: coredns-custom
                        optional: true
            ---
            apiVersion: v1
            kind: Service
            metadata:
              name: kube-dns
              namespace: kube-system
              annotations:
                prometheus.io/port: "9153"
                prometheus.io/scrape: "true"
              labels:
                k8s-app: kube-dns
                kubernetes.io/cluster-service: "true"
                kubernetes.io/name: "CoreDNS"
            spec:
              type: ClusterIP
              selector:
                k8s-app: kube-dns
              ports:
                - name: dns
                  port: 53
                  targetPort: 1053
                  protocol: UDP
                - name: dns-tcp
                  port: 53
                  targetPort: 1053
                  protocol: TCP
                - name: metrics
                  port: 9153
                  protocol: TCP
