# Source: https://github.com/kubermatic/kubeone/blob/master/addons/unattended-upgrades/
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: unattended-upgrades-install
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: unattended-upgrades-install
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        name: unattended-upgrades-install
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: v1.machine-controller.kubermatic.io/operating-system
                    operator: In
                    values:
                      - ubuntu
              - matchExpressions:
                  - key: v1.kubeone.io/operating-system
                    operator: In
                    values:
                      - ubuntu
                      - debian
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          effect: NoSchedule
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
      hostPID: true
      containers:
        - name: "unattended-upgrades-install"
          image: "alpine:3.17.3"
          securityContext:
            privileged: true
          command:
            - /bin/sh
            - -c
            - |
              set -xeuo pipefail
              apk add --no-cache bash util-linux
              nsenter -t 1 -m -u -i -n -p -- bash -c "${STARTUP_SCRIPT}"
              sleep inf
          env:
            - name: STARTUP_SCRIPT
              value: |
                set -xeuo pipefail
                export DEBIAN_FRONTEND=noninteractive
                apt-get install -y --no-install-recommends \
                  apt-utils \
                  unattended-upgrades
                echo unattended-upgrades unattended-upgrades/enable_auto_updates boolean true | debconf-set-selections
                dpkg-reconfigure -f noninteractive unattended-upgrades
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kured
rules:
  # Allow kured to read spec.unschedulable
  # Allow kubectl to drain/uncordon
  #
  # NB: These permissions are tightly coupled to the bundled version of kubectl; the ones below
  # match https://github.com/kubernetes/kubernetes/blob/v1.19.4/staging/src/k8s.io/kubectl/pkg/cmd/drain/drain.go
  #
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "patch"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["list", "delete", "get"]
  - apiGroups: ["apps"]
    resources: ["daemonsets"]
    verbs: ["get"]
  - apiGroups: [""]
    resources: ["pods/eviction"]
    verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kured
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kured
subjects:
  - kind: ServiceAccount
    name: kured
    namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: kube-system
  name: kured
rules:
  # Allow kured to lock/unlock itself
  - apiGroups: ["apps"]
    resources: ["daemonsets"]
    resourceNames: ["kured"]
    verbs: ["update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: kube-system
  name: kured
subjects:
  - kind: ServiceAccount
    namespace: kube-system
    name: kured
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kured
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kured
  namespace: kube-system
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kured # Must match `--ds-name`
  namespace: kube-system # Must match `--ds-namespace`
spec:
  selector:
    matchLabels:
      name: kured
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        name: kured
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: v1.machine-controller.kubermatic.io/operating-system
                    operator: In
                    values:
                      - amzn
                      - centos
                      - rhel
                      - rockylinux
                      - ubuntu
              - matchExpressions:
                  - key: v1.kubeone.io/operating-system
                    operator: In
                    values:
                      - amzn
                      - centos
                      - debian
                      - rhel
                      - rockylinux
                      - ubuntu
      serviceAccountName: kured
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          effect: NoSchedule
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
      hostPID: true # Facilitate entering the host mount namespace via init
      containers:
        - name: kured
          image: ghcr.io/kubereboot/kured:1.13.0
          imagePullPolicy: IfNotPresent
          securityContext:
            privileged: true # Give permission to nsenter /proc/1/ns/mnt
          env:
            # Pass in the name of the node on which this pod is scheduled
            # for use with drain/uncordon operations and lock acquisition
            - name: KURED_NODE_ID
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
          command:
            - /usr/bin/kured
#            - --alert-filter-regexp=^RebootRequired$
#            - --blocking-pod-selector=runtime=long,cost=expensive
#            - --blocking-pod-selector=name=temperamental
#            - --blocking-pod-selector=...
#            - --ds-name=kured
#            - --ds-namespace=kube-system
#            - --end-time=23:59:59
#            - --lock-annotation=weave.works/kured-node-lock
#            - --period=1h
#            - --prometheus-url=http://prometheus.monitoring.svc.cluster.local
#            - --reboot-days=sun,mon,tue,wed,thu,fri,sat
#            - --reboot-sentinel=/var/run/reboot-required
#            - --slack-hook-url=https://hooks.slack.com/...
#            - --slack-username=prod
#            - --slack-channel=alerting
#            - --message-template-drain=Draining node %s
#            - --message-template-drain=Rebooting node %s
#            - --start-time=0:00
#            - --time-zone=UTC
