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:
authorFilipa Lacerda <filipa@gitlab.com>2017-12-05 15:00:02 +0300
committerGrzegorz Bizon <grzegorz@gitlab.com>2017-12-05 15:00:02 +0300
commit4b66bdfa1af8fbef5d2af94a62e2522806cc7250 (patch)
treeb63b843eca0e92ac2938ad8a49a979c2b8ab52e9 /app
parent04a882d8d3bd68bee71f5b7073cb7a8ce0149852 (diff)
Second iteration of Move Kubernetes from service to Cluster page
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js15
-rw-r--r--app/assets/stylesheets/pages/clusters.scss6
-rw-r--r--app/controllers/projects/clusters/gcp_controller.rb75
-rw-r--r--app/controllers/projects/clusters/user_controller.rb39
-rw-r--r--app/controllers/projects/clusters_controller.rb96
-rw-r--r--app/models/clusters/cluster.rb6
-rw-r--r--app/models/clusters/platforms/kubernetes.rb14
-rw-r--r--app/services/clusters/create_service.rb2
-rw-r--r--app/validators/cluster_name_validator.rb10
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml16
-rw-r--r--app/views/projects/clusters/_advanced_settings.html.haml13
-rw-r--r--app/views/projects/clusters/_banner.html.haml21
-rw-r--r--app/views/projects/clusters/_dropdown.html.haml12
-rw-r--r--app/views/projects/clusters/_enabled.html.haml16
-rw-r--r--app/views/projects/clusters/_form.html.haml35
-rw-r--r--app/views/projects/clusters/gcp/_form.html.haml32
-rw-r--r--app/views/projects/clusters/gcp/_header.html.haml (renamed from app/views/projects/clusters/_header.html.haml)4
-rw-r--r--app/views/projects/clusters/gcp/_show.html.haml40
-rw-r--r--app/views/projects/clusters/gcp/login.html.haml (renamed from app/views/projects/clusters/login.html.haml)3
-rw-r--r--app/views/projects/clusters/gcp/new.html.haml10
-rw-r--r--app/views/projects/clusters/new.html.haml17
-rw-r--r--app/views/projects/clusters/new_gcp.html.haml10
-rw-r--r--app/views/projects/clusters/show.html.haml56
-rw-r--r--app/views/projects/clusters/user/_form.html.haml25
-rw-r--r--app/views/projects/clusters/user/_header.html.haml5
-rw-r--r--app/views/projects/clusters/user/_show.html.haml29
-rw-r--r--app/views/projects/clusters/user/new.html.haml11
27 files changed, 418 insertions, 200 deletions
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index dc443475952..cdb5c430aa9 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -48,6 +48,7 @@ export default class Clusters {
this.toggle = this.toggle.bind(this);
this.installApplication = this.installApplication.bind(this);
+ this.showToken = this.showToken.bind(this);
this.toggleButton = document.querySelector('.js-toggle-cluster');
this.toggleInput = document.querySelector('.js-toggle-input');
@@ -56,6 +57,8 @@ export default class Clusters {
this.creatingContainer = document.querySelector('.js-cluster-creating');
this.errorReasonContainer = this.errorContainer.querySelector('.js-error-reason');
this.successApplicationContainer = document.querySelector('.js-cluster-application-notice');
+ this.showTokenButton = document.querySelector('.js-show-cluster-token');
+ this.tokenField = document.querySelector('.js-cluster-token');
initSettingsPanels();
this.initApplications();
@@ -97,11 +100,13 @@ export default class Clusters {
addListeners() {
this.toggleButton.addEventListener('click', this.toggle);
+ if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
eventHub.$on('installApplication', this.installApplication);
}
removeListeners() {
this.toggleButton.removeEventListener('click', this.toggle);
+ if (this.showTokenButton) this.showTokenButton.removeEventListener('click', this.showToken);
eventHub.$off('installApplication', this.installApplication);
}
@@ -149,6 +154,16 @@ export default class Clusters {
this.toggleInput.setAttribute('value', this.toggleButton.classList.contains('checked').toString());
}
+ showToken() {
+ const type = this.tokenField.getAttribute('type');
+
+ if (type === 'password') {
+ this.tokenField.setAttribute('type', 'text');
+ } else {
+ this.tokenField.setAttribute('type', 'password');
+ }
+ }
+
hideAll() {
this.errorContainer.classList.add('hidden');
this.successContainer.classList.add('hidden');
diff --git a/app/assets/stylesheets/pages/clusters.scss b/app/assets/stylesheets/pages/clusters.scss
index e5b9e1f2de6..83e211d6086 100644
--- a/app/assets/stylesheets/pages/clusters.scss
+++ b/app/assets/stylesheets/pages/clusters.scss
@@ -8,3 +8,9 @@
// Wait for the Vue to kick-in and render the applications block
min-height: 302px;
}
+
+.clusters-dropdown-menu {
+ max-width: 100%;
+}
+
+@include new-style-dropdown('.clusters-dropdown ');
diff --git a/app/controllers/projects/clusters/gcp_controller.rb b/app/controllers/projects/clusters/gcp_controller.rb
new file mode 100644
index 00000000000..b64f7a2a6bd
--- /dev/null
+++ b/app/controllers/projects/clusters/gcp_controller.rb
@@ -0,0 +1,75 @@
+class Projects::Clusters::GcpController < Projects::ApplicationController
+ before_action :authorize_read_cluster!
+ before_action :authorize_google_api, except: [:login]
+ before_action :authorize_create_cluster!, only: [:new, :create]
+
+ def login
+ begin
+ state = generate_session_key_redirect(gcp_new_namespace_project_clusters_path.to_s)
+
+ @authorize_url = GoogleApi::CloudPlatform::Client.new(
+ nil, callback_google_api_auth_url,
+ state: state).authorize_url
+ rescue GoogleApi::Auth::ConfigMissingError
+ # no-op
+ end
+ end
+
+ def new
+ @cluster = ::Clusters::Cluster.new.tap do |cluster|
+ cluster.build_provider_gcp
+ end
+ end
+
+ def create
+ @cluster = ::Clusters::CreateService
+ .new(project, current_user, create_params)
+ .execute(token_in_session)
+
+ if @cluster.persisted?
+ redirect_to project_cluster_path(project, @cluster)
+ else
+ render :new
+ end
+ end
+
+ private
+
+ def create_params
+ params.require(:cluster).permit(
+ :enabled,
+ :name,
+ provider_gcp_attributes: [
+ :gcp_project_id,
+ :zone,
+ :num_nodes,
+ :machine_type
+ ]).merge(
+ provider_type: :gcp,
+ platform_type: :kubernetes
+ )
+ end
+
+ def authorize_google_api
+ unless GoogleApi::CloudPlatform::Client.new(token_in_session, nil)
+ .validate_token(expires_at_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 expires_at_in_session
+ @expires_at_in_session ||=
+ session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at]
+ end
+
+ def generate_session_key_redirect(uri)
+ GoogleApi::CloudPlatform::Client.new_session_key_for_redirect_uri do |key|
+ session[key] = uri
+ end
+ end
+end
diff --git a/app/controllers/projects/clusters/user_controller.rb b/app/controllers/projects/clusters/user_controller.rb
new file mode 100644
index 00000000000..d7678512073
--- /dev/null
+++ b/app/controllers/projects/clusters/user_controller.rb
@@ -0,0 +1,39 @@
+class Projects::Clusters::UserController < Projects::ApplicationController
+ before_action :authorize_read_cluster!
+ before_action :authorize_create_cluster!, only: [:new, :create]
+
+ def new
+ @cluster = ::Clusters::Cluster.new.tap do |cluster|
+ cluster.build_platform_kubernetes
+ end
+ end
+
+ def create
+ @cluster = ::Clusters::CreateService
+ .new(project, current_user, create_params)
+ .execute
+
+ if @cluster.persisted?
+ redirect_to project_cluster_path(project, @cluster)
+ else
+ render :new
+ end
+ end
+
+ private
+
+ def create_params
+ params.require(:cluster).permit(
+ :enabled,
+ :name,
+ platform_kubernetes_attributes: [
+ :namespace,
+ :api_url,
+ :token,
+ :ca_cert
+ ]).merge(
+ provider_type: :user,
+ platform_type: :kubernetes
+ )
+ end
+end
diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb
index 9a56c9de858..d18b6d4b78c 100644
--- a/app/controllers/projects/clusters_controller.rb
+++ b/app/controllers/projects/clusters_controller.rb
@@ -1,11 +1,12 @@
class Projects::ClustersController < Projects::ApplicationController
- before_action :cluster, except: [:login, :index, :new, :new_gcp, :create]
+ before_action :cluster, except: [:index, :new]
before_action :authorize_read_cluster!
- before_action :authorize_create_cluster!, only: [:new, :new_gcp, :create]
- before_action :authorize_google_api, only: [:new_gcp, :create]
+ before_action :authorize_create_cluster!, only: [:new]
before_action :authorize_update_cluster!, only: [:update]
before_action :authorize_admin_cluster!, only: [:destroy]
+ STATUS_POLLING_INTERVAL = 10_000
+
def index
if project.cluster
redirect_to project_cluster_path(project, project.cluster)
@@ -14,43 +15,13 @@ class Projects::ClustersController < Projects::ApplicationController
end
end
- def login
- begin
- state = generate_session_key_redirect(providers_gcp_new_namespace_project_clusters_url.to_s)
-
- @authorize_url = GoogleApi::CloudPlatform::Client.new(
- nil, callback_google_api_auth_url,
- state: state).authorize_url
- rescue GoogleApi::Auth::ConfigMissingError
- # no-op
- end
- end
-
def new
end
- def new_gcp
- @cluster = Clusters::Cluster.new.tap do |cluster|
- cluster.build_provider_gcp
- end
- end
-
- def create
- @cluster = Clusters::CreateService
- .new(project, current_user, create_params)
- .execute(token_in_session)
-
- if @cluster.persisted?
- redirect_to project_cluster_path(project, @cluster)
- else
- render :new_gcp
- end
- end
-
def status
respond_to do |format|
format.json do
- Gitlab::PollingInterval.set_header(response, interval: 10_000)
+ Gitlab::PollingInterval.set_header(response, interval: STATUS_POLLING_INTERVAL)
render json: ClusterSerializer
.new(project: @project, current_user: @current_user)
@@ -88,46 +59,29 @@ class Projects::ClustersController < Projects::ApplicationController
private
def cluster
- @cluster ||= project.cluster.present(current_user: current_user)
- end
-
- def create_params
- params.require(:cluster).permit(
- :enabled,
- :name,
- :provider_type,
- provider_gcp_attributes: [
- :gcp_project_id,
- :zone,
- :num_nodes,
- :machine_type
- ])
+ @cluster ||= project.clusters.find(params[:id])
+ .present(current_user: current_user)
end
def update_params
- params.require(:cluster).permit(:enabled)
- end
-
- def authorize_google_api
- unless GoogleApi::CloudPlatform::Client.new(token_in_session, nil)
- .validate_token(expires_at_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 expires_at_in_session
- @expires_at_in_session ||=
- session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at]
- end
-
- def generate_session_key_redirect(uri)
- GoogleApi::CloudPlatform::Client.new_session_key_for_redirect_uri do |key|
- session[key] = uri
+ if cluster.managed?
+ params.require(:cluster).permit(
+ :enabled,
+ platform_kubernetes_attributes: [
+ :namespace
+ ]
+ )
+ else
+ params.require(:cluster).permit(
+ :enabled,
+ :name,
+ platform_kubernetes_attributes: [
+ :api_url,
+ :token,
+ :ca_cert,
+ :namespace
+ ]
+ )
end
end
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 6d7fb4b7dbf..45beced1427 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -17,7 +17,7 @@ module Clusters
# we force autosave to happen when we save `Cluster` model
has_one :provider_gcp, class_name: 'Clusters::Providers::Gcp', autosave: true
- has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes'
+ has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes', autosave: true
has_one :application_helm, class_name: 'Clusters::Applications::Helm'
has_one :application_ingress, class_name: 'Clusters::Applications::Ingress'
@@ -70,6 +70,10 @@ module Clusters
return platform_kubernetes if kubernetes?
end
+ def managed?
+ !user?
+ end
+
def first_project
return @first_project if defined?(@first_project)
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 7ab670cf1ef..9160a169452 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -34,12 +34,15 @@ module Clusters
validates :api_url, url: true, presence: true
validates :token, presence: true
+ validate :prevent_modification, on: :update
+
after_save :clear_reactive_cache!
alias_attribute :ca_pem, :ca_cert
delegate :project, to: :cluster, allow_nil: true
delegate :enabled?, to: :cluster, allow_nil: true
+ delegate :managed?, to: :cluster, allow_nil: true
alias_method :active?, :enabled?
@@ -173,6 +176,17 @@ module Clusters
def enforce_namespace_to_lower_case
self.namespace = self.namespace&.downcase
end
+
+ def prevent_modification
+ return unless managed?
+
+ if api_url_changed? || token_changed? || ca_pem_changed?
+ errors.add(:base, "cannot modify managed cluster")
+ return false
+ end
+
+ true
+ end
end
end
end
diff --git a/app/services/clusters/create_service.rb b/app/services/clusters/create_service.rb
index 1d407739b21..7b697f6d807 100644
--- a/app/services/clusters/create_service.rb
+++ b/app/services/clusters/create_service.rb
@@ -2,7 +2,7 @@ module Clusters
class CreateService < BaseService
attr_reader :access_token
- def execute(access_token)
+ def execute(access_token = nil)
@access_token = access_token
create_cluster.tap do |cluster|
diff --git a/app/validators/cluster_name_validator.rb b/app/validators/cluster_name_validator.rb
index 13ec342f399..e7d32550176 100644
--- a/app/validators/cluster_name_validator.rb
+++ b/app/validators/cluster_name_validator.rb
@@ -3,11 +3,7 @@
# 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.managed?
if record.persisted? && record.name_changed?
record.errors.add(attribute, " can not be changed because it's synchronized with provider")
end
@@ -19,6 +15,10 @@ class ClusterNameValidator < ActiveModel::EachValidator
unless value =~ Gitlab::Regex.kubernetes_namespace_regex
record.errors.add(attribute, Gitlab::Regex.kubernetes_namespace_regex_message)
end
+ else
+ unless value.present?
+ record.errors.add(attribute, " has to be present")
+ end
end
end
end
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 2ce960df13c..8b2d2a5c74d 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -146,7 +146,7 @@
= number_with_delimiter(@project.open_merge_requests_count)
- if project_nav_tab? :pipelines
- = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts, :clusters]) do
+ = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts, :clusters, :user, :gcp]) do
= link_to project_pipelines_path(@project), class: 'shortcuts-pipelines' do
.nav-icon-container
= sprite_icon('pipeline')
@@ -154,7 +154,7 @@
CI / CD
%ul.sidebar-sub-level-items
- = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts], html_options: { class: "fly-out-top-item" } ) do
+ = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts, :clusters, :user, :gcp], html_options: { class: "fly-out-top-item" } ) do
= link_to project_pipelines_path(@project) do
%strong.fly-out-top-item-name
#{ _('CI / CD') }
@@ -183,18 +183,18 @@
%span
Environments
+ - if project_nav_tab? :clusters
+ = nav_link(controller: [:clusters, :user, :gcp]) do
+ = link_to project_clusters_path(@project), title: 'Cluster', class: 'shortcuts-cluster' do
+ %span
+ Cluster
+
- if @project.feature_available?(:builds, current_user) && !@project.empty_repo?
= nav_link(path: 'pipelines#charts') do
= link_to charts_project_pipelines_path(@project), title: 'Charts', class: 'shortcuts-pipelines-charts' do
%span
Charts
- - if project_nav_tab? :clusters
- = nav_link(controller: :clusters) do
- = link_to project_clusters_path(@project), title: 'Cluster', class: 'shortcuts-cluster' do
- %span
- Cluster
-
- if project_nav_tab? :wiki
= nav_link(controller: :wikis) do
= link_to get_project_wiki_path(@project), class: 'shortcuts-wiki' do
diff --git a/app/views/projects/clusters/_advanced_settings.html.haml b/app/views/projects/clusters/_advanced_settings.html.haml
index 97532f1e2bd..2b3095eb94b 100644
--- a/app/views/projects/clusters/_advanced_settings.html.haml
+++ b/app/views/projects/clusters/_advanced_settings.html.haml
@@ -1,10 +1,11 @@
- if can?(current_user, :admin_cluster, @cluster)
- .append-bottom-20
- %label.append-bottom-10
- = s_('ClusterIntegration|Google Container Engine')
- %p
- - link_gke = link_to(s_('ClusterIntegration|Google Container Engine'), @cluster.gke_cluster_url, target: '_blank', rel: 'noopener noreferrer')
- = s_('ClusterIntegration|Manage your cluster by visiting %{link_gke}').html_safe % { link_gke: link_gke }
+ - if @cluster.managed?
+ .append-bottom-20
+ %label.append-bottom-10
+ = s_('ClusterIntegration|Google Container Engine')
+ %p
+ - link_gke = link_to(s_('ClusterIntegration|Google Container Engine'), @cluster.gke_cluster_url, target: '_blank', rel: 'noopener noreferrer')
+ = s_('ClusterIntegration|Manage your cluster by visiting %{link_gke}').html_safe % { link_gke: link_gke }
.well.form-group
%label.text-danger
diff --git a/app/views/projects/clusters/_banner.html.haml b/app/views/projects/clusters/_banner.html.haml
new file mode 100644
index 00000000000..a1cc66eac92
--- /dev/null
+++ b/app/views/projects/clusters/_banner.html.haml
@@ -0,0 +1,21 @@
+%h4= s_('ClusterIntegration|Enable cluster integration')
+.settings-content
+
+ .hidden.js-cluster-error.alert.alert-danger.alert-block.append-bottom-10{ role: 'alert' }
+ = s_('ClusterIntegration|Something went wrong while creating your cluster on Google Container Engine')
+ %p.js-error-reason
+
+ .hidden.js-cluster-creating.alert.alert-info.alert-block.append-bottom-10{ role: 'alert' }
+ = s_('ClusterIntegration|Cluster is being created on Google Container Engine...')
+
+ .hidden.js-cluster-success.alert.alert-success.alert-block.append-bottom-10{ role: 'alert' }
+ = s_('ClusterIntegration|Cluster was successfully created on Google Container Engine. Refresh the page to see cluster\'s details')
+
+ %p
+ - if @cluster.enabled?
+ - if can?(current_user, :update_cluster, @cluster)
+ = s_('ClusterIntegration|Cluster integration is enabled for this project. Disabling this integration will not affect your cluster, it will only temporarily turn off GitLab\'s connection to it.')
+ - else
+ = s_('ClusterIntegration|Cluster integration is enabled for this project.')
+ - else
+ = s_('ClusterIntegration|Cluster integration is disabled for this project.')
diff --git a/app/views/projects/clusters/_dropdown.html.haml b/app/views/projects/clusters/_dropdown.html.haml
new file mode 100644
index 00000000000..39188c7ca27
--- /dev/null
+++ b/app/views/projects/clusters/_dropdown.html.haml
@@ -0,0 +1,12 @@
+%h4.prepend-top-0= s_('ClusterIntegration|Choose how to set up cluster integration')
+
+.dropdown.clusters-dropdown
+ %button.dropdown-menu-toggle.dropdown-menu-full-width{ type: 'button', data: { toggle: 'dropdown' }, 'aria-haspopup': true, 'aria-expanded': false }
+ %span.dropdown-toggle-text
+ = dropdown_text
+ = icon('chevron-down')
+ %ul.dropdown-menu.clusters-dropdown-menu.dropdown-menu-full-width
+ %li
+ = link_to(s_('ClusterIntegration|Create cluster on Google Container Engine'), gcp_new_namespace_project_clusters_path(@project.namespace, @project))
+ %li
+ = link_to(s_('ClusterIntegration|Add an existing cluster'), user_new_namespace_project_clusters_path(@project.namespace, @project))
diff --git a/app/views/projects/clusters/_enabled.html.haml b/app/views/projects/clusters/_enabled.html.haml
new file mode 100644
index 00000000000..f4d261df8f5
--- /dev/null
+++ b/app/views/projects/clusters/_enabled.html.haml
@@ -0,0 +1,16 @@
+= 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
+ = field.hidden_field :enabled, { class: 'js-toggle-input'}
+
+ %button{ type: 'button',
+ class: "js-toggle-cluster project-feature-toggle #{'checked' unless !@cluster.enabled?} #{'disabled' unless can?(current_user, :update_cluster, @cluster)}",
+ 'aria-label': s_('ClusterIntegration|Toggle Cluster'),
+ disabled: !can?(current_user, :update_cluster, @cluster),
+ data: { 'enabled-text': 'Enabled', 'disabled-text': 'Disabled' } }
+
+ - if can?(current_user, :update_cluster, @cluster)
+ .form-group
+ = field.submit _('Save'), class: 'btn btn-success'
+
diff --git a/app/views/projects/clusters/_form.html.haml b/app/views/projects/clusters/_form.html.haml
deleted file mode 100644
index 1f8ae463d0f..00000000000
--- a/app/views/projects/clusters/_form.html.haml
+++ /dev/null
@@ -1,35 +0,0 @@
-.row
- .col-sm-8.col-sm-offset-4
- %p
- - 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 @cluster, url: namespace_project_clusters_path(@project.namespace, @project, @cluster), as: :cluster do |field|
- = field.hidden_field :provider_type, value: :gcp
- = form_errors(@cluster)
- .form-group
- = field.label :name, s_('ClusterIntegration|Cluster name')
- = field.text_field :name, 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
- = 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
- = 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
- = 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-2'
-
- .form-group
- = field.submit s_('ClusterIntegration|Create cluster'), class: 'btn btn-save'
diff --git a/app/views/projects/clusters/gcp/_form.html.haml b/app/views/projects/clusters/gcp/_form.html.haml
new file mode 100644
index 00000000000..0f6bae97571
--- /dev/null
+++ b/app/views/projects/clusters/gcp/_form.html.haml
@@ -0,0 +1,32 @@
+%p
+ - 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 @cluster, html: { class: 'prepend-top-20' }, url: gcp_namespace_project_clusters_path(@project.namespace, @project), as: :cluster do |field|
+ = form_errors(@cluster)
+ .form-group
+ = field.label :name, s_('ClusterIntegration|Cluster name')
+ = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Cluster name')
+
+ = 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', placeholder: s_('ClusterIntegration|Project ID')
+
+ .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
+ = 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
+ = 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'
+
+ .form-group
+ = field.submit s_('ClusterIntegration|Create cluster'), class: 'btn btn-success'
diff --git a/app/views/projects/clusters/_header.html.haml b/app/views/projects/clusters/gcp/_header.html.haml
index beb798e7154..cddb53c2688 100644
--- a/app/views/projects/clusters/_header.html.haml
+++ b/app/views/projects/clusters/gcp/_header.html.haml
@@ -1,5 +1,5 @@
-%h4.prepend-top-0
- = s_('ClusterIntegration|Create new cluster on Google Container Engine')
+%h4.prepend-top-20
+ = s_('ClusterIntegration|Enter the details for your cluster')
%p
= s_('ClusterIntegration|Please make sure that your Google account meets the following requirements:')
%ul
diff --git a/app/views/projects/clusters/gcp/_show.html.haml b/app/views/projects/clusters/gcp/_show.html.haml
new file mode 100644
index 00000000000..3fa9f69708a
--- /dev/null
+++ b/app/views/projects/clusters/gcp/_show.html.haml
@@ -0,0 +1,40 @@
+.form-group
+ %label.append-bottom-10{ for: 'cluster-name' }
+ = s_('ClusterIntegration|Cluster name')
+ .input-group
+ %input.form-control.cluster-name.js-select-on-focus{ value: @cluster.name, readonly: true }
+ %span.input-group-btn
+ = clipboard_button(text: @cluster.name, title: s_('ClusterIntegration|Copy cluster name'), class: 'btn-default')
+
+= form_for @cluster, url: namespace_project_cluster_path(@project.namespace, @project, @cluster), as: :cluster do |field|
+ = form_errors(@cluster)
+ = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
+ .form-group
+ = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL')
+ .input-group
+ = platform_kubernetes_field.text_field :api_url, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|API URL'), readonly: true
+ %span.input-group-btn
+ = clipboard_button(text: @cluster.platform_kubernetes.api_url, title: s_('ClusterIntegration|Copy API URL'), class: 'btn-default')
+
+ .form-group
+ = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate')
+ .input-group
+ = platform_kubernetes_field.text_area :ca_cert, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)'), readonly: true
+ %span.input-group-addon.clipboard-addon
+ = clipboard_button(text: @cluster.platform_kubernetes.ca_cert, title: s_('ClusterIntegration|Copy CA Certificate'), class: 'btn-blank')
+
+ .form-group
+ = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token')
+ .input-group
+ = platform_kubernetes_field.text_field :token, class: 'form-control js-cluster-token js-select-on-focus', type: 'password', placeholder: s_('ClusterIntegration|Token'), readonly: true
+ %span.input-group-btn
+ %button.btn.btn-default.js-show-cluster-token{ type: 'button' }
+ = s_('ClusterIntegration|Show')
+ = clipboard_button(text: @cluster.platform_kubernetes.token, title: s_('ClusterIntegration|Copy Token'), class: 'btn-default')
+
+ .form-group
+ = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)')
+ = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
+
+ .form-group
+ = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/projects/clusters/login.html.haml b/app/views/projects/clusters/gcp/login.html.haml
index fde030b500b..790ba61fd86 100644
--- a/app/views/projects/clusters/login.html.haml
+++ b/app/views/projects/clusters/gcp/login.html.haml
@@ -3,8 +3,9 @@
.row.prepend-top-default
.col-sm-4
- = render 'sidebar'
+ = render 'projects/clusters/sidebar'
.col-sm-8
+ = render 'projects/clusters/dropdown', dropdown_text: s_('ClusterIntegration|Create cluster on Google Container Engine')
= render 'header'
.row
.col-sm-8.col-sm-offset-4.signin-with-google
diff --git a/app/views/projects/clusters/gcp/new.html.haml b/app/views/projects/clusters/gcp/new.html.haml
new file mode 100644
index 00000000000..9a79480c82f
--- /dev/null
+++ b/app/views/projects/clusters/gcp/new.html.haml
@@ -0,0 +1,10 @@
+- breadcrumb_title "Cluster"
+- page_title _("New Cluster")
+
+.row.prepend-top-default
+ .col-sm-4
+ = render 'projects/clusters/sidebar'
+ .col-sm-8
+ = render 'projects/clusters/dropdown', dropdown_text: s_('ClusterIntegration|Create cluster on Google Container Engine')
+ = render 'header'
+ = render 'form'
diff --git a/app/views/projects/clusters/new.html.haml b/app/views/projects/clusters/new.html.haml
index 665120c7e49..2e5bc34f64a 100644
--- a/app/views/projects/clusters/new.html.haml
+++ b/app/views/projects/clusters/new.html.haml
@@ -5,16 +5,9 @@
.col-sm-4
= render 'sidebar'
.col-sm-8
- - if @project.deployment_platform&.active?
- %h4.prepend-top-0= s_('ClusterIntegration|Cluster management')
+ %h4.prepend-top-0= s_('ClusterIntegration|Choose how to set up cluster integration')
- %p= s_('ClusterIntegration|A cluster has been set up on this project through the Kubernetes integration page')
- = link_to s_('ClusterIntegration|Manage Kubernetes integration'), edit_project_service_path(@project, :kubernetes), class: 'btn append-bottom-20'
-
- - else
- %h4.prepend-top-0= s_('ClusterIntegration|Choose how to set up cluster integration')
-
- %p= s_('ClusterIntegration|Create a new cluster on Google Container Engine right from GitLab')
- = link_to s_('ClusterIntegration|Create on GKE'), providers_gcp_new_namespace_project_clusters_path(@project.namespace, @project), class: 'btn append-bottom-20'
- %p= s_('ClusterIntegration|Enter the details for an existing Kubernetes cluster')
- = link_to s_('ClusterIntegration|Add an existing cluster'), edit_project_service_path(@project, :kubernetes), class: 'btn append-bottom-20'
+ %p= s_('ClusterIntegration|Create a new cluster on Google Engine right from GitLab')
+ = link_to s_('ClusterIntegration|Create on GKE'), gcp_new_namespace_project_clusters_path(@project.namespace, @project), class: 'btn append-bottom-20'
+ %p= s_('ClusterIntegration|Enter the details for an existing Kubernetes cluster')
+ = link_to s_('ClusterIntegration|Add an existing cluster'), user_new_namespace_project_clusters_path(@project.namespace, @project), class: 'btn append-bottom-20'
diff --git a/app/views/projects/clusters/new_gcp.html.haml b/app/views/projects/clusters/new_gcp.html.haml
deleted file mode 100644
index 48e6b6ae8e8..00000000000
--- a/app/views/projects/clusters/new_gcp.html.haml
+++ /dev/null
@@ -1,10 +0,0 @@
-- breadcrumb_title "Cluster"
-- page_title _("New Cluster")
-
-.row.prepend-top-default
- .col-sm-4
- = render 'sidebar'
- .col-sm-8
- = render 'header'
-
-= render 'form'
diff --git a/app/views/projects/clusters/show.html.haml b/app/views/projects/clusters/show.html.haml
index b7671f5e3c4..d23efe4d9aa 100644
--- a/app/views/projects/clusters/show.html.haml
+++ b/app/views/projects/clusters/show.html.haml
@@ -13,52 +13,16 @@
cluster_status_reason: @cluster.status_reason,
help_path: help_page_path('user/project/clusters/index.md', anchor: 'installing-applications') } }
-
.js-cluster-application-notice
.flash-container
%section.settings.no-animate.expanded
- %h4= s_('ClusterIntegration|Enable cluster integration')
- .settings-content
-
- .hidden.js-cluster-error.alert.alert-danger.alert-block.append-bottom-10{ role: 'alert' }
- = s_('ClusterIntegration|Something went wrong while creating your cluster on Google Container Engine')
- %p.js-error-reason
-
- .hidden.js-cluster-creating.alert.alert-info.alert-block.append-bottom-10{ role: 'alert' }
- = s_('ClusterIntegration|Cluster is being created on Google Container Engine...')
-
- .hidden.js-cluster-success.alert.alert-success.alert-block.append-bottom-10{ role: 'alert' }
- = s_('ClusterIntegration|Cluster was successfully created on Google Container Engine')
-
- %p
- - if @cluster.enabled?
- - if can?(current_user, :update_cluster, @cluster)
- = s_('ClusterIntegration|Cluster integration is enabled for this project. Disabling this integration will not affect your cluster, it will only temporarily turn off GitLab\'s connection to it.')
- - else
- = s_('ClusterIntegration|Cluster integration is enabled for this project.')
- - else
- = s_('ClusterIntegration|Cluster integration is disabled for this project.')
-
- = 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
- = field.hidden_field :enabled, { class: 'js-toggle-input'}
-
- %button{ type: 'button',
- class: "js-toggle-cluster project-feature-toggle #{'checked' unless !@cluster.enabled?} #{'disabled' unless can?(current_user, :update_cluster, @cluster)}",
- 'aria-label': s_('ClusterIntegration|Toggle Cluster'),
- disabled: !can?(current_user, :update_cluster, @cluster),
- data: { 'enabled-text': 'Enabled', 'disabled-text': 'Disabled' } }
-
- - if can?(current_user, :update_cluster, @cluster)
- .form-group
- = field.submit _('Save'), class: 'btn btn-success'
+ = render 'banner'
+ = render 'enabled'
.cluster-applications-table#js-cluster-applications
- %section.settings#js-cluster-details
+ %section.settings#js-cluster-details{ class: ('expanded' if expanded) }
.settings-header
%h4= s_('ClusterIntegration|Cluster details')
%button.btn.js-settings-toggle
@@ -66,20 +30,16 @@
%p= s_('ClusterIntegration|See and edit the details for your cluster')
.settings-content
-
- .form_group.append-bottom-20
- %label.append-bottom-10{ for: 'cluster-name' }
- = s_('ClusterIntegration|Cluster name')
- .input-group
- %input.form-control.cluster-name{ value: @cluster.name, disabled: true }
- %span.input-group-addon.clipboard-addon
- = clipboard_button(text: @cluster.name, title: s_('ClusterIntegration|Copy cluster name'))
+ - if @cluster.managed?
+ = render 'projects/clusters/gcp/show'
+ - else
+ = render 'projects/clusters/user/show'
%section.settings.no-animate#js-cluster-advanced-settings{ class: ('expanded' if expanded) }
.settings-header
%h4= _('Advanced settings')
%button.btn.js-settings-toggle
= expanded ? 'Collapse' : 'Expand'
- %p= s_('ClusterIntegration|Manage Cluster integration on your GitLab project')
+ %p= s_('ClusterIntegration|Manage cluster integration on your GitLab project')
.settings-content
= render 'advanced_settings'
diff --git a/app/views/projects/clusters/user/_form.html.haml b/app/views/projects/clusters/user/_form.html.haml
new file mode 100644
index 00000000000..4a9bd5186c6
--- /dev/null
+++ b/app/views/projects/clusters/user/_form.html.haml
@@ -0,0 +1,25 @@
+= form_for @cluster, url: user_namespace_project_clusters_path(@project.namespace, @project), as: :cluster do |field|
+ = form_errors(@cluster)
+ .form-group
+ = field.label :name, s_('ClusterIntegration|Cluster name')
+ = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Cluster name')
+
+ = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
+ .form-group
+ = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL')
+ = platform_kubernetes_field.text_field :api_url, class: 'form-control', placeholder: s_('ClusterIntegration|API URL')
+
+ .form-group
+ = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate')
+ = platform_kubernetes_field.text_area :ca_cert, class: 'form-control', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)')
+
+ .form-group
+ = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token')
+ = platform_kubernetes_field.text_field :token, class: 'form-control', placeholder: s_('ClusterIntegration|Service token'), autocomplete: 'off'
+
+ .form-group
+ = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)')
+ = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
+
+ .form-group
+ = field.submit s_('ClusterIntegration|Add cluster'), class: 'btn btn-success'
diff --git a/app/views/projects/clusters/user/_header.html.haml b/app/views/projects/clusters/user/_header.html.haml
new file mode 100644
index 00000000000..06ac210a06d
--- /dev/null
+++ b/app/views/projects/clusters/user/_header.html.haml
@@ -0,0 +1,5 @@
+%h4.prepend-top-20
+ = s_('ClusterIntegration|Enter the details for your cluster')
+%p
+ - link_to_help_page = link_to(s_('ClusterIntegration|documentation'), help_page_path('user/project/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
+ = s_('ClusterIntegration|Please enter access information for your cluster. If you need help, you can read our %{link_to_help_page} on clusters').html_safe % { link_to_help_page: link_to_help_page }
diff --git a/app/views/projects/clusters/user/_show.html.haml b/app/views/projects/clusters/user/_show.html.haml
new file mode 100644
index 00000000000..5931e0b7f17
--- /dev/null
+++ b/app/views/projects/clusters/user/_show.html.haml
@@ -0,0 +1,29 @@
+= form_for @cluster, url: namespace_project_cluster_path(@project.namespace, @project, @cluster), as: :cluster do |field|
+ = form_errors(@cluster)
+ .form-group
+ = field.label :name, s_('ClusterIntegration|Cluster name')
+ = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Cluster name')
+
+ = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
+ .form-group
+ = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL')
+ = platform_kubernetes_field.text_field :api_url, class: 'form-control', placeholder: s_('ClusterIntegration|API URL')
+
+ .form-group
+ = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate')
+ = platform_kubernetes_field.text_area :ca_cert, class: 'form-control', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)')
+
+ .form-group
+ = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token')
+ .input-group
+ = platform_kubernetes_field.text_field :token, class: 'form-control js-cluster-token', type: 'password', placeholder: s_('ClusterIntegration|Token'), autocomplete: 'off'
+ %span.input-group-addon.clipboard-addon
+ %button.js-show-cluster-token.btn-blank{ type: 'button' }
+ = s_('ClusterIntegration|Show')
+
+ .form-group
+ = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)')
+ = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
+
+ .form-group
+ = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/projects/clusters/user/new.html.haml b/app/views/projects/clusters/user/new.html.haml
new file mode 100644
index 00000000000..68f38f83453
--- /dev/null
+++ b/app/views/projects/clusters/user/new.html.haml
@@ -0,0 +1,11 @@
+- breadcrumb_title "Cluster"
+- page_title _("New Cluster")
+
+.row.prepend-top-default
+ .col-sm-4
+ = render 'projects/clusters/sidebar'
+ .col-sm-8
+ = render 'projects/clusters/dropdown', dropdown_text: s_('ClusterIntegration|Add an existing cluster')
+ = render 'header'
+ .prepend-top-20
+ = render 'form'