summaryrefslogtreecommitdiff
path: root/app/services/clusters/gcp/kubernetes/create_or_update_service_account_service.rb
blob: 7c5450dbcd6ac8175b4fe656b0b355f3094463c3 (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
137
138
139
140
141
# frozen_string_literal: true

module Clusters
  module Gcp
    module Kubernetes
      class CreateOrUpdateServiceAccountService
        def initialize(kubeclient, service_account_name:, service_account_namespace:, token_name:, rbac:, namespace_creator: false, role_binding_name: nil)
          @kubeclient = kubeclient
          @service_account_name = service_account_name
          @service_account_namespace = service_account_namespace
          @token_name = token_name
          @rbac = rbac
          @namespace_creator = namespace_creator
          @role_binding_name = role_binding_name
        end

        def self.gitlab_creator(kubeclient, rbac:)
          self.new(
            kubeclient,
            service_account_name: Clusters::Gcp::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAME,
            service_account_namespace: Clusters::Gcp::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAMESPACE,
            token_name: Clusters::Gcp::Kubernetes::GITLAB_ADMIN_TOKEN_NAME,
            rbac: rbac
          )
        end

        def self.namespace_creator(kubeclient, service_account_name:, service_account_namespace:, rbac:)
          self.new(
            kubeclient,
            service_account_name: service_account_name,
            service_account_namespace: service_account_namespace,
            token_name: "#{service_account_namespace}-token",
            rbac: rbac,
            namespace_creator: true,
            role_binding_name: "gitlab-#{service_account_namespace}"
          )
        end

        def execute
          ensure_project_namespace_exists if namespace_creator

          kubeclient.create_or_update_service_account(service_account_resource)
          kubeclient.create_or_update_secret(service_account_token_resource)

          return unless rbac

          create_role_or_cluster_role_binding

          return unless namespace_creator

          create_or_update_knative_serving_role
          create_or_update_knative_serving_role_binding
        end

        private

        attr_reader :kubeclient, :service_account_name, :service_account_namespace, :token_name, :rbac, :namespace_creator, :role_binding_name

        def ensure_project_namespace_exists
          Gitlab::Kubernetes::Namespace.new(
            service_account_namespace,
            kubeclient
          ).ensure_exists!
        end

        def create_role_or_cluster_role_binding
          if namespace_creator
            kubeclient.create_or_update_role_binding(role_binding_resource)
          else
            kubeclient.create_or_update_cluster_role_binding(cluster_role_binding_resource)
          end
        end

        def create_or_update_knative_serving_role
          kubeclient.update_role(knative_serving_role_resource)
        end

        def create_or_update_knative_serving_role_binding
          kubeclient.update_role_binding(knative_serving_role_binding_resource)
        end

        def service_account_resource
          Gitlab::Kubernetes::ServiceAccount.new(
            service_account_name,
            service_account_namespace
          ).generate
        end

        def service_account_token_resource
          Gitlab::Kubernetes::ServiceAccountToken.new(
            token_name,
            service_account_name,
            service_account_namespace
          ).generate
        end

        def cluster_role_binding_resource
          subjects = [{ kind: 'ServiceAccount', name: service_account_name, namespace: service_account_namespace }]

          Gitlab::Kubernetes::ClusterRoleBinding.new(
            Clusters::Gcp::Kubernetes::GITLAB_CLUSTER_ROLE_BINDING_NAME,
            Clusters::Gcp::Kubernetes::GITLAB_CLUSTER_ROLE_NAME,
            subjects
          ).generate
        end

        def role_binding_resource
          Gitlab::Kubernetes::RoleBinding.new(
            name: role_binding_name,
            role_name: Clusters::Gcp::Kubernetes::PROJECT_CLUSTER_ROLE_NAME,
            role_kind: :ClusterRole,
            namespace: service_account_namespace,
            service_account_name: service_account_name
          ).generate
        end

        def knative_serving_role_resource
          Gitlab::Kubernetes::Role.new(
            name: Clusters::Gcp::Kubernetes::GITLAB_KNATIVE_SERVING_ROLE_NAME,
            namespace: service_account_namespace,
            rules: [{
              apiGroups: %w(serving.knative.dev),
              resources: %w(configurations configurationgenerations routes revisions revisionuids autoscalers services),
              verbs: %w(get list create update delete patch watch)
            }]
          ).generate
        end

        def knative_serving_role_binding_resource
          Gitlab::Kubernetes::RoleBinding.new(
            name: Clusters::Gcp::Kubernetes::GITLAB_KNATIVE_SERVING_ROLE_BINDING_NAME,
            role_name: Clusters::Gcp::Kubernetes::GITLAB_KNATIVE_SERVING_ROLE_NAME,
            role_kind: :Role,
            namespace: service_account_namespace,
            service_account_name: service_account_name
          ).generate
        end
      end
    end
  end
end