diff options
author | Kamil Trzcinski <ayufan@ayufan.eu> | 2017-10-13 19:21:23 +0200 |
---|---|---|
committer | Shinya Maeda <shinya@gitlab.com> | 2017-10-23 08:57:52 +0300 |
commit | e1d12ba9b988e61afb9317f3a132d6e2caa93923 (patch) | |
tree | 2f68e95ed04d538dd0b4ddae338400b8af53379a /app/services/clusters | |
parent | c4cbf115db1ca719b97677057b984672a0900bf8 (diff) | |
download | gitlab-ce-e1d12ba9b988e61afb9317f3a132d6e2caa93923.tar.gz |
Refactor Clusters to be consisted from GcpProvider and KubernetesPlatform
Diffstat (limited to 'app/services/clusters')
-rw-r--r-- | app/services/clusters/create_service.rb | 14 | ||||
-rw-r--r-- | app/services/clusters/gcp/fetch_operation_service.rb | 16 | ||||
-rw-r--r-- | app/services/clusters/gcp/finalize_creation_service.rb | 66 | ||||
-rw-r--r-- | app/services/clusters/gcp/provision_service.rb | 49 | ||||
-rw-r--r-- | app/services/clusters/gcp/verify_provision_status_service.rb | 44 | ||||
-rw-r--r-- | app/services/clusters/update_service.rb | 7 |
6 files changed, 196 insertions, 0 deletions
diff --git a/app/services/clusters/create_service.rb b/app/services/clusters/create_service.rb new file mode 100644 index 00000000000..5429bc21256 --- /dev/null +++ b/app/services/clusters/create_service.rb @@ -0,0 +1,14 @@ +module Clusters + class CreateService < BaseService + def execute(access_token) + params['gcp_machine_type'] ||= GoogleApi::CloudPlatform::Client::DEFAULT_MACHINE_TYPE + + cluster_params = + params.merge(user: current_user) + + project.create_cluster(cluster_params).tap do |cluster| + ClusterProvisionWorker.perform_async(cluster.id) if cluster.persisted? + end + end + end +end diff --git a/app/services/clusters/gcp/fetch_operation_service.rb b/app/services/clusters/gcp/fetch_operation_service.rb new file mode 100644 index 00000000000..013225efac4 --- /dev/null +++ b/app/services/clusters/gcp/fetch_operation_service.rb @@ -0,0 +1,16 @@ +module Clusters + module Gcp + class FetchOperationService + def execute(provider) + operation = provider.api_client.projects_zones_operations( + provider.project_id, + provider.cluster_zone, + provider.operation_id) + + yield(operation) if block_given? + rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e + return provider.make_errored!("Failed to request to CloudPlatform; #{e.message}") + end + end + end +end diff --git a/app/services/clusters/gcp/finalize_creation_service.rb b/app/services/clusters/gcp/finalize_creation_service.rb new file mode 100644 index 00000000000..b536285b368 --- /dev/null +++ b/app/services/clusters/gcp/finalize_creation_service.rb @@ -0,0 +1,66 @@ +module Clusters + module Gcp + class FinalizeCreationService + attr_reader :provider + + def execute(provider) + @provider = provider + + configure_provider + configure_kubernetes_platform + request_kuberenetes_platform_token + + ActiveRecord::Base.transaction do + kubernetes_platform.update! + provider.make_created! + end + rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e + return cluster.make_errored!("Failed to request to CloudPlatform; #{e.message}") + rescue ActiveRecord::RecordInvalid => e + cluster.make_errored!("Failed to configure GKE Cluster: #{e.message}") + end + + private + + def configure_provider + provider.endpoint = gke_cluster.endpoint + end + + def configure_kubernetes_platform + kubernetes_platform = cluster.kubernetes_platform + kubernetes_platform.api_url = 'https://' + endpoint + kubernetes_platform.ca_cert = Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate) + kubernetes_platform.username = gke_cluster.master_auth.username + kubernetes_platform.password = gke_cluster.master_auth.password + end + + def request_kuberenetes_platform_token + kubernetes_platform.read_secrets.each do |secret| + name = secret.dig('metadata', 'name') + if /default-token/ =~ name + token_base64 = secret.dig('data', 'token') + if token_base64 + kubernetes_platform.token = Base64.decode64(token_base64) + break + end + end + end + end + + def gke_cluster + @gke_cluster ||= provider.api_client.projects_zones_clusters_get( + provider.gcp_project_id, + provider.gcp_cluster_zone, + provider.gcp_cluster_name) + end + + def cluster + provider.cluster + end + + def kubernetes_platform + cluster.kubernetes_platform + end + end + end +end diff --git a/app/services/clusters/gcp/provision_service.rb b/app/services/clusters/gcp/provision_service.rb new file mode 100644 index 00000000000..269705000ac --- /dev/null +++ b/app/services/clusters/gcp/provision_service.rb @@ -0,0 +1,49 @@ +module Clusters + module Gcp + class ProvisionService + attr_reader :provider + + def execute(provider) + @provider = provider + + unless operation.status == 'RUNNING' || operation.status == 'PENDING' + return provider.make_errored!("Operation status is unexpected; #{operation.status_message}") + end + + provider.operation_id = operation_id + + unless provider.operation_id + return provider.make_errored!('Can not find operation_id from self_link') + end + + if provider.make_creating + WaitForClusterCreationWorker.perform_in( + WaitForClusterCreationWorker::INITIAL_INTERVAL, provider.id) + else + return provider.make_errored!("Failed to update provider record; #{provider.errors}") + end + rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e + return provider.make_errored!("Failed to request to CloudPlatform; #{e.message}") + end + + private + + def operation_id + api_client.parse_operation_id(operation.self_link) + end + + def operation + @operation ||= api_client.projects_zones_providers_create( + provider.project_id, + provider.provider_zone, + provider.provider_name, + provider.provider_size, + machine_type: provider.machine_type) + end + + def api_client + provider.api_client + end + end + end +end diff --git a/app/services/clusters/gcp/verify_provision_status_service.rb b/app/services/clusters/gcp/verify_provision_status_service.rb new file mode 100644 index 00000000000..466ea986516 --- /dev/null +++ b/app/services/clusters/gcp/verify_provision_status_service.rb @@ -0,0 +1,44 @@ +module Clusters + module Gcp + class VerifyProvisionStatusService + attr_reader :provider + + INITIAL_INTERVAL = 2.minutes + EAGER_INTERVAL = 10.seconds + TIMEOUT = 20.minutes + + def execute(provider) + @provider = provider + + request_operation do |operation| + case operation.status + when 'RUNNING' + continue_creation(operation) + when 'DONE' + finalize_creation + else + return provider.make_errored!("Unexpected operation status; #{operation.status} #{operation.status_message}") + end + end + end + + private + + def continue_creation(operation) + if TIMEOUT < Time.now.utc - operation.start_time.to_time.utc + return provider.make_errored!("Cluster creation time exceeds timeout; #{TIMEOUT}") + end + + WaitForClusterCreationWorker.perform_in(EAGER_INTERVAL, provider.cluster_id) + end + + def finalize_creation + Clusters::Gcp::FinalizeCreationService.new.execute(provider) + end + + def request_operation(&blk) + Clusters::FetchGcpOperationService.new.execute(provider, &blk) + end + end + end +end diff --git a/app/services/clusters/update_service.rb b/app/services/clusters/update_service.rb new file mode 100644 index 00000000000..989218e32a2 --- /dev/null +++ b/app/services/clusters/update_service.rb @@ -0,0 +1,7 @@ +module Clusters + class UpdateService < BaseService + def execute(cluster) + cluster.update(params) + end + end +end |