Databse foreing key, index, encrypt password. Use short path. Improve error handling. Polish.
This commit is contained in:
parent
fabc359e77
commit
bda1b0a878
|
|
@ -1,8 +1,6 @@
|
|||
module GoogleApi
|
||||
class AuthorizationsController < ApplicationController
|
||||
# /google_api/authorizations/callback(.:format)
|
||||
def callback
|
||||
# TODO: Error handling
|
||||
session[GoogleApi::CloudPlatform::Client.token_in_session] =
|
||||
GoogleApi::Authentication.new(nil, callback_google_api_authorizations_url)
|
||||
.get_token(params[:code])
|
||||
|
|
|
|||
|
|
@ -7,14 +7,15 @@ class Projects::ClustersController < Projects::ApplicationController
|
|||
begin
|
||||
@authorize_url = api_client.authorize_url
|
||||
rescue GoogleApi::Authentication::ConfigMissingError
|
||||
# Show an alert message that gitlab.yml is not configured properly
|
||||
end
|
||||
end
|
||||
|
||||
def index
|
||||
if project.clusters.any?
|
||||
redirect_to edit_namespace_project_cluster_path(project.namespace, project, project.clusters.last.id)
|
||||
redirect_to edit_project_cluster_path(project, project.clusters.last.id)
|
||||
else
|
||||
redirect_to action: 'new'
|
||||
redirect_to new_project_cluster_path(project)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -26,11 +27,11 @@ class Projects::ClustersController < Projects::ApplicationController
|
|||
Ci::CreateClusterService.new(project, current_user, params)
|
||||
.create_cluster_on_gke(api_client)
|
||||
rescue Ci::CreateClusterService::UnexpectedOperationError => e
|
||||
puts "#{self.class.name} - #{__callee__}: e: #{e}"
|
||||
# TODO: error
|
||||
puts "#{self.class.name} - #{__callee__}: e: #{e}"
|
||||
end
|
||||
|
||||
redirect_to action: 'index'
|
||||
redirect_to project_clusters_path(project)
|
||||
end
|
||||
|
||||
##
|
||||
|
|
@ -49,15 +50,36 @@ class Projects::ClustersController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
cluster.update(enabled: params['enabled'])
|
||||
cluster.service.update(active: params['enabled'])
|
||||
# TODO: Do we overwrite KubernetesService parameter?
|
||||
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
|
||||
|
||||
render :edit
|
||||
end
|
||||
|
||||
def destroy
|
||||
cluster.destroy
|
||||
redirect_to action: 'index'
|
||||
if cluster.destroy
|
||||
redirect_to project_clusters_path(project), status: 302
|
||||
else
|
||||
redirect_to project_clusters_path(project),
|
||||
status: :forbidden,
|
||||
alert: _("Failed to remove the cluster")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -6,9 +6,15 @@ module Ci
|
|||
self.reactive_cache_key = ->(cluster) { [cluster.class.model_name.singular, cluster.project_id, cluster.id] }
|
||||
|
||||
belongs_to :project
|
||||
belongs_to :owner, class_name: 'User'
|
||||
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'
|
||||
|
||||
# after_save :clear_reactive_cache!
|
||||
|
||||
def creation_status(access_token)
|
||||
|
|
@ -26,12 +32,16 @@ module Ci
|
|||
api_client = GoogleApi::CloudPlatform::Client.new(access_token, nil)
|
||||
operation = api_client.projects_zones_operations(gcp_project_id, cluster_zone, gcp_operation_id)
|
||||
|
||||
if operation&.status == 'DONE'
|
||||
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|
|
||||
|
|
@ -50,34 +60,41 @@ module Ci
|
|||
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)
|
||||
|
||||
# Update service
|
||||
kubernetes_service.attributes = {
|
||||
active: true,
|
||||
api_url: endpoint,
|
||||
ca_pem: cluster_ca_certificate,
|
||||
namespace: project_namespace,
|
||||
token: token
|
||||
}
|
||||
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!
|
||||
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,
|
||||
end_point: endpoint,
|
||||
)
|
||||
# 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
|
||||
|
||||
puts "#{self.class.name} - #{__callee__}: operation.to_json: #{operation.to_json}"
|
||||
operation.to_h
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -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'],
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ class CreateCiClusters < ActiveRecord::Migration
|
|||
|
||||
def up
|
||||
create_table :ci_clusters do |t|
|
||||
t.integer :project_id
|
||||
t.integer :owner_id
|
||||
t.integer :service_id
|
||||
t.references :project, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade }
|
||||
t.references :user, null: false, foreign_key: true
|
||||
t.references :service, foreign_key: true
|
||||
|
||||
# General
|
||||
t.boolean :enabled, default: true
|
||||
|
|
@ -14,11 +14,14 @@ class CreateCiClusters < ActiveRecord::Migration
|
|||
t.string :project_namespace
|
||||
|
||||
# Cluster details
|
||||
t.string :end_point
|
||||
t.string :endpoint
|
||||
t.text :ca_cert
|
||||
t.string :token
|
||||
t.string :username
|
||||
t.string :password
|
||||
t.string :encrypted_password
|
||||
t.string :encrypted_password_salt
|
||||
t.string :encrypted_password_iv
|
||||
|
||||
# GKE
|
||||
t.string :gcp_project_id
|
||||
|
|
@ -29,12 +32,6 @@ class CreateCiClusters < ActiveRecord::Migration
|
|||
t.datetime_with_timezone :created_at, null: false
|
||||
t.datetime_with_timezone :updated_at, null: false
|
||||
end
|
||||
|
||||
# TODO: fk, index, attr_encrypted
|
||||
|
||||
add_foreign_key :ci_clusters, :projects
|
||||
add_foreign_key :ci_clusters, :users, column: :owner_id
|
||||
add_foreign_key :ci_clusters, :services
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
|||
15
db/schema.rb
15
db/schema.rb
|
|
@ -268,16 +268,19 @@ ActiveRecord::Schema.define(version: 20170924094327) do
|
|||
add_index "ci_builds", ["user_id"], name: "index_ci_builds_on_user_id", using: :btree
|
||||
|
||||
create_table "ci_clusters", force: :cascade do |t|
|
||||
t.integer "project_id"
|
||||
t.integer "owner_id"
|
||||
t.integer "project_id", null: false
|
||||
t.integer "user_id", null: false
|
||||
t.integer "service_id"
|
||||
t.boolean "enabled", default: true
|
||||
t.string "project_namespace"
|
||||
t.string "end_point"
|
||||
t.string "endpoint"
|
||||
t.text "ca_cert"
|
||||
t.string "token"
|
||||
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"
|
||||
|
|
@ -286,6 +289,8 @@ ActiveRecord::Schema.define(version: 20170924094327) do
|
|||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
add_index "ci_clusters", ["project_id"], name: "index_ci_clusters_on_project_id", unique: true, using: :btree
|
||||
|
||||
create_table "ci_group_variables", force: :cascade do |t|
|
||||
t.string "key", null: false
|
||||
t.text "value"
|
||||
|
|
@ -1704,9 +1709,9 @@ ActiveRecord::Schema.define(version: 20170924094327) do
|
|||
add_foreign_key "ci_builds", "ci_pipelines", column: "auto_canceled_by_id", name: "fk_a2141b1522", on_delete: :nullify
|
||||
add_foreign_key "ci_builds", "ci_stages", column: "stage_id", name: "fk_3a9eaa254d", on_delete: :cascade
|
||||
add_foreign_key "ci_builds", "projects", name: "fk_befce0568a", on_delete: :cascade
|
||||
add_foreign_key "ci_clusters", "projects"
|
||||
add_foreign_key "ci_clusters", "projects", on_delete: :cascade
|
||||
add_foreign_key "ci_clusters", "services"
|
||||
add_foreign_key "ci_clusters", "users", column: "owner_id"
|
||||
add_foreign_key "ci_clusters", "users"
|
||||
add_foreign_key "ci_group_variables", "namespaces", column: "group_id", name: "fk_33ae4d58d8", on_delete: :cascade
|
||||
add_foreign_key "ci_pipeline_schedule_variables", "ci_pipeline_schedules", column: "pipeline_schedule_id", name: "fk_41c35fda51", on_delete: :cascade
|
||||
add_foreign_key "ci_pipeline_schedules", "projects", name: "fk_8ead60fcc4", on_delete: :cascade
|
||||
|
|
|
|||
|
|
@ -13,11 +13,22 @@ 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
|
||||
|
||||
cluster = service.get_zone_cluster(project_id, zone, cluster_id)
|
||||
begin
|
||||
cluster = service.get_zone_cluster(project_id, zone, cluster_id)
|
||||
rescue Google::Apis::ClientError, Google::Apis::AuthorizationError => e
|
||||
return nil
|
||||
end
|
||||
|
||||
puts "#{self.class.name} - #{__callee__}: cluster: #{cluster.inspect}"
|
||||
cluster
|
||||
end
|
||||
|
|
@ -40,9 +51,9 @@ module GoogleApi
|
|||
begin
|
||||
operation = service.create_cluster(project_id, zone, request_body)
|
||||
rescue Google::Apis::ClientError, Google::Apis::AuthorizationError => e
|
||||
puts "#{self.class.name} - #{__callee__}: Could not create cluster #{cluster_name}: #{e}"
|
||||
# TODO: Error
|
||||
return nil
|
||||
end
|
||||
|
||||
puts "#{self.class.name} - #{__callee__}: operation: #{operation.inspect}"
|
||||
operation
|
||||
end
|
||||
|
|
@ -51,7 +62,12 @@ module GoogleApi
|
|||
service = Google::Apis::ContainerV1::ContainerService.new
|
||||
service.authorization = access_token
|
||||
|
||||
operation = service.get_zone_operation(project_id, zone, operation_id)
|
||||
begin
|
||||
operation = service.get_zone_operation(project_id, zone, operation_id)
|
||||
rescue Google::Apis::ClientError, Google::Apis::AuthorizationError => e
|
||||
return nil
|
||||
end
|
||||
|
||||
puts "#{self.class.name} - #{__callee__}: operation: #{operation.inspect}"
|
||||
operation
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue