1# frozen_string_literal: true 2 3module Clusters 4 module Aws 5 class FinalizeCreationService 6 include Gitlab::Utils::StrongMemoize 7 8 attr_reader :provider 9 10 delegate :cluster, to: :provider 11 12 def execute(provider) 13 @provider = provider 14 15 configure_provider 16 create_gitlab_service_account! 17 configure_platform_kubernetes 18 configure_node_authentication! 19 20 cluster.save! 21 rescue ::Aws::CloudFormation::Errors::ServiceError => e 22 log_service_error(e.class.name, provider.id, e.message) 23 provider.make_errored!(s_('ClusterIntegration|Failed to fetch CloudFormation stack: %{message}') % { message: e.message }) 24 rescue Kubeclient::HttpError => e 25 log_service_error(e.class.name, provider.id, e.message) 26 provider.make_errored!(s_('ClusterIntegration|Failed to run Kubeclient: %{message}') % { message: e.message }) 27 rescue ActiveRecord::RecordInvalid => e 28 log_service_error(e.class.name, provider.id, e.message) 29 provider.make_errored!(s_('ClusterIntegration|Failed to configure EKS provider: %{message}') % { message: e.message }) 30 end 31 32 private 33 34 def create_gitlab_service_account! 35 Clusters::Kubernetes::CreateOrUpdateServiceAccountService.gitlab_creator( 36 kube_client, 37 rbac: true 38 ).execute 39 end 40 41 def configure_provider 42 provider.status_event = :make_created 43 end 44 45 def configure_platform_kubernetes 46 cluster.build_platform_kubernetes( 47 api_url: cluster_endpoint, 48 ca_cert: cluster_certificate, 49 token: request_kubernetes_token) 50 end 51 52 def request_kubernetes_token 53 Clusters::Kubernetes::FetchKubernetesTokenService.new( 54 kube_client, 55 Clusters::Kubernetes::GITLAB_ADMIN_TOKEN_NAME, 56 Clusters::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAMESPACE 57 ).execute 58 end 59 60 def kube_client 61 @kube_client ||= build_kube_client!( 62 cluster_endpoint, 63 cluster_certificate 64 ) 65 end 66 67 def build_kube_client!(api_url, ca_pem) 68 raise "Incomplete settings" unless api_url 69 70 Gitlab::Kubernetes::KubeClient.new( 71 api_url, 72 auth_options: kubeclient_auth_options, 73 ssl_options: kubeclient_ssl_options(ca_pem), 74 http_proxy_uri: ENV['http_proxy'] 75 ) 76 end 77 78 def kubeclient_auth_options 79 { bearer_token: Kubeclient::AmazonEksCredentials.token(provider.credentials, cluster.name) } 80 end 81 82 def kubeclient_ssl_options(ca_pem) 83 opts = { verify_ssl: OpenSSL::SSL::VERIFY_PEER } 84 85 if ca_pem.present? 86 opts[:cert_store] = OpenSSL::X509::Store.new 87 opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_pem)) 88 end 89 90 opts 91 end 92 93 def cluster_stack 94 @cluster_stack ||= provider.api_client.describe_stacks(stack_name: provider.cluster.name).stacks.first 95 end 96 97 def stack_output_value(key) 98 cluster_stack.outputs.detect { |output| output.output_key == key }.output_value 99 end 100 101 def node_instance_role_arn 102 stack_output_value('NodeInstanceRole') 103 end 104 105 def cluster_endpoint 106 strong_memoize(:cluster_endpoint) do 107 stack_output_value('ClusterEndpoint') 108 end 109 end 110 111 def cluster_certificate 112 strong_memoize(:cluster_certificate) do 113 Base64.decode64(stack_output_value('ClusterCertificate')) 114 end 115 end 116 117 def configure_node_authentication! 118 kube_client.create_config_map(node_authentication_config) 119 end 120 121 def node_authentication_config 122 Gitlab::Kubernetes::ConfigMaps::AwsNodeAuth.new(node_instance_role_arn).generate 123 end 124 125 def logger 126 @logger ||= Gitlab::Kubernetes::Logger.build 127 end 128 129 def log_service_error(exception, provider_id, message) 130 logger.error( 131 exception: exception.class.name, 132 service: self.class.name, 133 provider_id: provider_id, 134 message: message 135 ) 136 end 137 end 138 end 139end 140