From fabc359e77c39aea86f0eaa9f19b17b2a609dd99 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Thu, 28 Sep 2017 18:11:17 +0900 Subject: Multithreading cluster creation is done with `reactive_cache` --- app/services/ci/create_cluster_service.rb | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 app/services/ci/create_cluster_service.rb (limited to 'app/services/ci') diff --git a/app/services/ci/create_cluster_service.rb b/app/services/ci/create_cluster_service.rb new file mode 100644 index 00000000000..bbf42ab2c8d --- /dev/null +++ b/app/services/ci/create_cluster_service.rb @@ -0,0 +1,29 @@ +module Ci + class CreateClusterService < BaseService + UnexpectedOperationError = Class.new(StandardError) + + def create_cluster_on_gke(api_client) + # Create a cluster on GKE + operation = api_client.projects_zones_clusters_create( + params['gcp_project_id'], params['cluster_zone'], params['cluster_name'], + cluster_size: params['cluster_size'], machine_type: params['machine_type'] + ) + + if operation&.status != ('RUNNING' || 'PENDING') + raise UnexpectedOperationError + end + + api_client.parse_self_link(operation.self_link).tap do |project_id, zone, operation_id| + project.clusters.create(owner: current_user, + gcp_project_id: params['gcp_project_id'], + cluster_zone: params['cluster_zone'], + cluster_name: params['cluster_name'], + project_namespace: params['project_namespace'], + gcp_operation_id: operation_id).tap do |cluster| + # Start status polling. When the operation finish, create KubernetesService. + cluster.creation_status(api_client.access_token) + end + end + end + end +end -- cgit v1.2.1 From bda1b0a878205ac99bf10c0b4f0e63f2d4e3a25f Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 29 Sep 2017 00:08:11 +0900 Subject: Databse foreing key, index, encrypt password. Use short path. Improve error handling. Polish. --- app/services/ci/create_cluster_service.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/services/ci') diff --git a/app/services/ci/create_cluster_service.rb b/app/services/ci/create_cluster_service.rb index bbf42ab2c8d..edae245ec38 100644 --- a/app/services/ci/create_cluster_service.rb +++ b/app/services/ci/create_cluster_service.rb @@ -10,11 +10,11 @@ module Ci ) if operation&.status != ('RUNNING' || 'PENDING') - raise UnexpectedOperationError + raise UnexpectedOperationError.new(operation&.status_message) end api_client.parse_self_link(operation.self_link).tap do |project_id, zone, operation_id| - project.clusters.create(owner: current_user, + project.clusters.create(user: current_user, gcp_project_id: params['gcp_project_id'], cluster_zone: params['cluster_zone'], cluster_name: params['cluster_name'], -- cgit v1.2.1 From e499c1c39dbea505858874ee47436641df3d93d4 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Sun, 1 Oct 2017 00:54:22 +0900 Subject: Replace reactive_cache by multipel sidekiq workers --- app/services/ci/create_cluster_service.rb | 29 ++++------------------ app/services/ci/integrate_cluster_service.rb | 36 ++++++++++++++++++++++++++++ app/services/ci/update_cluster_service.rb | 26 ++++++++++++++++++++ 3 files changed, 67 insertions(+), 24 deletions(-) create mode 100644 app/services/ci/integrate_cluster_service.rb create mode 100644 app/services/ci/update_cluster_service.rb (limited to 'app/services/ci') diff --git a/app/services/ci/create_cluster_service.rb b/app/services/ci/create_cluster_service.rb index edae245ec38..86820706831 100644 --- a/app/services/ci/create_cluster_service.rb +++ b/app/services/ci/create_cluster_service.rb @@ -1,29 +1,10 @@ module Ci class CreateClusterService < BaseService - UnexpectedOperationError = Class.new(StandardError) - - def create_cluster_on_gke(api_client) - # Create a cluster on GKE - operation = api_client.projects_zones_clusters_create( - params['gcp_project_id'], params['cluster_zone'], params['cluster_name'], - cluster_size: params['cluster_size'], machine_type: params['machine_type'] - ) - - if operation&.status != ('RUNNING' || 'PENDING') - raise UnexpectedOperationError.new(operation&.status_message) - end - - api_client.parse_self_link(operation.self_link).tap do |project_id, zone, operation_id| - project.clusters.create(user: current_user, - gcp_project_id: params['gcp_project_id'], - cluster_zone: params['cluster_zone'], - cluster_name: params['cluster_name'], - project_namespace: params['project_namespace'], - gcp_operation_id: operation_id).tap do |cluster| - # Start status polling. When the operation finish, create KubernetesService. - cluster.creation_status(api_client.access_token) - end - end + def execute(access_token) + project.clusters.create( + params.merge(user: current_user, + status: Ci::Cluster.statuses[:scheduled], + gcp_token: access_token)) end end end diff --git a/app/services/ci/integrate_cluster_service.rb b/app/services/ci/integrate_cluster_service.rb new file mode 100644 index 00000000000..d5b1ccd345d --- /dev/null +++ b/app/services/ci/integrate_cluster_service.rb @@ -0,0 +1,36 @@ +module Ci + class IntegrateClusterService + def execute(cluster, endpoint, ca_cert, token, username, password) + kubernetes_service ||= cluster.project.find_or_initialize_service('kubernetes') + + Ci::Cluster.transaction do + # Update service + kubernetes_service.attributes = { + active: true, + api_url: endpoint, + ca_pem: ca_cert, + namespace: cluster.project_namespace, + token: token + } + + kubernetes_service.save! + + # Save info in cluster record + cluster.update!( + enabled: true, + service: kubernetes_service, + username: username, + password: password, + kubernetes_token: token, + ca_cert: ca_cert, + endpoint: endpoint, + gcp_token: nil, + status: Ci::Cluster.statuses[:created] + ) + end + + rescue ActiveRecord::RecordInvalid => e + cluster.error!("Failed to integrate cluster into kubernetes_service: #{e.message}") + end + end +end diff --git a/app/services/ci/update_cluster_service.rb b/app/services/ci/update_cluster_service.rb new file mode 100644 index 00000000000..0b458e27b90 --- /dev/null +++ b/app/services/ci/update_cluster_service.rb @@ -0,0 +1,26 @@ +module Ci + class UpdateClusterService < BaseService + def execute(cluster) + Ci::Cluster.transaction do + if params['enabled'] == 'true' + + cluster.service.attributes = { + active: true, + api_url: cluster.endpoint, + ca_pem: cluster.ca_cert, + namespace: cluster.project_namespace, + token: cluster.kubernetes_token + } + + cluster.service.save! + else + cluster.service.update(active: false) + end + + cluster.update!(enabled: params['enabled']) + end + rescue ActiveRecord::RecordInvalid => e + cluster.errors.add(:base, e.message) + end + end +end -- cgit v1.2.1 From 2d1a77b8a3567cae61f73196918fe365d4fe9415 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Sun, 1 Oct 2017 17:48:21 +0900 Subject: Revert KubernetesService. Introduce FetchKubernetesTokenService. --- app/services/ci/create_cluster_service.rb | 4 ++ app/services/ci/fetch_kubernetes_token_service.rb | 70 +++++++++++++++++++++++ app/services/ci/integrate_cluster_service.rb | 27 ++++----- app/services/ci/update_cluster_service.rb | 14 ++--- 4 files changed, 90 insertions(+), 25 deletions(-) create mode 100644 app/services/ci/fetch_kubernetes_token_service.rb (limited to 'app/services/ci') diff --git a/app/services/ci/create_cluster_service.rb b/app/services/ci/create_cluster_service.rb index 86820706831..b5fb71f5092 100644 --- a/app/services/ci/create_cluster_service.rb +++ b/app/services/ci/create_cluster_service.rb @@ -1,6 +1,10 @@ module Ci class CreateClusterService < BaseService def execute(access_token) + if params['machine_type'].blank? + params['machine_type'] = GoogleApi::CloudPlatform::Client::DEFAULT_MACHINE_TYPE + end + project.clusters.create( params.merge(user: current_user, status: Ci::Cluster.statuses[:scheduled], diff --git a/app/services/ci/fetch_kubernetes_token_service.rb b/app/services/ci/fetch_kubernetes_token_service.rb new file mode 100644 index 00000000000..013e4f12682 --- /dev/null +++ b/app/services/ci/fetch_kubernetes_token_service.rb @@ -0,0 +1,70 @@ +## +# TODO: +# Almost components in this class were copied from app/models/project_services/kubernetes_service.rb +# We should dry up those classes not to repeat the same code. +# Maybe we should have a special facility (e.g. lib/kubernetes_api) to maintain all Kubernetes API caller. +module Ci + class FetchKubernetesTokenService + attr_reader :api_url, :ca_pem, :username, :password + + def initialize(api_url, ca_pem, username, password) + @api_url = api_url + @ca_pem = ca_pem + @username = username + @password = password + end + + def execute + read_secrets.each do |secret| + name = secret.dig('metadata', 'name') + if /default-token/ =~ name + token_base64 = secret.dig('data', 'token') + return Base64.decode64(token_base64) if token_base64 + end + end + end + + private + + def read_secrets + kubeclient = build_kubeclient! + + kubeclient.get_secrets.as_json + rescue KubeException => err + raise err unless err.error_code == 404 + [] + end + + def build_kubeclient!(api_path: 'api', api_version: 'v1') + raise "Incomplete settings" unless api_url && username && password + + ::Kubeclient::Client.new( + join_api_url(api_path), + api_version, + auth_options: { username: username, password: password }, + ssl_options: kubeclient_ssl_options, + http_proxy_uri: ENV['http_proxy'] + ) + end + + def join_api_url(api_path) + url = URI.parse(api_url) + prefix = url.path.sub(%r{/+\z}, '') + + url.path = [prefix, api_path].join("/") + + url.to_s + end + + def kubeclient_ssl_options + 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 + end +end diff --git a/app/services/ci/integrate_cluster_service.rb b/app/services/ci/integrate_cluster_service.rb index d5b1ccd345d..5dd1f2b3414 100644 --- a/app/services/ci/integrate_cluster_service.rb +++ b/app/services/ci/integrate_cluster_service.rb @@ -1,21 +1,10 @@ module Ci class IntegrateClusterService def execute(cluster, endpoint, ca_cert, token, username, password) - kubernetes_service ||= cluster.project.find_or_initialize_service('kubernetes') - Ci::Cluster.transaction do - # Update service - kubernetes_service.attributes = { - active: true, - api_url: endpoint, - ca_pem: ca_cert, - namespace: cluster.project_namespace, - token: token - } - - kubernetes_service.save! + kubernetes_service ||= + cluster.project.find_or_initialize_service('kubernetes') - # Save info in cluster record cluster.update!( enabled: true, service: kubernetes_service, @@ -25,10 +14,16 @@ module Ci ca_cert: ca_cert, endpoint: endpoint, gcp_token: nil, - status: Ci::Cluster.statuses[:created] - ) - end + gcp_operation_id: nil, + status: Ci::Cluster.statuses[:created]) + kubernetes_service.update!( + active: true, + api_url: cluster.api_url, + ca_pem: ca_cert, + namespace: cluster.project_namespace, + token: token) + end rescue ActiveRecord::RecordInvalid => e cluster.error!("Failed to integrate cluster into kubernetes_service: #{e.message}") end diff --git a/app/services/ci/update_cluster_service.rb b/app/services/ci/update_cluster_service.rb index 0b458e27b90..a440ac03a0b 100644 --- a/app/services/ci/update_cluster_service.rb +++ b/app/services/ci/update_cluster_service.rb @@ -2,22 +2,18 @@ module Ci class UpdateClusterService < BaseService def execute(cluster) Ci::Cluster.transaction do - if params['enabled'] == 'true' + cluster.update!(enabled: params['enabled']) - cluster.service.attributes = { + if params['enabled'] == 'true' + cluster.service.update!( active: true, - api_url: cluster.endpoint, + api_url: cluster.api_url, ca_pem: cluster.ca_cert, namespace: cluster.project_namespace, - token: cluster.kubernetes_token - } - - cluster.service.save! + token: cluster.kubernetes_token) else cluster.service.update(active: false) end - - cluster.update!(enabled: params['enabled']) end rescue ActiveRecord::RecordInvalid => e cluster.errors.add(:base, e.message) -- cgit v1.2.1 From 34e66c427dde2070c2c09a07ce08f991e46de92f Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Mon, 2 Oct 2017 21:58:50 +0900 Subject: PollingInterval, rename to gke_clusters, has_one :cluster --- app/services/ci/create_cluster_service.rb | 4 ++-- app/services/ci/integrate_cluster_service.rb | 19 +++---------------- app/services/ci/update_cluster_service.rb | 4 ++-- 3 files changed, 7 insertions(+), 20 deletions(-) (limited to 'app/services/ci') diff --git a/app/services/ci/create_cluster_service.rb b/app/services/ci/create_cluster_service.rb index b5fb71f5092..48d7c9aef23 100644 --- a/app/services/ci/create_cluster_service.rb +++ b/app/services/ci/create_cluster_service.rb @@ -5,9 +5,9 @@ module Ci params['machine_type'] = GoogleApi::CloudPlatform::Client::DEFAULT_MACHINE_TYPE end - project.clusters.create( + project.create_cluster( params.merge(user: current_user, - status: Ci::Cluster.statuses[:scheduled], + status: Gcp::Cluster.statuses[:scheduled], gcp_token: access_token)) end end diff --git a/app/services/ci/integrate_cluster_service.rb b/app/services/ci/integrate_cluster_service.rb index 5dd1f2b3414..c60d3722373 100644 --- a/app/services/ci/integrate_cluster_service.rb +++ b/app/services/ci/integrate_cluster_service.rb @@ -1,23 +1,10 @@ module Ci class IntegrateClusterService def execute(cluster, endpoint, ca_cert, token, username, password) - Ci::Cluster.transaction do - kubernetes_service ||= - cluster.project.find_or_initialize_service('kubernetes') + Gcp::Cluster.transaction do + cluster.created!(endpoint, ca_cert, token, username, password) - cluster.update!( - enabled: true, - service: kubernetes_service, - username: username, - password: password, - kubernetes_token: token, - ca_cert: ca_cert, - endpoint: endpoint, - gcp_token: nil, - gcp_operation_id: nil, - status: Ci::Cluster.statuses[:created]) - - kubernetes_service.update!( + cluster.service.update!( active: true, api_url: cluster.api_url, ca_pem: ca_cert, diff --git a/app/services/ci/update_cluster_service.rb b/app/services/ci/update_cluster_service.rb index a440ac03a0b..a517d6be0c7 100644 --- a/app/services/ci/update_cluster_service.rb +++ b/app/services/ci/update_cluster_service.rb @@ -1,7 +1,7 @@ module Ci class UpdateClusterService < BaseService def execute(cluster) - Ci::Cluster.transaction do + Gcp::Cluster.transaction do cluster.update!(enabled: params['enabled']) if params['enabled'] == 'true' @@ -12,7 +12,7 @@ module Ci namespace: cluster.project_namespace, token: cluster.kubernetes_token) else - cluster.service.update(active: false) + cluster.service.update!(active: false) end end rescue ActiveRecord::RecordInvalid => e -- cgit v1.2.1 From 6b7889f750c56962c0674467c3fbfd7976b9b44f Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Tue, 3 Oct 2017 23:44:06 +0900 Subject: Implement Policy. Use show instead of edit. Chnage db column. fix comments. dry up workers --- app/services/ci/create_cluster_service.rb | 8 ++--- app/services/ci/create_gke_cluster_service.rb | 37 ++++++++++++++++++++++ app/services/ci/fetch_gcp_operation_service.rb | 17 ++++++++++ .../ci/finalize_cluster_creation_service.rb | 33 +++++++++++++++++++ 4 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 app/services/ci/create_gke_cluster_service.rb create mode 100644 app/services/ci/fetch_gcp_operation_service.rb create mode 100644 app/services/ci/finalize_cluster_creation_service.rb (limited to 'app/services/ci') diff --git a/app/services/ci/create_cluster_service.rb b/app/services/ci/create_cluster_service.rb index 48d7c9aef23..2fb6df9d669 100644 --- a/app/services/ci/create_cluster_service.rb +++ b/app/services/ci/create_cluster_service.rb @@ -1,14 +1,14 @@ module Ci class CreateClusterService < BaseService def execute(access_token) - if params['machine_type'].blank? - params['machine_type'] = GoogleApi::CloudPlatform::Client::DEFAULT_MACHINE_TYPE - end + params['gcp_machine_type'] ||= GoogleApi::CloudPlatform::Client::DEFAULT_MACHINE_TYPE project.create_cluster( params.merge(user: current_user, status: Gcp::Cluster.statuses[:scheduled], - gcp_token: access_token)) + gcp_token: access_token)).tap do |cluster| + ClusterCreationWorker.perform_async(cluster.id) if cluster.persisted? + end end end end diff --git a/app/services/ci/create_gke_cluster_service.rb b/app/services/ci/create_gke_cluster_service.rb new file mode 100644 index 00000000000..2407de5fc75 --- /dev/null +++ b/app/services/ci/create_gke_cluster_service.rb @@ -0,0 +1,37 @@ +module Ci + class CreateGkeClusterService + def execute(cluster) + api_client = + GoogleApi::CloudPlatform::Client.new(cluster.gcp_token, nil) + + begin + operation = api_client.projects_zones_clusters_create( + cluster.gcp_project_id, + cluster.gcp_cluster_zone, + cluster.gcp_cluster_name, + cluster.gcp_cluster_size, + machine_type: cluster.gcp_machine_type + ) + rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e + return cluster.errored!("Failed to request to CloudPlatform; #{e.message}") + end + + unless operation.status == 'RUNNING' || operation.status == 'PENDING' + return cluster.errored!("Operation status is unexpected; #{operation.status_message}") + end + + operation_id = api_client.parse_operation_id(operation.self_link) + + unless operation_id + return cluster.errored!('Can not find operation_id from self_link') + end + + if cluster.creating!(operation_id) + WaitForClusterCreationWorker.perform_in( + WaitForClusterCreationWorker::INITIAL_INTERVAL, cluster.id) + else + return cluster.errored!("Failed to update cluster record; #{cluster.errors}") + end + end + end +end diff --git a/app/services/ci/fetch_gcp_operation_service.rb b/app/services/ci/fetch_gcp_operation_service.rb new file mode 100644 index 00000000000..24892d1ab47 --- /dev/null +++ b/app/services/ci/fetch_gcp_operation_service.rb @@ -0,0 +1,17 @@ +module Ci + class FetchGcpOperationService + def execute(cluster) + api_client = + GoogleApi::CloudPlatform::Client.new(cluster.gcp_token, nil) + + operation = api_client.projects_zones_operations( + cluster.gcp_project_id, + cluster.gcp_cluster_zone, + cluster.gcp_operation_id) + + yield(operation) if block_given? + rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e + return cluster.errored!("Failed to request to CloudPlatform; #{e.message}") + end + end +end diff --git a/app/services/ci/finalize_cluster_creation_service.rb b/app/services/ci/finalize_cluster_creation_service.rb new file mode 100644 index 00000000000..03cd761deb7 --- /dev/null +++ b/app/services/ci/finalize_cluster_creation_service.rb @@ -0,0 +1,33 @@ +module Ci + class FinalizeClusterCreationService + def execute(cluster) + api_client = + GoogleApi::CloudPlatform::Client.new(cluster.gcp_token, nil) + + begin + gke_cluster = api_client.projects_zones_clusters_get( + cluster.gcp_project_id, + cluster.gcp_cluster_zone, + cluster.gcp_cluster_name) + rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e + return cluster.errored!("Failed to request to CloudPlatform; #{e.message}") + end + + endpoint = gke_cluster.endpoint + api_url = 'https://' + endpoint + ca_cert = Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate) + username = gke_cluster.master_auth.username + password = gke_cluster.master_auth.password + + kubernetes_token = Ci::FetchKubernetesTokenService.new( + api_url, ca_cert, username, password).execute + + unless kubernetes_token + return cluster.errored!('Failed to get a default token of kubernetes') + end + + Ci::IntegrateClusterService.new.execute( + cluster, endpoint, ca_cert, kubernetes_token, username, password) + end + end +end -- cgit v1.2.1 From e8e2a2103a806873f338da4b1de21a3df9c65502 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 3 Oct 2017 23:24:32 +0200 Subject: Rename to ClusterProvisionWorker and CreateGkeClusterService.new.execute --- app/services/ci/create_cluster_service.rb | 2 +- app/services/ci/create_gke_cluster_service.rb | 37 --------------------------- app/services/ci/provision_cluster_service.rb | 37 +++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 38 deletions(-) delete mode 100644 app/services/ci/create_gke_cluster_service.rb create mode 100644 app/services/ci/provision_cluster_service.rb (limited to 'app/services/ci') diff --git a/app/services/ci/create_cluster_service.rb b/app/services/ci/create_cluster_service.rb index 2fb6df9d669..179dfa0c6bb 100644 --- a/app/services/ci/create_cluster_service.rb +++ b/app/services/ci/create_cluster_service.rb @@ -7,7 +7,7 @@ module Ci params.merge(user: current_user, status: Gcp::Cluster.statuses[:scheduled], gcp_token: access_token)).tap do |cluster| - ClusterCreationWorker.perform_async(cluster.id) if cluster.persisted? + ClusterProvisionWorker.perform_async(cluster.id) if cluster.persisted? end end end diff --git a/app/services/ci/create_gke_cluster_service.rb b/app/services/ci/create_gke_cluster_service.rb deleted file mode 100644 index 2407de5fc75..00000000000 --- a/app/services/ci/create_gke_cluster_service.rb +++ /dev/null @@ -1,37 +0,0 @@ -module Ci - class CreateGkeClusterService - def execute(cluster) - api_client = - GoogleApi::CloudPlatform::Client.new(cluster.gcp_token, nil) - - begin - operation = api_client.projects_zones_clusters_create( - cluster.gcp_project_id, - cluster.gcp_cluster_zone, - cluster.gcp_cluster_name, - cluster.gcp_cluster_size, - machine_type: cluster.gcp_machine_type - ) - rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e - return cluster.errored!("Failed to request to CloudPlatform; #{e.message}") - end - - unless operation.status == 'RUNNING' || operation.status == 'PENDING' - return cluster.errored!("Operation status is unexpected; #{operation.status_message}") - end - - operation_id = api_client.parse_operation_id(operation.self_link) - - unless operation_id - return cluster.errored!('Can not find operation_id from self_link') - end - - if cluster.creating!(operation_id) - WaitForClusterCreationWorker.perform_in( - WaitForClusterCreationWorker::INITIAL_INTERVAL, cluster.id) - else - return cluster.errored!("Failed to update cluster record; #{cluster.errors}") - end - end - end -end diff --git a/app/services/ci/provision_cluster_service.rb b/app/services/ci/provision_cluster_service.rb new file mode 100644 index 00000000000..3e7e565b361 --- /dev/null +++ b/app/services/ci/provision_cluster_service.rb @@ -0,0 +1,37 @@ +module Ci + class ProvisionClusterService + def execute(cluster) + api_client = + GoogleApi::CloudPlatform::Client.new(cluster.gcp_token, nil) + + begin + operation = api_client.projects_zones_clusters_create( + cluster.gcp_project_id, + cluster.gcp_cluster_zone, + cluster.gcp_cluster_name, + cluster.gcp_cluster_size, + machine_type: cluster.gcp_machine_type + ) + rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e + return cluster.errored!("Failed to request to CloudPlatform; #{e.message}") + end + + unless operation.status == 'RUNNING' || operation.status == 'PENDING' + return cluster.errored!("Operation status is unexpected; #{operation.status_message}") + end + + cluster.gcp_operation_id = api_client.parse_operation_id(operation.self_link) + + unless cluster.gcp_operation_id + return cluster.errored!('Can not find operation_id from self_link') + end + + if cluster.creating + WaitForClusterCreationWorker.perform_in( + WaitForClusterCreationWorker::INITIAL_INTERVAL, cluster.id) + else + return cluster.errored!("Failed to update cluster record; #{cluster.errors}") + end + end + end +end -- cgit v1.2.1 From c471430a13c79a82555ee171fecdf45b882a3c19 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 3 Oct 2017 23:26:26 +0200 Subject: Gcp::Cluster improvements - introduce state machine - use before transitions to clear data - introduce namespace validation --- app/services/ci/integrate_cluster_service.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'app/services/ci') diff --git a/app/services/ci/integrate_cluster_service.rb b/app/services/ci/integrate_cluster_service.rb index c60d3722373..959c425fe74 100644 --- a/app/services/ci/integrate_cluster_service.rb +++ b/app/services/ci/integrate_cluster_service.rb @@ -2,7 +2,15 @@ module Ci class IntegrateClusterService def execute(cluster, endpoint, ca_cert, token, username, password) Gcp::Cluster.transaction do - cluster.created!(endpoint, ca_cert, token, username, password) + cluster.update!( + enabled: true, + endpoint: endpoint, + ca_cert: ca_cert, + kubernetes_token: token, + username: username, + password: password, + service: project.find_or_initialize_service('kubernetes'), + status_event: :created) cluster.service.update!( active: true, -- cgit v1.2.1 From c6d53250de7f439bc25740913d85ada6e3b2fed4 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 4 Oct 2017 00:20:47 +0200 Subject: Specify defaults, fix policies, fix db columns --- app/services/ci/integrate_cluster_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/services/ci') diff --git a/app/services/ci/integrate_cluster_service.rb b/app/services/ci/integrate_cluster_service.rb index 959c425fe74..ae7dccb0f42 100644 --- a/app/services/ci/integrate_cluster_service.rb +++ b/app/services/ci/integrate_cluster_service.rb @@ -9,7 +9,7 @@ module Ci kubernetes_token: token, username: username, password: password, - service: project.find_or_initialize_service('kubernetes'), + service: cluster.project.find_or_initialize_service('kubernetes'), status_event: :created) cluster.service.update!( -- cgit v1.2.1 From 20abcbffae71f8177223f2b978c8ad56102da271 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 4 Oct 2017 16:04:45 +0900 Subject: Add google_api to TOP_LEVEL_ROUTES. Import/Export model failure fix. Fix static analysys. --- app/services/ci/fetch_gcp_operation_service.rb | 2 +- app/services/ci/finalize_cluster_creation_service.rb | 2 +- app/services/ci/provision_cluster_service.rb | 11 +++++------ 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'app/services/ci') diff --git a/app/services/ci/fetch_gcp_operation_service.rb b/app/services/ci/fetch_gcp_operation_service.rb index 24892d1ab47..415afaf901f 100644 --- a/app/services/ci/fetch_gcp_operation_service.rb +++ b/app/services/ci/fetch_gcp_operation_service.rb @@ -1,7 +1,7 @@ module Ci class FetchGcpOperationService def execute(cluster) - api_client = + api_client = GoogleApi::CloudPlatform::Client.new(cluster.gcp_token, nil) operation = api_client.projects_zones_operations( diff --git a/app/services/ci/finalize_cluster_creation_service.rb b/app/services/ci/finalize_cluster_creation_service.rb index 03cd761deb7..a469acc0467 100644 --- a/app/services/ci/finalize_cluster_creation_service.rb +++ b/app/services/ci/finalize_cluster_creation_service.rb @@ -1,7 +1,7 @@ module Ci class FinalizeClusterCreationService def execute(cluster) - api_client = + api_client = GoogleApi::CloudPlatform::Client.new(cluster.gcp_token, nil) begin diff --git a/app/services/ci/provision_cluster_service.rb b/app/services/ci/provision_cluster_service.rb index 3e7e565b361..6fcbdd8b483 100644 --- a/app/services/ci/provision_cluster_service.rb +++ b/app/services/ci/provision_cluster_service.rb @@ -6,12 +6,11 @@ module Ci begin operation = api_client.projects_zones_clusters_create( - cluster.gcp_project_id, - cluster.gcp_cluster_zone, - cluster.gcp_cluster_name, - cluster.gcp_cluster_size, - machine_type: cluster.gcp_machine_type - ) + cluster.gcp_project_id, + cluster.gcp_cluster_zone, + cluster.gcp_cluster_name, + cluster.gcp_cluster_size, + machine_type: cluster.gcp_machine_type) rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e return cluster.errored!("Failed to request to CloudPlatform; #{e.message}") end -- cgit v1.2.1 From ea4af856e49cf5933b6995965fa7d6b922e38c20 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 4 Oct 2017 15:14:01 +0200 Subject: Fix cluster event names to be prefixed with: `make_` --- app/services/ci/fetch_gcp_operation_service.rb | 2 +- app/services/ci/finalize_cluster_creation_service.rb | 4 ++-- app/services/ci/integrate_cluster_service.rb | 2 +- app/services/ci/provision_cluster_service.rb | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'app/services/ci') diff --git a/app/services/ci/fetch_gcp_operation_service.rb b/app/services/ci/fetch_gcp_operation_service.rb index 415afaf901f..0b68e4d6ea9 100644 --- a/app/services/ci/fetch_gcp_operation_service.rb +++ b/app/services/ci/fetch_gcp_operation_service.rb @@ -11,7 +11,7 @@ module Ci yield(operation) if block_given? rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e - return cluster.errored!("Failed to request to CloudPlatform; #{e.message}") + return cluster.make_errored!("Failed to request to CloudPlatform; #{e.message}") end end end diff --git a/app/services/ci/finalize_cluster_creation_service.rb b/app/services/ci/finalize_cluster_creation_service.rb index a469acc0467..347875c5697 100644 --- a/app/services/ci/finalize_cluster_creation_service.rb +++ b/app/services/ci/finalize_cluster_creation_service.rb @@ -10,7 +10,7 @@ module Ci cluster.gcp_cluster_zone, cluster.gcp_cluster_name) rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e - return cluster.errored!("Failed to request to CloudPlatform; #{e.message}") + return cluster.make_errored!("Failed to request to CloudPlatform; #{e.message}") end endpoint = gke_cluster.endpoint @@ -23,7 +23,7 @@ module Ci api_url, ca_cert, username, password).execute unless kubernetes_token - return cluster.errored!('Failed to get a default token of kubernetes') + return cluster.make_errored!('Failed to get a default token of kubernetes') end Ci::IntegrateClusterService.new.execute( diff --git a/app/services/ci/integrate_cluster_service.rb b/app/services/ci/integrate_cluster_service.rb index ae7dccb0f42..857bca3f953 100644 --- a/app/services/ci/integrate_cluster_service.rb +++ b/app/services/ci/integrate_cluster_service.rb @@ -10,7 +10,7 @@ module Ci username: username, password: password, service: cluster.project.find_or_initialize_service('kubernetes'), - status_event: :created) + status_event: :make_created) cluster.service.update!( active: true, diff --git a/app/services/ci/provision_cluster_service.rb b/app/services/ci/provision_cluster_service.rb index 6fcbdd8b483..52d80b01813 100644 --- a/app/services/ci/provision_cluster_service.rb +++ b/app/services/ci/provision_cluster_service.rb @@ -12,24 +12,24 @@ module Ci cluster.gcp_cluster_size, machine_type: cluster.gcp_machine_type) rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e - return cluster.errored!("Failed to request to CloudPlatform; #{e.message}") + return cluster.make_errored!("Failed to request to CloudPlatform; #{e.message}") end unless operation.status == 'RUNNING' || operation.status == 'PENDING' - return cluster.errored!("Operation status is unexpected; #{operation.status_message}") + return cluster.make_errored!("Operation status is unexpected; #{operation.status_message}") end cluster.gcp_operation_id = api_client.parse_operation_id(operation.self_link) unless cluster.gcp_operation_id - return cluster.errored!('Can not find operation_id from self_link') + return cluster.make_errored!('Can not find operation_id from self_link') end - if cluster.creating + if cluster.make_creating WaitForClusterCreationWorker.perform_in( WaitForClusterCreationWorker::INITIAL_INTERVAL, cluster.id) else - return cluster.errored!("Failed to update cluster record; #{cluster.errors}") + return cluster.make_errored!("Failed to update cluster record; #{cluster.errors}") end end end -- cgit v1.2.1 From 07247601f3208fce65b3ac64ad3854dcc3dfd8c2 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 4 Oct 2017 22:13:10 +0200 Subject: Remove status enum from Gcp::Cluster, use state_machine#state --- app/services/ci/create_cluster_service.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'app/services/ci') diff --git a/app/services/ci/create_cluster_service.rb b/app/services/ci/create_cluster_service.rb index 179dfa0c6bb..d01e167ecc3 100644 --- a/app/services/ci/create_cluster_service.rb +++ b/app/services/ci/create_cluster_service.rb @@ -5,7 +5,6 @@ module Ci project.create_cluster( params.merge(user: current_user, - status: Gcp::Cluster.statuses[:scheduled], gcp_token: access_token)).tap do |cluster| ClusterProvisionWorker.perform_async(cluster.id) if cluster.persisted? end -- cgit v1.2.1 From 6b07aa5ec863706e58f781ee77ad54b54702c88a Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Thu, 5 Oct 2017 16:34:24 +0900 Subject: integrate_cluster_service_spec. provision_cluster_service_spec. update_cluster_service_spec. --- app/services/ci/integrate_cluster_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/services/ci') diff --git a/app/services/ci/integrate_cluster_service.rb b/app/services/ci/integrate_cluster_service.rb index 857bca3f953..d123ce8d26b 100644 --- a/app/services/ci/integrate_cluster_service.rb +++ b/app/services/ci/integrate_cluster_service.rb @@ -20,7 +20,7 @@ module Ci token: token) end rescue ActiveRecord::RecordInvalid => e - cluster.error!("Failed to integrate cluster into kubernetes_service: #{e.message}") + cluster.make_errored!("Failed to integrate cluster into kubernetes_service: #{e.message}") end end end -- cgit v1.2.1 From b229637b0837065a9993d06573b41218ab7e9dfb Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Thu, 5 Oct 2017 20:26:07 +0900 Subject: fetch_kubernetes_token_service_spec. Fix static analysys. --- app/services/ci/fetch_kubernetes_token_service.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/services/ci') diff --git a/app/services/ci/fetch_kubernetes_token_service.rb b/app/services/ci/fetch_kubernetes_token_service.rb index 013e4f12682..44da87cb00c 100644 --- a/app/services/ci/fetch_kubernetes_token_service.rb +++ b/app/services/ci/fetch_kubernetes_token_service.rb @@ -22,6 +22,8 @@ module Ci return Base64.decode64(token_base64) if token_base64 end end + + nil end private -- cgit v1.2.1 From e15fc89dd8f57f50cc5c15e6ad832eb2ebc6e985 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 5 Oct 2017 17:05:29 +0200 Subject: Added cluster controller specs --- app/services/ci/update_cluster_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/services/ci') diff --git a/app/services/ci/update_cluster_service.rb b/app/services/ci/update_cluster_service.rb index a517d6be0c7..70d88fca660 100644 --- a/app/services/ci/update_cluster_service.rb +++ b/app/services/ci/update_cluster_service.rb @@ -2,7 +2,7 @@ module Ci class UpdateClusterService < BaseService def execute(cluster) Gcp::Cluster.transaction do - cluster.update!(enabled: params['enabled']) + cluster.update!(params) if params['enabled'] == 'true' cluster.service.update!( -- cgit v1.2.1 From 4cda11585c75ce923d357b0dbb91fb393ed8e303 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 5 Oct 2017 21:33:29 +0200 Subject: Fix almost all unresolved comments from Docs and UX review --- app/services/ci/create_cluster_service.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'app/services/ci') diff --git a/app/services/ci/create_cluster_service.rb b/app/services/ci/create_cluster_service.rb index d01e167ecc3..f7ee0e468e2 100644 --- a/app/services/ci/create_cluster_service.rb +++ b/app/services/ci/create_cluster_service.rb @@ -3,9 +3,11 @@ module Ci def execute(access_token) params['gcp_machine_type'] ||= GoogleApi::CloudPlatform::Client::DEFAULT_MACHINE_TYPE - project.create_cluster( + cluster_params = params.merge(user: current_user, - gcp_token: access_token)).tap do |cluster| + gcp_token: access_token) + + project.create_cluster(cluster_params).tap do |cluster| ClusterProvisionWorker.perform_async(cluster.id) if cluster.persisted? end end -- cgit v1.2.1