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
|
# frozen_string_literal: true
module Clusters
module Aws
class FinalizeCreationService
include Gitlab::Utils::StrongMemoize
attr_reader :provider
delegate :cluster, to: :provider
def execute(provider)
@provider = provider
configure_provider
create_gitlab_service_account!
configure_platform_kubernetes
configure_node_authentication!
cluster.save!
rescue ::Aws::CloudFormation::Errors::ServiceError => e
log_service_error(e.class.name, provider.id, e.message)
provider.make_errored!(s_('ClusterIntegration|Failed to fetch CloudFormation stack: %{message}') % { message: e.message })
rescue Kubeclient::HttpError => e
log_service_error(e.class.name, provider.id, e.message)
provider.make_errored!(s_('ClusterIntegration|Failed to run Kubeclient: %{message}') % { message: e.message })
rescue ActiveRecord::RecordInvalid => e
log_service_error(e.class.name, provider.id, e.message)
provider.make_errored!(s_('ClusterIntegration|Failed to configure EKS provider: %{message}') % { message: e.message })
end
private
def create_gitlab_service_account!
Clusters::Kubernetes::CreateOrUpdateServiceAccountService.gitlab_creator(
kube_client,
rbac: true
).execute
end
def configure_provider
provider.status_event = :make_created
end
def configure_platform_kubernetes
cluster.build_platform_kubernetes(
api_url: cluster_endpoint,
ca_cert: cluster_certificate,
token: request_kubernetes_token)
end
def request_kubernetes_token
Clusters::Kubernetes::FetchKubernetesTokenService.new(
kube_client,
Clusters::Kubernetes::GITLAB_ADMIN_TOKEN_NAME,
Clusters::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAMESPACE
).execute
end
def kube_client
@kube_client ||= build_kube_client!(
cluster_endpoint,
cluster_certificate
)
end
def build_kube_client!(api_url, ca_pem)
raise "Incomplete settings" unless api_url
Gitlab::Kubernetes::KubeClient.new(
api_url,
auth_options: kubeclient_auth_options,
ssl_options: kubeclient_ssl_options(ca_pem),
http_proxy_uri: ENV['http_proxy']
)
end
def kubeclient_auth_options
{ bearer_token: Kubeclient::AmazonEksCredentials.token(provider.credentials, cluster.name) }
end
def kubeclient_ssl_options(ca_pem)
opts = { verify_ssl: OpenSSL::SSL::VERIFY_PEER }
if ca_pem.present?
opts[:cert_store] = OpenSSL::X509::Store.new
opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_pem))
end
opts
end
def cluster_stack
@cluster_stack ||= provider.api_client.describe_stacks(stack_name: provider.cluster.name).stacks.first
end
def stack_output_value(key)
cluster_stack.outputs.detect { |output| output.output_key == key }.output_value
end
def node_instance_role_arn
stack_output_value('NodeInstanceRole')
end
def cluster_endpoint
strong_memoize(:cluster_endpoint) do
stack_output_value('ClusterEndpoint')
end
end
def cluster_certificate
strong_memoize(:cluster_certificate) do
Base64.decode64(stack_output_value('ClusterCertificate'))
end
end
def configure_node_authentication!
kube_client.create_config_map(node_authentication_config)
end
def node_authentication_config
Gitlab::Kubernetes::ConfigMaps::AwsNodeAuth.new(node_instance_role_arn).generate
end
def logger
@logger ||= Gitlab::Kubernetes::Logger.build
end
def log_service_error(exception, provider_id, message)
logger.error(
exception: exception.class.name,
service: self.class.name,
provider_id: provider_id,
message: message
)
end
end
end
end
|