Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorShinya Maeda <shinya@gitlab.com>2017-10-23 11:36:35 +0300
committerShinya Maeda <shinya@gitlab.com>2017-10-23 11:36:35 +0300
commitd0cff7f5855f91b5479f9fdaa39d8d95ec691a9e (patch)
tree892e9ce3d95fdc19d3b258bac2a0cbb4705cf35f /app
parente1d12ba9b988e61afb9317f3a132d6e2caa93923 (diff)
This works
Diffstat (limited to 'app')
-rw-r--r--app/controllers/projects/clusters_controller.rb26
-rw-r--r--app/models/clusters/cluster.rb52
-rw-r--r--app/models/clusters/cluster_project.rb6
-rw-r--r--app/models/clusters/platforms/kubernetes.rb39
-rw-r--r--app/models/clusters/project.rb8
-rw-r--r--app/models/clusters/providers/gcp.rb29
-rw-r--r--app/models/project.rb4
-rw-r--r--app/policies/clusters/cluster_policy.rb (renamed from app/policies/gcp/cluster_policy.rb)4
-rw-r--r--app/presenters/clusters/cluster_presenter.rb (renamed from app/presenters/gcp/cluster_presenter.rb)4
-rw-r--r--app/services/clusters/create_service.rb35
-rw-r--r--app/services/clusters/gcp/fetch_operation_service.rb6
-rw-r--r--app/services/clusters/gcp/finalize_creation_service.rb38
-rw-r--r--app/services/clusters/gcp/provision_service.rb54
-rw-r--r--app/services/clusters/gcp/verify_provision_status_service.rb14
-rw-r--r--app/validators/cluster_name_validator.rb24
-rw-r--r--app/views/projects/clusters/_form.html.haml44
-rw-r--r--app/views/projects/clusters/show.html.haml6
-rw-r--r--app/workers/cluster_provision_worker.rb2
-rw-r--r--app/workers/wait_for_cluster_creation_worker.rb2
19 files changed, 235 insertions, 162 deletions
diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb
index 0679d8c69f0..c07d955f148 100644
--- a/app/controllers/projects/clusters_controller.rb
+++ b/app/controllers/projects/clusters_controller.rb
@@ -27,11 +27,17 @@ class Projects::ClustersController < Projects::ApplicationController
end
def new
- @cluster = project.build_cluster
+ @cluster = Clusters::Cluster.new(
+ platform_type: :kubernetes,
+ provider_type: :gcp).tap do |cluster|
+ cluster.build_provider_gcp
+ cluster.build_platform_kubernetes
+ cluster.projects << project
+ end
end
def create
- @cluster = Ci::CreateService
+ @cluster = Clusters::CreateService
.new(project, current_user, create_params)
.execute(token_in_session)
@@ -58,7 +64,7 @@ class Projects::ClustersController < Projects::ApplicationController
end
def update
- Ci::UpdateClusterService
+ Clusters::UpdateService
.new(project, current_user, update_params)
.execute(cluster)
@@ -89,16 +95,16 @@ class Projects::ClustersController < Projects::ApplicationController
def create_params
params.require(:cluster).permit(
:enabled,
+ :name,
:platform_type,
:provider_type,
- kubernetes_platform: [
+ platform_kubernetes_attributes: [
:namespace
],
- gcp_provider: [
- :project_id,
- :cluster_zone,
- :cluster_name,
- :cluster_size,
+ provider_gcp_attributes: [
+ :gcp_project_id,
+ :zone,
+ :num_nodes,
:machine_type
])
end
@@ -106,7 +112,7 @@ class Projects::ClustersController < Projects::ApplicationController
def update_params
params.require(:cluster).permit(
:enabled,
- kubernetes_platform: [
+ platform_kubernetes_attributes: [
:namespace
])
end
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index d7b13ac88f2..f1eedad8795 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -2,49 +2,46 @@ module Clusters
class Cluster < ActiveRecord::Base
include Presentable
+ self.table_name = 'clusters'
+
belongs_to :user
- belongs_to :service
- enum :platform_type {
+ enum platform_type: {
kubernetes: 1
}
- enum :provider_type {
+ enum provider_type: {
user: 0,
gcp: 1
}
- has_many :cluster_projects
- has_many :projects, through: :cluster_projects
+ has_many :cluster_projects, class_name: 'Clusters::Project'
+ has_many :projects, through: :cluster_projects, class_name: '::Project'
- has_one :gcp_provider
- has_one :kubernetes_platform
+ has_one :provider_gcp, class_name: 'Clusters::Providers::Gcp'
+ has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes'
- accepts_nested_attributes_for :gcp_provider
- accepts_nested_attributes_for :kubernetes_platform
+ accepts_nested_attributes_for :provider_gcp
+ accepts_nested_attributes_for :platform_kubernetes
- validates :kubernetes_platform, presence: true, if: :kubernetes?
- validates :gcp_provider, presence: true, if: :gcp?
+ validates :name, cluster_name: true
validate :restrict_modification, on: :update
delegate :status, to: :provider, allow_nil: true
delegate :status_reason, to: :provider, allow_nil: true
-
- def restrict_modification
- if provider&.on_creation?
- errors.add(:base, "cannot modify during creation")
- return false
- end
-
- true
- end
+ delegate :status_name, to: :provider, allow_nil: true
+ delegate :on_creation?, to: :provider, allow_nil: true
def provider
- return gcp_provider if gcp?
+ return provider_gcp if gcp?
end
def platform
- return kubernetes_platform if kubernetes?
+ return platform_kubernetes if kubernetes?
+ end
+
+ def project
+ first_project
end
def first_project
@@ -52,5 +49,16 @@ module Clusters
@first_project = projects.first
end
+
+ private
+
+ def restrict_modification
+ if provider&.on_creation?
+ errors.add(:base, "cannot modify during creation")
+ return false
+ end
+
+ true
+ end
end
end
diff --git a/app/models/clusters/cluster_project.rb b/app/models/clusters/cluster_project.rb
deleted file mode 100644
index 7b139c2bb08..00000000000
--- a/app/models/clusters/cluster_project.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Clusters
- class ClusterProject < ActiveRecord::Base
- belongs_to :cluster
- belongs_to :project
- end
-end
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index aed6f733487..d9f8927f7cc 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -4,11 +4,13 @@ module Clusters
include Gitlab::Kubernetes
include ReactiveCaching
+ self.table_name = 'cluster_platforms_kubernetes'
+
TEMPLATE_PLACEHOLDER = 'Kubernetes namespace'.freeze
- self.reactive_cache_key = ->(service) { [service.class.model_name.singular, service.project_id] }
+ self.reactive_cache_key = ->(kubernetes) { [kubernetes.class.model_name.singular, kubernetes.cluster_id] }
- belongs_to :cluster
+ belongs_to :cluster, inverse_of: :platform_kubernetes, class_name: 'Clusters::Cluster'
attr_encrypted :password,
mode: :per_attribute_iv,
@@ -28,8 +30,8 @@ module Clusters
message: Gitlab::Regex.kubernetes_namespace_regex_message
}
- validates :api_url, url: true, presence: true
- validates :token, presence: true
+ validates :api_url, url: true, presence: true, on: :update
+ validates :token, presence: true, on: :update
after_save :clear_reactive_cache!
@@ -53,9 +55,9 @@ module Clusters
{ key: 'KUBECONFIG', value: config, public: false, file: true }
]
- if ca_pem.present?
- variables << { key: 'KUBE_CA_PEM', value: ca_pem, public: true }
- variables << { key: 'KUBE_CA_PEM_FILE', value: ca_pem, public: true, file: true }
+ if ca_cert.present?
+ variables << { key: 'KUBE_CA_PEM', value: ca_cert, public: true }
+ variables << { key: 'KUBE_CA_PEM_FILE', value: ca_cert, public: true, file: true }
end
variables
@@ -76,7 +78,7 @@ module Clusters
# Caches resources in the namespace so other calls don't need to block on
# network access
def calculate_reactive_cache
- return unless active? && project && !project.pending_delete?
+ return unless active? && cluster.project && !cluster.project.pending_delete?
# We may want to cache extra things in the future
{ pods: read_pods }
@@ -87,15 +89,16 @@ module Clusters
url: api_url,
namespace: actual_namespace,
token: token,
- ca_pem: ca_pem)
+ ca_pem: ca_cert)
end
def namespace_placeholder
default_namespace || TEMPLATE_PLACEHOLDER
end
- def default_namespace
- "#{cluster.first_project.path}-#{cluster.first_project.id}" if cluster.first_project
+ def default_namespace(project = nil)
+ project ||= cluster&.project
+ "#{project.path}-#{project.id}" if project
end
def read_secrets
@@ -120,9 +123,9 @@ module Clusters
def kubeclient_ssl_options
opts = { verify_ssl: OpenSSL::SSL::VERIFY_PEER }
- if ca_pem.present?
+ if ca_cert.present?
opts[:cert_store] = OpenSSL::X509::Store.new
- opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_pem))
+ opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_cert))
end
opts
@@ -131,7 +134,11 @@ module Clusters
private
def build_kubeclient!(api_path: 'api', api_version: 'v1')
- raise "Incomplete settings" unless api_url && actual_namespace && token
+ raise "Incomplete settings" unless api_url && actual_namespace
+
+ unless (username && password) || token
+ raise "Either username/password or token is required to access API"
+ end
::Kubeclient::Client.new(
join_api_url(api_path),
@@ -143,7 +150,7 @@ module Clusters
end
def kubeclient_auth_options
- return { username: username, password: password } if username
+ return { username: username, password: password } if username && password
return { bearer_token: token } if token
end
@@ -159,7 +166,7 @@ module Clusters
def terminal_auth
{
token: token,
- ca_pem: ca_pem,
+ ca_pem: ca_cert,
max_session_time: current_application_settings.terminal_max_session_time
}
end
diff --git a/app/models/clusters/project.rb b/app/models/clusters/project.rb
new file mode 100644
index 00000000000..69088100420
--- /dev/null
+++ b/app/models/clusters/project.rb
@@ -0,0 +1,8 @@
+module Clusters
+ class Project < ActiveRecord::Base
+ self.table_name = 'cluster_projects'
+
+ belongs_to :cluster, inverse_of: :projects, class_name: 'Clusters::Cluster'
+ belongs_to :project, inverse_of: :project, class_name: 'Project'
+ end
+end
diff --git a/app/models/clusters/providers/gcp.rb b/app/models/clusters/providers/gcp.rb
index 5d4618cfe87..e4f109d2794 100644
--- a/app/models/clusters/providers/gcp.rb
+++ b/app/models/clusters/providers/gcp.rb
@@ -1,10 +1,12 @@
module Clusters
module Providers
class Gcp < ActiveRecord::Base
- belongs_to :cluster
+ self.table_name = 'cluster_providers_gcp'
- default_value_for :cluster_zone, 'us-central1-a'
- default_value_for :cluster_size, 3
+ belongs_to :cluster, inverse_of: :provider_gcp, class_name: 'Clusters::Cluster'
+
+ default_value_for :zone, 'us-central1-a'
+ default_value_for :num_nodes, 3
default_value_for :machine_type, 'n1-standard-4'
attr_encrypted :access_token,
@@ -12,23 +14,16 @@ module Clusters
key: Gitlab::Application.secrets.db_key_base,
algorithm: 'aes-256-cbc'
- validates :project_id,
+ validates :gcp_project_id,
length: 1..63,
format: {
with: Gitlab::Regex.kubernetes_namespace_regex,
message: Gitlab::Regex.kubernetes_namespace_regex_message
}
- validates :cluster_name,
- length: 1..63,
- format: {
- with: Gitlab::Regex.kubernetes_namespace_regex,
- message: Gitlab::Regex.kubernetes_namespace_regex_message
- }
-
- validates :cluster_zone, presence: true
+ validates :zone, presence: true
- validates :cluster_size,
+ validates :num_nodes,
presence: true,
numericality: {
only_integer: true,
@@ -54,9 +49,13 @@ module Clusters
end
before_transition any => [:errored, :created] do |provider|
- provider.token = nil
+ provider.access_token = nil
provider.operation_id = nil
- provider.save!
+ end
+
+ before_transition any => [:creating] do |provider, transition|
+ operation_id = transition.args.first
+ provider.operation_id = operation_id if operation_id
end
before_transition any => [:errored] do |provider, transition|
diff --git a/app/models/project.rb b/app/models/project.rb
index bc263b63881..70c75edcda3 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -178,8 +178,8 @@ class Project < ActiveRecord::Base
has_one :project_feature, inverse_of: :project
has_one :statistics, class_name: 'ProjectStatistics'
- has_many :cluster_projects, class_name: 'Clusters::ClusterProject'
- has_one :cluster, through: :cluster_projects
+ has_one :cluster_project, class_name: 'Clusters::Project'
+ has_one :cluster, through: :cluster_project, class_name: 'Clusters::Cluster'
# Container repositories need to remove data from the container registry,
# which is not managed by the DB. Hence we're still using dependent: :destroy
diff --git a/app/policies/gcp/cluster_policy.rb b/app/policies/clusters/cluster_policy.rb
index e77173ea6e1..1f7c13072b9 100644
--- a/app/policies/gcp/cluster_policy.rb
+++ b/app/policies/clusters/cluster_policy.rb
@@ -1,8 +1,8 @@
-module Gcp
+module Clusters
class ClusterPolicy < BasePolicy
alias_method :cluster, :subject
- delegate { @subject.project }
+ delegate { cluster.project }
rule { can?(:master_access) }.policy do
enable :update_cluster
diff --git a/app/presenters/gcp/cluster_presenter.rb b/app/presenters/clusters/cluster_presenter.rb
index f7908f92a37..01cb59d0d44 100644
--- a/app/presenters/gcp/cluster_presenter.rb
+++ b/app/presenters/clusters/cluster_presenter.rb
@@ -1,9 +1,9 @@
-module Gcp
+module Clusters
class ClusterPresenter < Gitlab::View::Presenter::Delegated
presents :cluster
def gke_cluster_url
- "https://console.cloud.google.com/kubernetes/clusters/details/#{gcp_cluster_zone}/#{gcp_cluster_name}"
+ "https://console.cloud.google.com/kubernetes/clusters/details/#{provider.zone}/#{name}" if gcp?
end
end
end
diff --git a/app/services/clusters/create_service.rb b/app/services/clusters/create_service.rb
index 5429bc21256..3f458e25c14 100644
--- a/app/services/clusters/create_service.rb
+++ b/app/services/clusters/create_service.rb
@@ -1,14 +1,39 @@
module Clusters
class CreateService < BaseService
- def execute(access_token)
- params['gcp_machine_type'] ||= GoogleApi::CloudPlatform::Client::DEFAULT_MACHINE_TYPE
+ attr_reader :access_token
- cluster_params =
- params.merge(user: current_user)
+ def execute(access_token)
+ @access_token = access_token
- project.create_cluster(cluster_params).tap do |cluster|
+ create_cluster.tap do |cluster|
ClusterProvisionWorker.perform_async(cluster.id) if cluster.persisted?
end
end
+
+ private
+
+ def create_cluster
+ cluster = nil
+
+ ActiveRecord::Base.transaction do
+ cluster = Clusters::Cluster.create!(cluster_params)
+ cluster.projects << project
+ end
+
+ cluster
+ rescue ActiveRecord::RecordInvalid => e
+ e.record
+ end
+
+ def cluster_params
+ return @cluster_params if defined?(@cluster_params)
+
+ params[:provider_gcp_attributes][:machine_type] ||=
+ GoogleApi::CloudPlatform::Client::DEFAULT_MACHINE_TYPE
+
+ params[:provider_gcp_attributes][:access_token] ||= access_token
+
+ @cluster_params = params.merge(user: current_user)
+ end
end
end
diff --git a/app/services/clusters/gcp/fetch_operation_service.rb b/app/services/clusters/gcp/fetch_operation_service.rb
index 013225efac4..a4cd3ca5c11 100644
--- a/app/services/clusters/gcp/fetch_operation_service.rb
+++ b/app/services/clusters/gcp/fetch_operation_service.rb
@@ -3,13 +3,13 @@ module Clusters
class FetchOperationService
def execute(provider)
operation = provider.api_client.projects_zones_operations(
- provider.project_id,
- provider.cluster_zone,
+ provider.gcp_project_id,
+ provider.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}")
+ provider.make_errored!("Failed to request to CloudPlatform; #{e.message}")
end
end
end
diff --git a/app/services/clusters/gcp/finalize_creation_service.rb b/app/services/clusters/gcp/finalize_creation_service.rb
index b536285b368..9f257bd0e9a 100644
--- a/app/services/clusters/gcp/finalize_creation_service.rb
+++ b/app/services/clusters/gcp/finalize_creation_service.rb
@@ -7,15 +7,14 @@ module Clusters
@provider = provider
configure_provider
- configure_kubernetes_platform
- request_kuberenetes_platform_token
+ configure_kubernetes
ActiveRecord::Base.transaction do
- kubernetes_platform.update!
+ kubernetes.save!
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}")
+ 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
@@ -26,23 +25,20 @@ module Clusters
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
+ def configure_kubernetes
+ kubernetes.api_url = 'https://' + gke_cluster.endpoint
+ kubernetes.ca_cert = Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate)
+ kubernetes.username = gke_cluster.master_auth.username
+ kubernetes.password = gke_cluster.master_auth.password
+ kubernetes.token = request_kuberenetes_token
end
- def request_kuberenetes_platform_token
- kubernetes_platform.read_secrets.each do |secret|
+ def request_kuberenetes_token
+ kubernetes.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
+ return Base64.decode64(token_base64) if token_base64
end
end
end
@@ -50,16 +46,16 @@ module Clusters
def gke_cluster
@gke_cluster ||= provider.api_client.projects_zones_clusters_get(
provider.gcp_project_id,
- provider.gcp_cluster_zone,
- provider.gcp_cluster_name)
+ provider.zone,
+ cluster.name)
end
def cluster
- provider.cluster
+ @cluster ||= provider.cluster
end
- def kubernetes_platform
- cluster.kubernetes_platform
+ def kubernetes
+ @kubernetes ||= cluster.platform_kubernetes
end
end
end
diff --git a/app/services/clusters/gcp/provision_service.rb b/app/services/clusters/gcp/provision_service.rb
index 269705000ac..8ec81e22203 100644
--- a/app/services/clusters/gcp/provision_service.rb
+++ b/app/services/clusters/gcp/provision_service.rb
@@ -6,43 +6,41 @@ module Clusters
def execute(provider)
@provider = provider
- unless operation.status == 'RUNNING' || operation.status == 'PENDING'
- return provider.make_errored!("Operation status is unexpected; #{operation.status_message}")
+ get_operation_id do |operation_id|
+ if provider.make_creating(operation_id)
+ WaitForClusterCreationWorker.perform_in(
+ Clusters::Gcp::VerifyProvisionStatusService::INITIAL_INTERVAL,
+ provider.id)
+ else
+ provider.make_errored!("Failed to update provider record; #{provider.errors}")
+ end
end
+ end
- provider.operation_id = operation_id
+ private
- unless provider.operation_id
- return provider.make_errored!('Can not find operation_id from self_link')
- end
+ def get_operation_id
+ operation = provider.api_client.projects_zones_clusters_create(
+ provider.gcp_project_id,
+ provider.zone,
+ provider.cluster.name,
+ provider.num_nodes,
+ machine_type: provider.machine_type)
- if provider.make_creating
- WaitForClusterCreationWorker.perform_in(
- WaitForClusterCreationWorker::INITIAL_INTERVAL, provider.id)
- else
- return provider.make_errored!("Failed to update provider record; #{provider.errors}")
+ unless operation.status == 'PENDING' || operation.status == 'RUNNING'
+ return provider.make_errored!("Operation status is unexpected; #{operation.status_message}")
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
+ operation_id = provider.api_client.parse_operation_id(operation.self_link)
- def operation_id
- api_client.parse_operation_id(operation.self_link)
- end
+ unless operation_id
+ return provider.make_errored!('Can not find operation_id from 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
+ yield(operation_id)
- def api_client
- provider.api_client
+ rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
+ provider.make_errored!("Failed to request to CloudPlatform; #{e.message}")
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
index 466ea986516..bc33756f27c 100644
--- a/app/services/clusters/gcp/verify_provision_status_service.rb
+++ b/app/services/clusters/gcp/verify_provision_status_service.rb
@@ -12,7 +12,7 @@ module Clusters
request_operation do |operation|
case operation.status
- when 'RUNNING'
+ when 'PENDING', 'RUNNING'
continue_creation(operation)
when 'DONE'
finalize_creation
@@ -25,11 +25,15 @@ module Clusters
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}")
+ if elapsed_time_from_creation(operation) < TIMEOUT
+ WaitForClusterCreationWorker.perform_in(EAGER_INTERVAL, provider.cluster_id)
+ else
+ provider.make_errored!("Cluster creation time exceeds timeout; #{TIMEOUT}")
end
+ end
- WaitForClusterCreationWorker.perform_in(EAGER_INTERVAL, provider.cluster_id)
+ def elapsed_time_from_creation(operation)
+ Time.now.utc - operation.start_time.to_time.utc
end
def finalize_creation
@@ -37,7 +41,7 @@ module Clusters
end
def request_operation(&blk)
- Clusters::FetchGcpOperationService.new.execute(provider, &blk)
+ Clusters::Gcp::FetchOperationService.new.execute(provider, &blk)
end
end
end
diff --git a/app/validators/cluster_name_validator.rb b/app/validators/cluster_name_validator.rb
new file mode 100644
index 00000000000..6c9850af30f
--- /dev/null
+++ b/app/validators/cluster_name_validator.rb
@@ -0,0 +1,24 @@
+# ClusterNameValidator
+#
+# Custom validator for ClusterName.
+class ClusterNameValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ if record.user?
+ unless value.present?
+ record.errors.add(attribute, " has to be present")
+ end
+ elsif record.gcp?
+ if record.persisted? && record.name != value
+ record.errors.add(attribute, " can not be changed because it's synchronized with provider")
+ end
+
+ unless value.length >= 1 && value.length <= 63
+ record.errors.add(attribute, " is invalid syntax")
+ end
+
+ unless value =~ Gitlab::Regex.kubernetes_namespace_regex
+ record.errors.add(attribute, Gitlab::Regex.kubernetes_namespace_regex_message)
+ end
+ end
+ end
+end
diff --git a/app/views/projects/clusters/_form.html.haml b/app/views/projects/clusters/_form.html.haml
index 371cdb1e403..b3020513abf 100644
--- a/app/views/projects/clusters/_form.html.haml
+++ b/app/views/projects/clusters/_form.html.haml
@@ -4,34 +4,38 @@
- link_to_help_page = link_to(s_('ClusterIntegration|help page'), help_page_path('user/project/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
= s_('ClusterIntegration|Read our %{link_to_help_page} on cluster integration.').html_safe % { link_to_help_page: link_to_help_page}
- = form_for [@project.namespace.becomes(Namespace), @project, @cluster] do |field|
+ = form_for @cluster, url: namespace_project_clusters_path(@project.namespace, @project, @cluster), as: :cluster do |field|
+ = field.hidden_field :platform_type, :value => 'kubernetes'
+ = field.hidden_field :provider_type, :value => 'gcp'
= form_errors(@cluster)
.form-group
- = field.label :gcp_cluster_name, s_('ClusterIntegration|Cluster name')
- = field.text_field :gcp_cluster_name, class: 'form-control'
+ = field.label :name, s_('ClusterIntegration|Cluster name')
+ = field.text_field :name, class: 'form-control'
- .form-group
- = field.label :gcp_project_id, s_('ClusterIntegration|Google Cloud Platform project ID')
- = link_to(s_('ClusterIntegration|See your projects'), 'https://console.cloud.google.com/home/dashboard', target: '_blank', rel: 'noopener noreferrer')
- = field.text_field :gcp_project_id, class: 'form-control'
+ = field.fields_for :provider_gcp, @cluster.provider_gcp do |provider_gcp_field|
+ .form-group
+ = provider_gcp_field.label :gcp_project_id, s_('ClusterIntegration|Google Cloud Platform project ID')
+ = link_to(s_('ClusterIntegration|See your projects'), 'https://console.cloud.google.com/home/dashboard', target: '_blank', rel: 'noopener noreferrer')
+ = provider_gcp_field.text_field :gcp_project_id, class: 'form-control'
- .form-group
- = field.label :gcp_cluster_zone, s_('ClusterIntegration|Zone')
- = link_to(s_('ClusterIntegration|See zones'), 'https://cloud.google.com/compute/docs/regions-zones/regions-zones', target: '_blank', rel: 'noopener noreferrer')
- = field.text_field :gcp_cluster_zone, class: 'form-control', placeholder: 'us-central1-a'
+ .form-group
+ = provider_gcp_field.label :zone, s_('ClusterIntegration|Zone')
+ = link_to(s_('ClusterIntegration|See zones'), 'https://cloud.google.com/compute/docs/regions-zones/regions-zones', target: '_blank', rel: 'noopener noreferrer')
+ = provider_gcp_field.text_field :zone, class: 'form-control', placeholder: 'us-central1-a'
- .form-group
- = field.label :gcp_cluster_size, s_('ClusterIntegration|Number of nodes')
- = field.text_field :gcp_cluster_size, class: 'form-control', placeholder: '3'
+ .form-group
+ = provider_gcp_field.label :num_nodes, s_('ClusterIntegration|Number of nodes')
+ = provider_gcp_field.text_field :num_nodes, class: 'form-control', placeholder: '3'
- .form-group
- = field.label :gcp_machine_type, s_('ClusterIntegration|Machine type')
- = link_to(s_('ClusterIntegration|See machine types'), 'https://cloud.google.com/compute/docs/machine-types', target: '_blank', rel: 'noopener noreferrer')
- = field.text_field :gcp_machine_type, class: 'form-control', placeholder: 'n1-standard-4'
+ .form-group
+ = provider_gcp_field.label :machine_type, s_('ClusterIntegration|Machine type')
+ = link_to(s_('ClusterIntegration|See machine types'), 'https://cloud.google.com/compute/docs/machine-types', target: '_blank', rel: 'noopener noreferrer')
+ = provider_gcp_field.text_field :machine_type, class: 'form-control', placeholder: 'n1-standard-4'
+ = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
.form-group
- = field.label :project_namespace, s_('ClusterIntegration|Project namespace (optional, unique)')
- = field.text_field :project_namespace, class: 'form-control', placeholder: @cluster.project_namespace_placeholder
+ = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)')
+ = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: @cluster.platform_kubernetes.default_namespace(@project)
.form-group
= field.submit s_('ClusterIntegration|Create cluster'), class: 'btn btn-save'
diff --git a/app/views/projects/clusters/show.html.haml b/app/views/projects/clusters/show.html.haml
index ff76abc3553..49adae82454 100644
--- a/app/views/projects/clusters/show.html.haml
+++ b/app/views/projects/clusters/show.html.haml
@@ -33,7 +33,7 @@
- else
= s_('ClusterIntegration|Cluster integration is disabled for this project.')
- = form_for [@project.namespace.becomes(Namespace), @project, @cluster] do |field|
+ = form_for @cluster, url: namespace_project_cluster_path(@project.namespace, @project, @cluster), as: :cluster do |field|
= form_errors(@cluster)
.form-group.append-bottom-20
%label.append-bottom-10
@@ -62,9 +62,9 @@
%label.append-bottom-10{ for: 'cluter-name' }
= s_('ClusterIntegration|Cluster name')
.input-group
- %input.form-control.cluster-name{ value: @cluster.gcp_cluster_name, disabled: true }
+ %input.form-control.cluster-name{ value: @cluster.name, disabled: true }
%span.input-group-addon.clipboard-addon
- = clipboard_button(text: @cluster.gcp_cluster_name, title: s_('ClusterIntegration|Copy cluster name'))
+ = clipboard_button(text: @cluster.name, title: s_('ClusterIntegration|Copy cluster name'))
%section.settings#js-cluster-advanced-settings
.settings-header
diff --git a/app/workers/cluster_provision_worker.rb b/app/workers/cluster_provision_worker.rb
index 79f0d73c396..0929fffc444 100644
--- a/app/workers/cluster_provision_worker.rb
+++ b/app/workers/cluster_provision_worker.rb
@@ -4,7 +4,7 @@ class ClusterProvisionWorker
def perform(cluster_id)
Clusters::Cluster.find_by_id(cluster_id).try do |cluster|
- cluster.gcp_provider.try do |provider|
+ cluster.provider_gcp.try do |provider|
Clusters::Gcp::ProvisionService.new.execute(provider)
end
end
diff --git a/app/workers/wait_for_cluster_creation_worker.rb b/app/workers/wait_for_cluster_creation_worker.rb
index d8c42c6bd55..b2f04869636 100644
--- a/app/workers/wait_for_cluster_creation_worker.rb
+++ b/app/workers/wait_for_cluster_creation_worker.rb
@@ -4,7 +4,7 @@ class WaitForClusterCreationWorker
def perform(cluster_id)
Clusters::Cluster.find_by_id(cluster_id).try do |cluster|
- cluster.gcp_provider.try do |provider|
+ cluster.provider_gcp.try do |provider|
Clusters::Gcp::VerifyProvisionStatusService.new.execute(provider)
end
end