Replace reactive_cache by multipel sidekiq workers
This commit is contained in:
parent
c30546f4aa
commit
e499c1c39d
|
|
@ -1,9 +1,9 @@
|
|||
module GoogleApi
|
||||
class AuthorizationsController < ApplicationController
|
||||
def callback
|
||||
session[GoogleApi::CloudPlatform::Client.token_in_session] =
|
||||
GoogleApi::Authentication.new(nil, callback_google_api_authorizations_url)
|
||||
.get_token(params[:code])
|
||||
session[GoogleApi::CloudPlatform::Client.session_key_for_token] =
|
||||
GoogleApi::CloudPlatform::Client.new(nil, callback_google_api_authorizations_url)
|
||||
.get_token(params[:code])
|
||||
|
||||
if params[:state]
|
||||
redirect_to params[:state]
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
class Projects::ClustersController < Projects::ApplicationController
|
||||
before_action :cluster, except: [:login, :index, :new, :create]
|
||||
before_action :authorize_google_api, except: [:login]
|
||||
# before_action :cluster_creation_lock, only: [:update, :destroy]
|
||||
# before_action :authorize_admin_clusters! # TODO: Authentication
|
||||
|
||||
def login
|
||||
begin
|
||||
@authorize_url = api_client.authorize_url
|
||||
rescue GoogleApi::Authentication::ConfigMissingError
|
||||
@authorize_url = GoogleApi::CloudPlatform::Client.new(
|
||||
nil,
|
||||
callback_google_api_authorizations_url,
|
||||
state: namespace_project_clusters_url.to_s
|
||||
).authorize_url
|
||||
rescue GoogleApi::Auth::ConfigMissingError
|
||||
# Show an alert message that gitlab.yml is not configured properly
|
||||
end
|
||||
end
|
||||
|
|
@ -20,28 +25,29 @@ class Projects::ClustersController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
@cluster = project.clusters.new
|
||||
end
|
||||
|
||||
def create
|
||||
begin
|
||||
Ci::CreateClusterService.new(project, current_user, params)
|
||||
.create_cluster_on_gke(api_client)
|
||||
rescue Ci::CreateClusterService::UnexpectedOperationError => e
|
||||
# TODO: error
|
||||
puts "#{self.class.name} - #{__callee__}: e: #{e}"
|
||||
end
|
||||
@cluster = Ci::CreateClusterService
|
||||
.new(project, current_user, cluster_params)
|
||||
.execute(token_in_session)
|
||||
|
||||
redirect_to project_clusters_path(project)
|
||||
if @cluster.persisted?
|
||||
ClusterCreationWorker.perform_async(@cluster.id)
|
||||
redirect_to project_clusters_path(project)
|
||||
else
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Return
|
||||
# @status: The current status of the operation.
|
||||
# @status_message: If an error has occurred, a textual description of the error.
|
||||
def creation_status
|
||||
def status
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: cluster.creation_status(session[GoogleApi::CloudPlatform::Client.token_in_session])
|
||||
render json: {
|
||||
status: cluster.status, # The current status of the operation.
|
||||
status_reason: cluster.status_reason # If an error has occurred, a textual description of the error.
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -50,24 +56,9 @@ class Projects::ClustersController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
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.token
|
||||
}
|
||||
|
||||
cluster.service.save!
|
||||
else
|
||||
cluster.service.update(active: false)
|
||||
end
|
||||
|
||||
cluster.update(enabled: params['enabled'])
|
||||
end
|
||||
Ci::UpdateClusterService
|
||||
.new(project, current_user, cluster_params)
|
||||
.execute(cluster)
|
||||
|
||||
render :edit
|
||||
end
|
||||
|
|
@ -88,18 +79,27 @@ class Projects::ClustersController < Projects::ApplicationController
|
|||
@cluster ||= project.clusters.find(params[:id])
|
||||
end
|
||||
|
||||
def api_client
|
||||
@api_client ||=
|
||||
GoogleApi::CloudPlatform::Client.new(
|
||||
session[GoogleApi::CloudPlatform::Client.token_in_session],
|
||||
callback_google_api_authorizations_url,
|
||||
state: namespace_project_clusters_url.to_s
|
||||
)
|
||||
def cluster_params
|
||||
params.require(:cluster)
|
||||
.permit(:gcp_project_id, :cluster_zone, :cluster_name, :cluster_size,
|
||||
:machine_type, :project_namespace, :enabled)
|
||||
end
|
||||
|
||||
def authorize_google_api
|
||||
unless session[GoogleApi::CloudPlatform::Client.token_in_session]
|
||||
unless token_in_session
|
||||
redirect_to action: 'login'
|
||||
end
|
||||
end
|
||||
|
||||
def token_in_session
|
||||
@token_in_session ||= session[GoogleApi::CloudPlatform::Client.session_key_for_token]
|
||||
end
|
||||
|
||||
def cluster_creation_lock
|
||||
if cluster.on_creation?
|
||||
redirect_to edit_project_cluster_path(project, cluster),
|
||||
status: :forbidden,
|
||||
alert: _("You can not modify cluster during creation")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,105 +1,45 @@
|
|||
module Ci
|
||||
class Cluster < ActiveRecord::Base
|
||||
extend Gitlab::Ci::Model
|
||||
include ReactiveCaching
|
||||
|
||||
self.reactive_cache_key = ->(cluster) { [cluster.class.model_name.singular, cluster.project_id, cluster.id] }
|
||||
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
belongs_to :service
|
||||
|
||||
attr_encrypted :password,
|
||||
mode: :per_attribute_iv_and_salt,
|
||||
insecure_mode: true,
|
||||
key: Gitlab::Application.secrets.db_key_base,
|
||||
algorithm: 'aes-256-cbc'
|
||||
mode: :per_attribute_iv_and_salt,
|
||||
insecure_mode: true,
|
||||
key: Gitlab::Application.secrets.db_key_base,
|
||||
algorithm: 'aes-256-cbc'
|
||||
|
||||
# after_save :clear_reactive_cache!
|
||||
attr_encrypted :kubernetes_token,
|
||||
mode: :per_attribute_iv_and_salt,
|
||||
insecure_mode: true,
|
||||
key: Gitlab::Application.secrets.db_key_base,
|
||||
algorithm: 'aes-256-cbc'
|
||||
|
||||
def creation_status(access_token)
|
||||
with_reactive_cache(access_token) do |operation|
|
||||
{
|
||||
status: operation[:status],
|
||||
status_message: operation[:status_message]
|
||||
}
|
||||
end
|
||||
attr_encrypted :gcp_token,
|
||||
mode: :per_attribute_iv_and_salt,
|
||||
insecure_mode: true,
|
||||
key: Gitlab::Application.secrets.db_key_base,
|
||||
algorithm: 'aes-256-cbc'
|
||||
|
||||
enum status: {
|
||||
unknown: nil,
|
||||
scheduled: 1,
|
||||
creating: 2,
|
||||
created: 3,
|
||||
errored: 4
|
||||
}
|
||||
|
||||
def error!(reason)
|
||||
update!(status: statuses[:errored],
|
||||
status_reason: reason,
|
||||
gcp_token: nil)
|
||||
end
|
||||
|
||||
def calculate_reactive_cache(access_token)
|
||||
return { status: 'INTEGRATED' } if service # If it's already done, we don't need to continue the following process
|
||||
|
||||
api_client = GoogleApi::CloudPlatform::Client.new(access_token, nil)
|
||||
operation = api_client.projects_zones_operations(gcp_project_id, cluster_zone, gcp_operation_id)
|
||||
|
||||
return { status_message: 'Failed to get a status' } unless operation
|
||||
|
||||
if operation.status == 'DONE'
|
||||
# Get cluster details (end point, etc)
|
||||
gke_cluster = api_client.projects_zones_clusters_get(
|
||||
gcp_project_id, cluster_zone, cluster_name
|
||||
)
|
||||
|
||||
return { status_message: 'Failed to get a cluster info on gke' } unless gke_cluster
|
||||
|
||||
# Get k8s token
|
||||
token = ''
|
||||
KubernetesService.new.tap do |ks|
|
||||
ks.api_url = 'https://' + gke_cluster.endpoint
|
||||
ks.ca_pem = Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate)
|
||||
ks.username = gke_cluster.master_auth.username
|
||||
ks.password = gke_cluster.master_auth.password
|
||||
secrets = ks.read_secrets
|
||||
secrets.each do |secret|
|
||||
name = secret.dig('metadata', 'name')
|
||||
if /default-token/ =~ name
|
||||
token_base64 = secret.dig('data', 'token')
|
||||
token = Base64.decode64(token_base64)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return { status_message: 'Failed to get a default token on kubernetes' } unless token
|
||||
|
||||
# k8s endpoint, ca_cert
|
||||
endpoint = 'https://' + gke_cluster.endpoint
|
||||
cluster_ca_certificate = Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate)
|
||||
|
||||
begin
|
||||
Ci::Cluster.transaction do
|
||||
# Update service
|
||||
kubernetes_service.attributes = {
|
||||
active: true,
|
||||
api_url: endpoint,
|
||||
ca_pem: cluster_ca_certificate,
|
||||
namespace: project_namespace,
|
||||
token: token
|
||||
}
|
||||
|
||||
kubernetes_service.save!
|
||||
|
||||
# Save info in cluster record
|
||||
update(
|
||||
enabled: true,
|
||||
service: kubernetes_service,
|
||||
username: gke_cluster.master_auth.username,
|
||||
password: gke_cluster.master_auth.password,
|
||||
token: token,
|
||||
ca_cert: cluster_ca_certificate,
|
||||
endpoint: endpoint,
|
||||
)
|
||||
end
|
||||
rescue ActiveRecord::RecordInvalid => exception
|
||||
return { status_message: 'Failed to setup integration' }
|
||||
end
|
||||
end
|
||||
|
||||
operation.to_h
|
||||
end
|
||||
|
||||
def kubernetes_service
|
||||
@kubernetes_service ||= project.find_or_initialize_service('kubernetes')
|
||||
def on_creation?
|
||||
scheduled? || creating?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
-link_to_help_page = link_to(s_('ClusterIntegration|help page'), help_page_path('TODO'), target: '_blank', rel: 'noopener noreferrer')
|
||||
= s_('ClusterIntegration|Use our %{link_to_help_page} on cluster integration.').html_safe % { link_to_help_page: link_to_help_page}
|
||||
|
||||
= form_for 'cluster' do |field|
|
||||
= form_for [@project.namespace.becomes(Namespace), @project, @cluster] do |field|
|
||||
.form-group
|
||||
= field.label :cluster_name
|
||||
= field.text_field :cluster_name, class: 'form-control'
|
||||
|
|
@ -32,4 +32,5 @@
|
|||
.form-group
|
||||
= field.submit s_('ClusterIntegration|Create cluster'), class: 'btn btn-save'
|
||||
|
||||
= link_to "Create on Google Container Engine", namespace_project_clusters_path(@project.namespace, @project, cluster_name: "gke-test-creation#{Random.rand(100)}", gcp_project_id: 'gitlab-internal-153318', cluster_zone: 'us-central1-a', cluster_size: '1', project_namespace: 'aaa', machine_type: '???'), method: :post
|
||||
-# TODO: Remove before merge
|
||||
= link_to "Create on Google Container Engine", namespace_project_clusters_path(@project.namespace, @project, cluster: {cluster_name: "gke-test-creation#{Random.rand(100)}", gcp_project_id: 'gitlab-internal-153318', cluster_zone: 'us-central1-a', cluster_size: '1', project_namespace: 'aaa', machine_type: '???'}), method: :post
|
||||
|
|
@ -2,7 +2,15 @@ edit/show cluster
|
|||
%br
|
||||
= @cluster.inspect
|
||||
= @cluster.service.inspect
|
||||
= link_to "Enable", namespace_project_cluster_path(@project.namespace, @project, @cluster.id, enabled: 'true'), method: :put
|
||||
= link_to "Disable", namespace_project_cluster_path(@project.namespace, @project, @cluster.id, enabled: 'false'), method: :put
|
||||
= link_to "Soft-delete the cluster", namespace_project_cluster_path(@project.namespace, @project, @cluster.id), method: :delete
|
||||
= link_to 'Check status', creation_status_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster.id), :remote => true
|
||||
- unless @cluster.on_creation?
|
||||
= link_to "Enable", namespace_project_cluster_path(@project.namespace, @project, @cluster.id, cluster: {enabled: 'true'}), method: :put
|
||||
= link_to "Disable", namespace_project_cluster_path(@project.namespace, @project, @cluster.id, cluster: {enabled: 'false'}), method: :put
|
||||
= link_to "Soft-delete the cluster", namespace_project_cluster_path(@project.namespace, @project, @cluster.id), method: :delete
|
||||
-# status GET
|
||||
-# status: The current status of the operation.
|
||||
-# status_reason: If an error has occurred, a textual description of the error.
|
||||
= link_to 'Check status', status_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster.id), :remote => true
|
||||
-# simply rendering error, if it happened
|
||||
- if @cluster.status_reason
|
||||
%p= status_reason
|
||||
-# Even if we got an error during the creation process, we don't delete cluster objects automatically, because we don't have a method to delete the cluster on gke. So users move to edit page from new page **regardless of validation errors**, and they have to delete the record manually. This is for giving users headsup that a new cluster might remain in gke. /cc @ayufan
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
class ClusterCreationWorker
|
||||
include Sidekiq::Worker
|
||||
include DedicatedSidekiqQueue
|
||||
|
||||
def perform(cluster_id)
|
||||
cluster = Ci::Cluster.find_by_id(cluster_id)
|
||||
|
||||
unless cluster
|
||||
return Rails.logger.error "Cluster object is not found; #{cluster_id}"
|
||||
end
|
||||
|
||||
api_client =
|
||||
GoogleApi::CloudPlatform::Client.new(cluster.gcp_token, nil)
|
||||
|
||||
operation = api_client.projects_zones_clusters_create(
|
||||
cluster.gcp_project_id,
|
||||
cluster.cluster_zone,
|
||||
cluster.cluster_name,
|
||||
cluster.cluster_size,
|
||||
machine_type: cluster.machine_type
|
||||
)
|
||||
|
||||
if operation.is_a?(StandardError)
|
||||
return cluster.error!("Failed to request to CloudPlatform; #{operation.message}")
|
||||
end
|
||||
|
||||
unless operation.status == 'RUNNING' || operation.status == 'PENDING'
|
||||
return cluster.error!("Operation status is unexpected; #{operation.status_message}")
|
||||
end
|
||||
|
||||
operation_id = api_client.parse_operation_id(operation.self_link)
|
||||
|
||||
unless operation_id
|
||||
return cluster.error!('Can not find operation_id from self_link')
|
||||
end
|
||||
|
||||
if cluster.update(status: Ci::Cluster.statuses[:creating],
|
||||
gcp_operation_id: operation_id)
|
||||
WaitForClusterCreationWorker.perform_in(
|
||||
WaitForClusterCreationWorker::INITIAL_INTERVAL,
|
||||
cluster.id
|
||||
)
|
||||
else
|
||||
return cluster.error!("Failed to update cluster record; #{cluster.errors}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
class WaitForClusterCreationWorker
|
||||
include Sidekiq::Worker
|
||||
include DedicatedSidekiqQueue
|
||||
|
||||
INITIAL_INTERVAL = 2.minutes
|
||||
EAGER_INTERVAL = 10.seconds
|
||||
TIMEOUT = 20.minutes
|
||||
|
||||
def perform(cluster_id)
|
||||
cluster = Ci::Cluster.find_by_id(cluster_id)
|
||||
|
||||
unless cluster
|
||||
return Rails.logger.error "Cluster object is not found; #{cluster_id}"
|
||||
end
|
||||
|
||||
api_client =
|
||||
GoogleApi::CloudPlatform::Client.new(cluster.gcp_token, nil)
|
||||
|
||||
operation = api_client.projects_zones_operations(
|
||||
cluster.gcp_project_id,
|
||||
cluster.cluster_zone,
|
||||
cluster.gcp_operation_id
|
||||
)
|
||||
|
||||
if operation.is_a?(StandardError)
|
||||
return cluster.error!("Failed to request to CloudPlatform; #{operation.message}")
|
||||
end
|
||||
|
||||
case operation.status
|
||||
when 'DONE'
|
||||
integrate(api_client, cluster)
|
||||
when 'RUNNING'
|
||||
if Time.now < operation.start_time.to_time + TIMEOUT
|
||||
WaitForClusterCreationWorker.perform_in(EAGER_INTERVAL, cluster.id)
|
||||
else
|
||||
return cluster.error!("Cluster creation time exceeds timeout; #{TIMEOUT}")
|
||||
end
|
||||
else
|
||||
return cluster.error!("Unexpected operation status; #{operation.status_message}")
|
||||
end
|
||||
end
|
||||
|
||||
def integrate(api_client, cluster)
|
||||
# Get cluster details (end point, etc)
|
||||
gke_cluster = api_client.projects_zones_clusters_get(
|
||||
cluster.gcp_project_id,
|
||||
cluster.cluster_zone,
|
||||
cluster.cluster_name
|
||||
)
|
||||
|
||||
if gke_cluster.is_a?(StandardError)
|
||||
return cluster.error!("Failed to request to CloudPlatform; #{gke_cluster.message}")
|
||||
end
|
||||
|
||||
# Get k8s token
|
||||
kubernetes_token = ''
|
||||
KubernetesService.new.tap do |ks|
|
||||
ks.api_url = 'https://' + gke_cluster.endpoint
|
||||
ks.ca_pem = Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate)
|
||||
ks.username = gke_cluster.master_auth.username
|
||||
ks.password = gke_cluster.master_auth.password
|
||||
secrets = ks.read_secrets
|
||||
secrets.each do |secret|
|
||||
name = secret.dig('metadata', 'name')
|
||||
if /default-token/ =~ name
|
||||
token_base64 = secret.dig('data', 'token')
|
||||
kubernetes_token = Base64.decode64(token_base64)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
unless kubernetes_token
|
||||
return cluster.error!('Failed to get a default token of kubernetes')
|
||||
end
|
||||
|
||||
# k8s endpoint, ca_cert
|
||||
endpoint = 'https://' + gke_cluster.endpoint
|
||||
ca_cert = Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate)
|
||||
username = gke_cluster.master_auth.username
|
||||
password = gke_cluster.master_auth.password
|
||||
|
||||
Ci::IntegrateClusterService.new.execute(cluster, endpoint, ca_cert, kubernetes_token, username, password)
|
||||
end
|
||||
end
|
||||
|
|
@ -189,7 +189,7 @@ constraints(ProjectUrlConstrainer.new) do
|
|||
end
|
||||
|
||||
member do
|
||||
get :creation_status, format: :json
|
||||
get :status, format: :json
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -62,3 +62,5 @@
|
|||
- [update_user_activity, 1]
|
||||
- [propagate_service_template, 1]
|
||||
- [background_migration, 1]
|
||||
- [cluster_creation, 1]
|
||||
- [wait_for_cluster_creation, 1]
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ class CreateCiClusters < ActiveRecord::Migration
|
|||
|
||||
# General
|
||||
t.boolean :enabled, default: true
|
||||
t.integer :status
|
||||
t.string :status_reason
|
||||
|
||||
# k8s integration specific
|
||||
t.string :project_namespace
|
||||
|
|
@ -16,9 +18,10 @@ class CreateCiClusters < ActiveRecord::Migration
|
|||
# Cluster details
|
||||
t.string :endpoint
|
||||
t.text :ca_cert
|
||||
t.string :token
|
||||
t.string :encrypted_kubernetes_token
|
||||
t.string :encrypted_kubernetes_token_salt
|
||||
t.string :encrypted_kubernetes_token_iv
|
||||
t.string :username
|
||||
t.string :password
|
||||
t.string :encrypted_password
|
||||
t.string :encrypted_password_salt
|
||||
t.string :encrypted_password_iv
|
||||
|
|
@ -27,7 +30,12 @@ class CreateCiClusters < ActiveRecord::Migration
|
|||
t.string :gcp_project_id
|
||||
t.string :cluster_zone
|
||||
t.string :cluster_name
|
||||
t.string :cluster_size
|
||||
t.string :machine_type
|
||||
t.string :gcp_operation_id
|
||||
t.string :encrypted_gcp_token
|
||||
t.string :encrypted_gcp_token_salt
|
||||
t.string :encrypted_gcp_token_iv
|
||||
|
||||
t.datetime_with_timezone :created_at, null: false
|
||||
t.datetime_with_timezone :updated_at, null: false
|
||||
|
|
|
|||
12
db/schema.rb
12
db/schema.rb
|
|
@ -272,19 +272,27 @@ ActiveRecord::Schema.define(version: 20170924094327) do
|
|||
t.integer "user_id", null: false
|
||||
t.integer "service_id"
|
||||
t.boolean "enabled", default: true
|
||||
t.integer "status"
|
||||
t.string "status_reason"
|
||||
t.string "project_namespace"
|
||||
t.string "endpoint"
|
||||
t.text "ca_cert"
|
||||
t.string "token"
|
||||
t.string "encrypted_kubernetes_token"
|
||||
t.string "encrypted_kubernetes_token_salt"
|
||||
t.string "encrypted_kubernetes_token_iv"
|
||||
t.string "username"
|
||||
t.string "password"
|
||||
t.string "encrypted_password"
|
||||
t.string "encrypted_password_salt"
|
||||
t.string "encrypted_password_iv"
|
||||
t.string "gcp_project_id"
|
||||
t.string "cluster_zone"
|
||||
t.string "cluster_name"
|
||||
t.string "cluster_size"
|
||||
t.string "machine_type"
|
||||
t.string "gcp_operation_id"
|
||||
t.string "encrypted_gcp_token"
|
||||
t.string "encrypted_gcp_token_salt"
|
||||
t.string "encrypted_gcp_token_iv"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
module GoogleApi
|
||||
class Authentication
|
||||
class Auth
|
||||
attr_reader :access_token, :redirect_uri, :state
|
||||
|
||||
ConfigMissingError = Class.new(StandardError)
|
||||
|
|
@ -2,9 +2,9 @@ require 'google/apis/container_v1'
|
|||
|
||||
module GoogleApi
|
||||
module CloudPlatform
|
||||
class Client < GoogleApi::Authentication
|
||||
class Client < GoogleApi::Auth
|
||||
class << self
|
||||
def token_in_session
|
||||
def session_key_for_token
|
||||
:cloud_platform_access_token
|
||||
end
|
||||
end
|
||||
|
|
@ -13,20 +13,14 @@ module GoogleApi
|
|||
'https://www.googleapis.com/auth/cloud-platform'
|
||||
end
|
||||
|
||||
##
|
||||
# Exception
|
||||
# Google::Apis::ClientError:
|
||||
# Google::Apis::AuthorizationError:
|
||||
##
|
||||
|
||||
def projects_zones_clusters_get(project_id, zone, cluster_id)
|
||||
service = Google::Apis::ContainerV1::ContainerService.new
|
||||
service.authorization = access_token
|
||||
|
||||
begin
|
||||
cluster = service.get_zone_cluster(project_id, zone, cluster_id)
|
||||
rescue Google::Apis::ClientError, Google::Apis::AuthorizationError => e
|
||||
return nil
|
||||
rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
|
||||
return e
|
||||
end
|
||||
|
||||
puts "#{self.class.name} - #{__callee__}: cluster: #{cluster.inspect}"
|
||||
|
|
@ -35,7 +29,7 @@ module GoogleApi
|
|||
|
||||
# Responce exmaple
|
||||
# TODO: machine_type : Defailt 3.75 GB
|
||||
def projects_zones_clusters_create(project_id, zone, cluster_name, cluster_size:, machine_type:)
|
||||
def projects_zones_clusters_create(project_id, zone, cluster_name, cluster_size, machine_type:)
|
||||
service = Google::Apis::ContainerV1::ContainerService.new
|
||||
service.authorization = access_token
|
||||
|
||||
|
|
@ -50,8 +44,8 @@ module GoogleApi
|
|||
|
||||
begin
|
||||
operation = service.create_cluster(project_id, zone, request_body)
|
||||
rescue Google::Apis::ClientError, Google::Apis::AuthorizationError => e
|
||||
return nil
|
||||
rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
|
||||
return e
|
||||
end
|
||||
|
||||
puts "#{self.class.name} - #{__callee__}: operation: #{operation.inspect}"
|
||||
|
|
@ -65,17 +59,15 @@ module GoogleApi
|
|||
begin
|
||||
operation = service.get_zone_operation(project_id, zone, operation_id)
|
||||
rescue Google::Apis::ClientError, Google::Apis::AuthorizationError => e
|
||||
return nil
|
||||
return e
|
||||
end
|
||||
|
||||
puts "#{self.class.name} - #{__callee__}: operation: #{operation.inspect}"
|
||||
operation
|
||||
end
|
||||
|
||||
def parse_self_link(self_link)
|
||||
ret = self_link.match(/projects\/(.*)\/zones\/(.*)\/operations\/(.*)/)
|
||||
|
||||
return ret[1], ret[2], ret[3] # project_id, zone, operation_id
|
||||
def parse_operation_id(self_link)
|
||||
self_link.match(/projects\/.*\/zones\/.*\/operations\/(.*)/)[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue