summaryrefslogtreecommitdiff
path: root/qa/qa/service/kubernetes_cluster.rb
blob: 59bfacf9195b4d1d64ac1370bf871d76d74a9d15 (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
132
133
134
135
136
# frozen_string_literal: true

require 'mkmf'

module QA
  module Service
    class KubernetesCluster
      include Service::Shellout

      attr_reader :api_url, :ca_certificate, :token, :rbac, :provider

      def initialize(rbac: true, provider_class: QA::Service::ClusterProvider::Gcloud)
        @rbac = rbac
        @provider = provider_class.new(rbac: rbac)
      end

      def create!
        validate_dependencies

        @provider.validate_dependencies
        @provider.setup

        @api_url = fetch_api_url

        credentials = @provider.filter_credentials(fetch_credentials)
        @ca_certificate = Base64.decode64(credentials.dig('data', 'ca.crt'))
        @token = Base64.decode64(credentials.dig('data', 'token'))

        self
      end

      def remove!
        @provider.teardown
      end

      def cluster_name
        @provider.cluster_name
      end

      def to_s
        cluster_name
      end

      def install_kubernetes_agent(agent_token)
        @provider.install_kubernetes_agent(agent_token)
      end

      def create_secret(secret, secret_name)
        shell("kubectl create secret generic #{secret_name} --from-literal=token='#{secret}'")
      end

      def apply_manifest(manifest)
        shell('kubectl apply -f -', stdin_data: manifest)
      end

      def add_sample_policy(project, policy_name: 'sample-policy')
        namespace = "#{project.name}-#{project.id}-production"
        network_policy = <<~YAML
          apiVersion: "cilium.io/v2"
          kind: CiliumNetworkPolicy
          metadata:
            name: #{policy_name}
            namespace: #{namespace}
          spec:
            endpointSelector:
              matchLabels:
                role: backend
            ingress:
            - fromEndpoints:
              - matchLabels:
                  role: frontend
        YAML
        shell('kubectl apply -f -', stdin_data: network_policy)
      end

      private

      def fetch_api_url
        `kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}'`
      end

      def fetch_credentials
        return global_credentials unless rbac

        create_service_account(admin_user)
        account_credentials
      end

      def admin_user
        @admin_user ||= "#{@provider.cluster_name}-admin"
      end

      def create_service_account(user)
        service_account = <<~YAML
          ---
          apiVersion: v1
          kind: ServiceAccount
          metadata:
            name: gitlab-account
            namespace: default
          ---
          kind: ClusterRoleBinding
          apiVersion: rbac.authorization.k8s.io/v1
          metadata:
            name: gitlab-account-binding
          subjects:
          - kind: ServiceAccount
            name: gitlab-account
            namespace: default
          roleRef:
            kind: ClusterRole
            name: cluster-admin
            apiGroup: rbac.authorization.k8s.io
        YAML

        shell('kubectl apply -f -', stdin_data: service_account)
      end

      def account_credentials
        secrets = JSON.parse(`kubectl get secrets -o json`)

        secrets['items'].find do |item|
          item['metadata']['annotations']['kubernetes.io/service-account.name'] == 'gitlab-account'
        end
      end

      def global_credentials
        JSON.parse(`kubectl get secrets -o jsonpath='{.items[0]}'`)
      end

      def validate_dependencies
        find_executable('kubectl') || raise("You must first install `kubectl` executable to run these tests.")
      end
    end
  end
end