# This manifest installs the Istio install-cni container, as well
# as the Istio CNI plugin and config on
# each master and worker node in a Kubernetes cluster.
{{- $defaultBinDir :=
    (.Capabilities.KubeVersion.GitVersion | contains "-gke") | ternary
      "/home/kubernetes/bin"
      "/opt/cni/bin"
}}
kind: DaemonSet
apiVersion: apps/v1
metadata:
  name: istio-cni-node
  namespace: {{ .Release.Namespace }}
  labels:
    k8s-app: istio-cni-node
    release: {{ .Release.Name }}
    istio.io/rev: {{ .Values.revision | default "default" }}
    install.operator.istio.io/owning-resource: {{ .Values.ownerName | default "unknown" }}
    operator.istio.io/component: "Cni"
spec:
  selector:
    matchLabels:
      k8s-app: istio-cni-node
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  template:
    metadata:
      labels:
        k8s-app: istio-cni-node
        sidecar.istio.io/inject: "false"
      annotations:
        sidecar.istio.io/inject: "false"
        # Add Prometheus Scrape annotations
        prometheus.io/scrape: 'true'
        prometheus.io/port: "15014"
        prometheus.io/path: '/metrics'
        # Custom annotations
        {{- if .Values.cni.podAnnotations }}
{{ toYaml .Values.cni.podAnnotations | indent 8 }}
        {{- end }}
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      tolerations:
        # Make sure istio-cni-node gets scheduled on all nodes.
        - effect: NoSchedule
          operator: Exists
        # Mark the pod as a critical add-on for rescheduling.
        - key: CriticalAddonsOnly
          operator: Exists
        - effect: NoExecute
          operator: Exists
      priorityClassName: system-node-critical
      serviceAccountName: istio-cni
      # Minimize downtime during a rolling upgrade or deletion; tell Kubernetes to do a "force
      # deletion": https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods.
      terminationGracePeriodSeconds: 5
      containers:
        # This container installs the Istio CNI binaries
        # and CNI network config file on each node.
        - name: install-cni
{{- if contains "/" .Values.cni.image }}
          image: "{{ .Values.cni.image }}"
{{- else }}
          image: "{{ .Values.cni.hub | default .Values.global.hub }}/{{ .Values.cni.image | default "install-cni" }}:{{ .Values.cni.tag | default .Values.global.tag }}{{with (.Values.cni.variant | default .Values.global.variant)}}-{{.}}{{end}}"
{{- end }}
{{- if or .Values.cni.pullPolicy .Values.global.imagePullPolicy }}
          imagePullPolicy: {{ .Values.cni.pullPolicy | default .Values.global.imagePullPolicy }}
{{- end }}
          readinessProbe:
            httpGet:
              path: /readyz
              port: 8000
          securityContext:
            runAsGroup: 0
            runAsUser: 0
            runAsNonRoot: false
            privileged: {{ .Values.cni.privileged }}
{{- if .Values.cni.seccompProfile }}
            seccompProfile:
{{ toYaml .Values.cni.seccompProfile | trim | indent 14 }}
{{- end }}
          command: ["install-cni"]
          args:
            {{- if .Values.global.logging.level }}
            - --log_output_level={{ .Values.global.logging.level }}
            {{- end}}
          env:
{{- if .Values.cni.cniConfFileName }}
            # Name of the CNI config file to create.
            - name: CNI_CONF_NAME
              value: "{{ .Values.cni.cniConfFileName }}"
{{- end }}
            # The CNI network config to install on each node.
            - name: CNI_NETWORK_CONFIG
              valueFrom:
                configMapKeyRef:
                  name: istio-cni-config
                  key: cni_network_config
            - name: CNI_NET_DIR
              value: {{ default "/etc/cni/net.d" .Values.cni.cniConfDir }}
            # Deploy as a standalone CNI plugin or as chained?
            - name: CHAINED_CNI_PLUGIN
              value: "{{ .Values.cni.chained }}"
            - name: REPAIR_ENABLED
              value: "{{ .Values.cni.repair.enabled }}"
            - name: REPAIR_NODE_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: REPAIR_LABEL_PODS
              value: "{{.Values.cni.repair.labelPods}}"
            # Set to true to enable pod deletion
            - name: REPAIR_DELETE_PODS
              value: "{{.Values.cni.repair.deletePods}}"
            - name: REPAIR_RUN_AS_DAEMON
              value: "true"
            - name: REPAIR_SIDECAR_ANNOTATION
              value: "sidecar.istio.io/status"
            - name: REPAIR_INIT_CONTAINER_NAME
              value: "{{ .Values.cni.repair.initContainerName }}"
            - name: REPAIR_BROKEN_POD_LABEL_KEY
              value: "{{.Values.cni.repair.brokenPodLabelKey}}"
            - name: REPAIR_BROKEN_POD_LABEL_VALUE
              value: "{{.Values.cni.repair.brokenPodLabelValue}}"
          volumeMounts:
            - mountPath: /host/opt/cni/bin
              name: cni-bin-dir
            - mountPath: /host/etc/cni/net.d
              name: cni-net-dir
            - mountPath: /var/run/istio-cni
              name: cni-log-dir
          resources:
{{- if .Values.cni.resources }}
{{ toYaml .Values.cni.resources | trim | indent 12 }}
{{- else }}
{{ toYaml .Values.global.defaultResources | trim | indent 12 }}
{{- end }}
{{- if .Values.cni.taint.enabled }}
        - name: taint-controller
{{- if contains "/" .Values.cni.image }}
          image: "{{ .Values.cni.image }}"
{{- else }}
          image: "{{ .Values.cni.hub | default .Values.global.hub }}/{{ .Values.cni.image | default "install-cni" }}:{{ .Values.cni.tag | default .Values.global.tag }}{{with (.Values.cni.variant | default .Values.global.variant)}}-{{.}}{{end}}"
{{- end }}
{{- if or .Values.cni.pullPolicy .Values.global.imagePullPolicy }}
          imagePullPolicy: {{ .Values.cni.pullPolicy | default .Values.global.imagePullPolicy }}
{{- end }}
          command: ["/opt/local/bin/istio-cni-taint"]
          securityContext:
            runAsUser: 1337
            runAsGroup: 1337
            runAsNonRoot: true
{{- if .Values.cni.seccompProfile }}
            seccompProfile:
{{ toYaml .Values.cni.seccompProfile | trim | indent 14 }}
{{- end }}
          env:
          - name: "TAINT_RUN-AS-DAEMON"
            value: "true"
          - name: "TAINT_CONFIGMAP-NAME"
            value: "istio-cni-taint-configmap"
          - name: "TAINT_CONFIGMAP-NAMESPACE"
            value: {{ .Release.Namespace | quote }}
{{- end }}
      volumes:
        # Used to install CNI.
        - name: cni-bin-dir
          hostPath:
            path: {{ .Values.cni.cniBinDir | default $defaultBinDir }}
        - name: cni-net-dir
          hostPath:
            path: {{ default "/etc/cni/net.d" .Values.cni.cniConfDir }}
        # Used for UDS log
        - name: cni-log-dir
          hostPath:
            path: /var/run/istio-cni
