summaryrefslogtreecommitdiff
path: root/qa/qa/service/cluster_provider/k3d.rb
blob: 8e117c2dbd5ce2d6863780ca7d12192580e25172 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# frozen_string_literal: true

module QA
  module Service
    module ClusterProvider
      class K3d < Base
        def validate_dependencies
          find_executable('k3d') || raise("You must first install `k3d` executable to run these tests.")
        end

        def set_credentials(admin_user)
        end

        def setup
          shell "k3d create --workers 1 --name #{cluster_name} --wait 0"

          @old_kubeconfig = ENV['KUBECONFIG']
          ENV['KUBECONFIG'] = fetch_kubeconfig
          raise "Could not fetch kubeconfig" unless ENV['KUBECONFIG']

          install_local_storage
        end

        def teardown
          ENV['KUBECONFIG'] = @old_kubeconfig
          shell "k3d delete --name #{cluster_name}"
        end

        # Fetch "real" certificate
        # See https://github.com/rancher/k3s/issues/27
        def filter_credentials(credentials)
          kubeconfig = YAML.load_file(ENV['KUBECONFIG'])
          ca_certificate = kubeconfig.dig('clusters', 0, 'cluster', 'certificate-authority-data')

          credentials.merge('data' => credentials['data'].merge('ca.crt' => ca_certificate))
        end

        private

        def retry_until(max_attempts: 10, wait: 1)
          max_attempts.times do
            result = yield
            return result if result

            sleep wait
          end

          raise "Retried #{max_attempts} times. Aborting"
        end

        def fetch_kubeconfig
          retry_until do
            config = `k3d get-kubeconfig --name #{cluster_name}`.chomp
            config if config =~ /kubeconfig.yaml/
          end
        end

        def install_local_storage
          shell('kubectl apply -f -', stdin_data: local_storage_config)
        end

        # See https://github.com/rancher/k3d/issues/67
        def local_storage_config
          <<~YAML
            ---
            apiVersion: v1
            kind: ServiceAccount
            metadata:
              name: storage-provisioner
              namespace: kube-system
            ---
            apiVersion: rbac.authorization.k8s.io/v1
            kind: ClusterRoleBinding
            metadata:
              name: storage-provisioner
            roleRef:
              apiGroup: rbac.authorization.k8s.io
              kind: ClusterRole
              name: system:persistent-volume-provisioner
            subjects:
              - kind: ServiceAccount
                name: storage-provisioner
                namespace: kube-system
            ---
            apiVersion: v1
            kind: Pod
            metadata:
              name: storage-provisioner
              namespace: kube-system
            spec:
              serviceAccountName: storage-provisioner
              tolerations:
              - effect: NoExecute
                key: node.kubernetes.io/not-ready
                operator: Exists
                tolerationSeconds: 300
              - effect: NoExecute
                key: node.kubernetes.io/unreachable
                operator: Exists
                tolerationSeconds: 300
              hostNetwork: true
              containers:
              - name: storage-provisioner
                image: gcr.io/k8s-minikube/storage-provisioner:v1.8.1
                command: ["/storage-provisioner"]
                imagePullPolicy: IfNotPresent
                volumeMounts:
                - mountPath: /tmp
                  name: tmp
              volumes:
              - name: tmp
                hostPath:
                  path: /tmp
                  type: Directory
            ---
            kind: StorageClass
            apiVersion: storage.k8s.io/v1
            metadata:
              name: standard
              namespace: kube-system
              annotations:
                storageclass.kubernetes.io/is-default-class: "true"
              labels:
                addonmanager.kubernetes.io/mode: EnsureExists
            provisioner: k8s.io/minikube-hostpath
          YAML
        end
      end
    end
  end
end