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
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/pages/projects/clusters/gcp/login/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/clusters/new/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/index.js14
-rw-r--r--app/controllers/projects/clusters/gcp_controller.rb76
-rw-r--r--app/controllers/projects/clusters/user_controller.rb40
-rw-r--r--app/controllers/projects/clusters_controller.rb113
-rw-r--r--app/views/projects/clusters/_dropdown.html.haml12
-rw-r--r--app/views/projects/clusters/gcp/_form.html.haml8
-rw-r--r--app/views/projects/clusters/gcp/_header.html.haml2
-rw-r--r--app/views/projects/clusters/gcp/login.html.haml21
-rw-r--r--app/views/projects/clusters/gcp/new.html.haml10
-rw-r--r--app/views/projects/clusters/new.html.haml35
-rw-r--r--app/views/projects/clusters/user/_form.html.haml6
-rw-r--r--app/views/projects/clusters/user/_header.html.haml2
-rw-r--r--app/views/projects/clusters/user/new.html.haml11
-rw-r--r--changelogs/unreleased/43446-new-cluster-page-tabs.yml5
-rw-r--r--config/routes/project.rb10
-rw-r--r--qa/qa/page/project/operations/kubernetes/add.rb4
-rw-r--r--spec/controllers/projects/clusters/gcp_controller_spec.rb182
-rw-r--r--spec/controllers/projects/clusters/user_controller_spec.rb89
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb226
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb10
-rw-r--r--spec/features/projects/clusters/user_spec.rb2
-rw-r--r--spec/features/projects/clusters_spec.rb2
24 files changed, 406 insertions, 480 deletions
diff --git a/app/assets/javascripts/pages/projects/clusters/gcp/login/index.js b/app/assets/javascripts/pages/projects/clusters/gcp/login/index.js
deleted file mode 100644
index 0c2d7d7c96a..00000000000
--- a/app/assets/javascripts/pages/projects/clusters/gcp/login/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import gcpSignupOffer from '~/clusters/components/gcp_signup_offer';
-
-gcpSignupOffer();
diff --git a/app/assets/javascripts/pages/projects/clusters/new/index.js b/app/assets/javascripts/pages/projects/clusters/new/index.js
deleted file mode 100644
index 0c2d7d7c96a..00000000000
--- a/app/assets/javascripts/pages/projects/clusters/new/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import gcpSignupOffer from '~/clusters/components/gcp_signup_offer';
-
-gcpSignupOffer();
diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js
index de1e13de7e9..0658ae8ec23 100644
--- a/app/assets/javascripts/pages/projects/index.js
+++ b/app/assets/javascripts/pages/projects/index.js
@@ -1,7 +1,21 @@
+import gcpSignupOffer from '~/clusters/components/gcp_signup_offer';
+import initGkeDropdowns from '~/projects/gke_cluster_dropdowns';
import Project from './project';
import ShortcutsNavigation from '../../shortcuts_navigation';
document.addEventListener('DOMContentLoaded', () => {
+ const page = document.body.dataset.page;
+ const newClusterViews = [
+ 'projects:clusters:new',
+ 'projects:clusters:create_gcp',
+ 'projects:clusters:create_user',
+ ];
+
+ if (newClusterViews.indexOf(page) > -1) {
+ gcpSignupOffer();
+ initGkeDropdowns();
+ }
+
new Project(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
});
diff --git a/app/controllers/projects/clusters/gcp_controller.rb b/app/controllers/projects/clusters/gcp_controller.rb
deleted file mode 100644
index c2c5ad61e01..00000000000
--- a/app/controllers/projects/clusters/gcp_controller.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-class Projects::Clusters::GcpController < Projects::ApplicationController
- before_action :authorize_read_cluster!
- before_action :authorize_create_cluster!, only: [:new, :create]
- before_action :authorize_google_api, except: :login
- helper_method :token_in_session
-
- 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,
- :environment_scope,
- 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
- 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
deleted file mode 100644
index d0db64b2fa9..00000000000
--- a/app/controllers/projects/clusters/user_controller.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-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,
- :environment_scope,
- 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 d58039b7d42..62193257940 100644
--- a/app/controllers/projects/clusters_controller.rb
+++ b/app/controllers/projects/clusters_controller.rb
@@ -1,10 +1,15 @@
class Projects::ClustersController < Projects::ApplicationController
- before_action :cluster, except: [:index, :new]
+ before_action :cluster, except: [:index, :new, :create_gcp, :create_user]
before_action :authorize_read_cluster!
+ before_action :generate_gcp_authorize_url, only: [:new]
+ before_action :validate_gcp_token, only: [:new]
+ before_action :gcp_cluster, only: [:new]
+ before_action :user_cluster, only: [:new]
before_action :authorize_create_cluster!, only: [:new]
before_action :authorize_update_cluster!, only: [:update]
before_action :authorize_admin_cluster!, only: [:destroy]
before_action :update_applications_status, only: [:status]
+ helper_method :token_in_session
STATUS_POLLING_INTERVAL = 10_000
@@ -64,6 +69,38 @@ class Projects::ClustersController < Projects::ApplicationController
end
end
+ def create_gcp
+ @gcp_cluster = ::Clusters::CreateService
+ .new(project, current_user, create_gcp_cluster_params)
+ .execute(token_in_session)
+
+ if @gcp_cluster.persisted?
+ redirect_to project_cluster_path(project, @gcp_cluster)
+ else
+ generate_gcp_authorize_url
+ validate_gcp_token
+ user_cluster
+
+ render :new, locals: { active_tab: 'gcp' }
+ end
+ end
+
+ def create_user
+ @user_cluster = ::Clusters::CreateService
+ .new(project, current_user, create_user_cluster_params)
+ .execute(token_in_session)
+
+ if @user_cluster.persisted?
+ redirect_to project_cluster_path(project, @user_cluster)
+ else
+ generate_gcp_authorize_url
+ validate_gcp_token
+ gcp_cluster
+
+ render :new, locals: { active_tab: 'user' }
+ end
+ end
+
private
def cluster
@@ -95,6 +132,80 @@ class Projects::ClustersController < Projects::ApplicationController
end
end
+ def create_gcp_cluster_params
+ params.require(:cluster).permit(
+ :enabled,
+ :name,
+ :environment_scope,
+ provider_gcp_attributes: [
+ :gcp_project_id,
+ :zone,
+ :num_nodes,
+ :machine_type
+ ]).merge(
+ provider_type: :gcp,
+ platform_type: :kubernetes
+ )
+ end
+
+ def create_user_cluster_params
+ params.require(:cluster).permit(
+ :enabled,
+ :name,
+ :environment_scope,
+ platform_kubernetes_attributes: [
+ :namespace,
+ :api_url,
+ :token,
+ :ca_cert
+ ]).merge(
+ provider_type: :user,
+ platform_type: :kubernetes
+ )
+ end
+
+ def generate_gcp_authorize_url
+ state = generate_session_key_redirect(new_project_cluster_path(@project).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
+
+ def gcp_cluster
+ @gcp_cluster = ::Clusters::Cluster.new.tap do |cluster|
+ cluster.build_provider_gcp
+ end
+ end
+
+ def user_cluster
+ @user_cluster = ::Clusters::Cluster.new.tap do |cluster|
+ cluster.build_platform_kubernetes
+ end
+ end
+
+ def validate_gcp_token
+ @valid_gcp_token = GoogleApi::CloudPlatform::Client.new(token_in_session, nil)
+ .validate_token(expires_at_in_session)
+ end
+
+ def 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
+
def authorize_update_cluster!
access_denied! unless can?(current_user, :update_cluster, cluster)
end
diff --git a/app/views/projects/clusters/_dropdown.html.haml b/app/views/projects/clusters/_dropdown.html.haml
deleted file mode 100644
index d55a9c60b64..00000000000
--- a/app/views/projects/clusters/_dropdown.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-%h4.prepend-top-0= s_('ClusterIntegration|Choose how to set up Kubernetes 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 Kubernetes cluster on Google Kubernetes Engine'), gcp_new_namespace_project_clusters_path(@project.namespace, @project))
- %li
- = link_to(s_('ClusterIntegration|Add an existing Kubernetes cluster'), user_new_namespace_project_clusters_path(@project.namespace, @project))
diff --git a/app/views/projects/clusters/gcp/_form.html.haml b/app/views/projects/clusters/gcp/_form.html.haml
index b8e40b0a38b..0a2e320556d 100644
--- a/app/views/projects/clusters/gcp/_form.html.haml
+++ b/app/views/projects/clusters/gcp/_form.html.haml
@@ -10,8 +10,10 @@
- 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 Kubernetes cluster integration.').html_safe % { link_to_help_page: link_to_help_page}
-= form_for @cluster, html: { class: 'js-gke-cluster-creation prepend-top-20', data: { token: token_in_session } }, url: gcp_namespace_project_clusters_path(@project.namespace, @project), as: :cluster do |field|
- = form_errors(@cluster)
+%p= link_to('Select a different Google account', @authorize_url)
+
+= form_for @gcp_cluster, html: { class: 'js-gke-cluster-creation prepend-top-20', data: { token: token_in_session } }, url: create_gcp_namespace_project_clusters_path(@project.namespace, @project), as: :cluster do |field|
+ = form_errors(@gcp_cluster)
.form-group
= field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-light'
= field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
@@ -19,7 +21,7 @@
= field.label :environment_scope, s_('ClusterIntegration|Environment scope'), class: 'label-light'
= field.text_field :environment_scope, class: 'form-control', readonly: !has_multiple_clusters?(@project), placeholder: s_('ClusterIntegration|Environment scope')
- = field.fields_for :provider_gcp, @cluster.provider_gcp do |provider_gcp_field|
+ = field.fields_for :provider_gcp, @gcp_cluster.provider_gcp do |provider_gcp_field|
.form-group
= provider_gcp_field.label :gcp_project_id, s_('ClusterIntegration|Google Cloud Platform project'), class: 'label-light'
.js-gcp-project-id-dropdown-entry-point{ data: { docsUrl: 'https://console.cloud.google.com/home/dashboard' } }
diff --git a/app/views/projects/clusters/gcp/_header.html.haml b/app/views/projects/clusters/gcp/_header.html.haml
index fa989943492..a2ad3cd64df 100644
--- a/app/views/projects/clusters/gcp/_header.html.haml
+++ b/app/views/projects/clusters/gcp/_header.html.haml
@@ -1,4 +1,4 @@
-%h4.prepend-top-20
+%h4
= s_('ClusterIntegration|Enter the details for your Kubernetes cluster')
%p
= s_('ClusterIntegration|Please make sure that your Google account meets the following requirements:')
diff --git a/app/views/projects/clusters/gcp/login.html.haml b/app/views/projects/clusters/gcp/login.html.haml
deleted file mode 100644
index 96c7a648676..00000000000
--- a/app/views/projects/clusters/gcp/login.html.haml
+++ /dev/null
@@ -1,21 +0,0 @@
-- breadcrumb_title 'Kubernetes'
-- page_title _("Login")
-
-= render_gcp_signup_offer
-
-.row.prepend-top-default
- .col-sm-4
- = render 'projects/clusters/sidebar'
- .col-sm-8
- = render 'projects/clusters/dropdown', dropdown_text: s_('ClusterIntegration|Create Kubernetes cluster on Google Kubernetes Engine')
- = render 'header'
-.row
- .col-sm-8.offset-sm-4.signin-with-google
- - if @authorize_url
- = link_to(image_tag('auth_buttons/signin_with_google.png', width: '191px'), @authorize_url)
- = _('or')
- = link_to('create a new Google account', 'https://accounts.google.com/SignUpWithoutGmail?service=cloudconsole&continue=https%3A%2F%2Fconsole.cloud.google.com%2Ffreetrial%3Futm_campaign%3D2018_cpanel%26utm_source%3Dgitlab%26utm_medium%3Dreferral', target: '_blank', rel: 'noopener noreferrer')
- - else
- .settings-message.text-center
- - link = link_to(s_('ClusterIntegration|properly configured'), help_page_path("integration/google"), target: '_blank', rel: 'noopener noreferrer')
- = s_('Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service.').html_safe % { link_to_documentation: link }
diff --git a/app/views/projects/clusters/gcp/new.html.haml b/app/views/projects/clusters/gcp/new.html.haml
deleted file mode 100644
index ea78d66d883..00000000000
--- a/app/views/projects/clusters/gcp/new.html.haml
+++ /dev/null
@@ -1,10 +0,0 @@
-- breadcrumb_title 'Kubernetes'
-- page_title _("New Kubernetes Cluster")
-
-.row.prepend-top-default
- .col-sm-4
- = render 'projects/clusters/sidebar'
- .col-sm-8
- = render 'projects/clusters/dropdown', dropdown_text: s_('ClusterIntegration|Create Kubernetes cluster on Google Kubernetes Engine')
- = render 'header'
- = render 'form'
diff --git a/app/views/projects/clusters/new.html.haml b/app/views/projects/clusters/new.html.haml
index 828e2a84753..a38003f5750 100644
--- a/app/views/projects/clusters/new.html.haml
+++ b/app/views/projects/clusters/new.html.haml
@@ -1,15 +1,36 @@
- breadcrumb_title 'Kubernetes'
- page_title _("Kubernetes Cluster")
+- active_tab = local_assigns.fetch(:active_tab, 'gcp')
+= javascript_include_tag 'https://apis.google.com/js/api.js'
= render_gcp_signup_offer
.row.prepend-top-default
- .col-sm-4
+ .col-md-3
= render 'sidebar'
- .col-sm-8
- %h4.prepend-top-0= s_('ClusterIntegration|Choose how to set up Kubernetes cluster integration')
+ .col-md-9.js-toggle-container
+ %ul.nav-links.nav-tabs.gitlab-tabs.nav{ role: 'tablist' }
+ %li.nav-item{ role: 'presentation' }
+ %a.nav-link{ href: '#create-gcp-cluster-pane', id: 'create-gcp-cluster-tab', class: active_when(active_tab == 'gcp'), data: { toggle: 'tab' }, role: 'tab' }
+ %span Create new Cluster on GKE
+ %li.nav-item{ role: 'presentation' }
+ %a.nav-link{ href: '#add-user-cluster-pane', id: 'add-user-cluster-tab', class: active_when(active_tab == 'user'), data: { toggle: 'tab' }, role: 'tab' }
+ %span Add existing cluster
- %p= s_('ClusterIntegration|Create a new Kubernetes cluster on Google Kubernetes Engine right from GitLab')
- = link_to s_('ClusterIntegration|Create on Google Kubernetes Engine'), 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 Kubernetes cluster'), user_new_namespace_project_clusters_path(@project.namespace, @project), class: 'btn append-bottom-20'
+ .tab-content.gitlab-tab-content
+ .tab-pane{ id: 'create-gcp-cluster-pane', class: active_when(active_tab == 'gcp'), role: 'tabpanel' }
+ = render 'projects/clusters/gcp/header'
+ - if @valid_gcp_token
+ = render 'projects/clusters/gcp/form'
+ - elsif @authorize_url
+ .signin-with-google
+ = link_to(image_tag('auth_buttons/signin_with_google.png', width: '191px'), @authorize_url)
+ = _('or')
+ = link_to('create a new Google account', 'https://accounts.google.com/SignUpWithoutGmail?service=cloudconsole&continue=https%3A%2F%2Fconsole.cloud.google.com%2Ffreetrial%3Futm_campaign%3D2018_cpanel%26utm_source%3Dgitlab%26utm_medium%3Dreferral', target: '_blank', rel: 'noopener noreferrer')
+ - else
+ - link = link_to(s_('ClusterIntegration|properly configured'), help_page_path("integration/google"), target: '_blank', rel: 'noopener noreferrer')
+ = s_('Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service.').html_safe % { link_to_documentation: link }
+
+ .tab-pane{ id: 'add-user-cluster-pane', class: active_when(active_tab == 'user'), role: 'tabpanel' }
+ = render 'projects/clusters/user/header'
+ = render 'projects/clusters/user/form'
diff --git a/app/views/projects/clusters/user/_form.html.haml b/app/views/projects/clusters/user/_form.html.haml
index d45ae6ec91f..3006bb5073e 100644
--- a/app/views/projects/clusters/user/_form.html.haml
+++ b/app/views/projects/clusters/user/_form.html.haml
@@ -1,5 +1,5 @@
-= form_for @cluster, url: user_namespace_project_clusters_path(@project.namespace, @project), as: :cluster do |field|
- = form_errors(@cluster)
+= form_for @user_cluster, url: create_user_namespace_project_clusters_path(@project.namespace, @project), as: :cluster do |field|
+ = form_errors(@user_cluster)
.form-group
= field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-light'
= field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
@@ -8,7 +8,7 @@
= field.label :environment_scope, s_('ClusterIntegration|Environment scope'), class: 'label-light'
= field.text_field :environment_scope, class: 'form-control', placeholder: s_('ClusterIntegration|Environment scope')
- = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
+ = field.fields_for :platform_kubernetes, @user_cluster.platform_kubernetes do |platform_kubernetes_field|
.form-group
= platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL'), class: 'label-light'
= platform_kubernetes_field.text_field :api_url, class: 'form-control', placeholder: s_('ClusterIntegration|API URL')
diff --git a/app/views/projects/clusters/user/_header.html.haml b/app/views/projects/clusters/user/_header.html.haml
index 37f6a788518..749177fa6c1 100644
--- a/app/views/projects/clusters/user/_header.html.haml
+++ b/app/views/projects/clusters/user/_header.html.haml
@@ -1,4 +1,4 @@
-%h4.prepend-top-20
+%h4
= s_('ClusterIntegration|Enter the details for your Kubernetes cluster')
%p
- link_to_help_page = link_to(s_('ClusterIntegration|documentation'), help_page_path('user/project/clusters/index', anchor: 'adding-an-existing-kubernetes-cluster'), target: '_blank', rel: 'noopener noreferrer')
diff --git a/app/views/projects/clusters/user/new.html.haml b/app/views/projects/clusters/user/new.html.haml
deleted file mode 100644
index 7fb75cd9cc7..00000000000
--- a/app/views/projects/clusters/user/new.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-- breadcrumb_title 'Kubernetes'
-- page_title _("New Kubernetes 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 Kubernetes cluster')
- = render 'header'
- .prepend-top-20
- = render 'form'
diff --git a/changelogs/unreleased/43446-new-cluster-page-tabs.yml b/changelogs/unreleased/43446-new-cluster-page-tabs.yml
new file mode 100644
index 00000000000..e8c73257b16
--- /dev/null
+++ b/changelogs/unreleased/43446-new-cluster-page-tabs.yml
@@ -0,0 +1,5 @@
+---
+title: Create new or add existing Kubernetes cluster from a single page
+merge_request: 18963
+author:
+type: changed
diff --git a/config/routes/project.rb b/config/routes/project.rb
index b689b9800e6..a9cff7ff028 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -206,14 +206,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :clusters, except: [:edit, :create] do
collection do
- scope :providers do
- get '/user/new', to: 'clusters/user#new'
- post '/user', to: 'clusters/user#create'
-
- get '/gcp/new', to: 'clusters/gcp#new'
- get '/gcp/login', to: 'clusters/gcp#login'
- post '/gcp', to: 'clusters/gcp#create'
- end
+ post :create_gcp
+ post :create_user
end
member do
diff --git a/qa/qa/page/project/operations/kubernetes/add.rb b/qa/qa/page/project/operations/kubernetes/add.rb
index 9b3c482fa6c..11ebe10fb18 100644
--- a/qa/qa/page/project/operations/kubernetes/add.rb
+++ b/qa/qa/page/project/operations/kubernetes/add.rb
@@ -5,11 +5,11 @@ module QA
module Kubernetes
class Add < Page::Base
view 'app/views/projects/clusters/new.html.haml' do
- element :add_kubernetes_cluster_button, "link_to s_('ClusterIntegration|Add an existing Kubernetes cluster')"
+ element :add_existing_cluster_button, "Add existing cluster"
end
def add_existing_cluster
- click_on 'Add an existing Kubernetes cluster'
+ click_on 'Add existing cluster'
end
end
end
diff --git a/spec/controllers/projects/clusters/gcp_controller_spec.rb b/spec/controllers/projects/clusters/gcp_controller_spec.rb
deleted file mode 100644
index 271ba37aed4..00000000000
--- a/spec/controllers/projects/clusters/gcp_controller_spec.rb
+++ /dev/null
@@ -1,182 +0,0 @@
-require 'spec_helper'
-
-describe Projects::Clusters::GcpController do
- include AccessMatchersForController
- include GoogleApi::CloudPlatformHelpers
-
- set(:project) { create(:project) }
-
- describe 'GET login' do
- describe 'functionality' do
- let(:user) { create(:user) }
-
- before do
- project.add_master(user)
- sign_in(user)
- end
-
- context 'when omniauth has been configured' do
- let(:key) { 'secret-key' }
- let(:session_key_for_redirect_uri) do
- GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(key)
- end
-
- before do
- allow(SecureRandom).to receive(:hex).and_return(key)
- end
-
- it 'has authorize_url' do
- go
-
- expect(assigns(:authorize_url)).to include(key)
- expect(session[session_key_for_redirect_uri]).to eq(gcp_new_project_clusters_path(project))
- end
- end
-
- context 'when omniauth has not configured' do
- before do
- stub_omniauth_setting(providers: [])
- end
-
- it 'does not have authorize_url' do
- go
-
- expect(assigns(:authorize_url)).to be_nil
- end
- end
- end
-
- describe 'security' do
- it { expect { go }.to be_allowed_for(:admin) }
- it { expect { go }.to be_allowed_for(:owner).of(project) }
- it { expect { go }.to be_allowed_for(:master).of(project) }
- it { expect { go }.to be_denied_for(:developer).of(project) }
- it { expect { go }.to be_denied_for(:reporter).of(project) }
- it { expect { go }.to be_denied_for(:guest).of(project) }
- it { expect { go }.to be_denied_for(:user) }
- it { expect { go }.to be_denied_for(:external) }
- end
-
- def go
- get :login, namespace_id: project.namespace, project_id: project
- end
- end
-
- describe 'GET new' do
- describe 'functionality' do
- let(:user) { create(:user) }
-
- before do
- project.add_master(user)
- sign_in(user)
- end
-
- context 'when access token is valid' do
- before do
- stub_google_api_validate_token
- end
-
- it 'has new object' do
- go
-
- expect(assigns(:cluster)).to be_an_instance_of(Clusters::Cluster)
- end
- end
-
- context 'when access token is expired' do
- before do
- stub_google_api_expired_token
- end
-
- it { expect(go).to redirect_to(gcp_login_project_clusters_path(project)) }
- end
-
- context 'when access token is not stored in session' do
- it { expect(go).to redirect_to(gcp_login_project_clusters_path(project)) }
- end
- end
-
- describe 'security' do
- it { expect { go }.to be_allowed_for(:admin) }
- it { expect { go }.to be_allowed_for(:owner).of(project) }
- it { expect { go }.to be_allowed_for(:master).of(project) }
- it { expect { go }.to be_denied_for(:developer).of(project) }
- it { expect { go }.to be_denied_for(:reporter).of(project) }
- it { expect { go }.to be_denied_for(:guest).of(project) }
- it { expect { go }.to be_denied_for(:user) }
- it { expect { go }.to be_denied_for(:external) }
- end
-
- def go
- get :new, namespace_id: project.namespace, project_id: project
- end
- end
-
- describe 'POST create' do
- let(:params) do
- {
- cluster: {
- name: 'new-cluster',
- provider_gcp_attributes: {
- gcp_project_id: '111'
- }
- }
- }
- end
-
- describe 'functionality' do
- let(:user) { create(:user) }
-
- before do
- project.add_master(user)
- sign_in(user)
- end
-
- context 'when access token is valid' do
- before do
- stub_google_api_validate_token
- end
-
- it 'creates a new cluster' do
- expect(ClusterProvisionWorker).to receive(:perform_async)
- expect { go }.to change { Clusters::Cluster.count }
- .and change { Clusters::Providers::Gcp.count }
- expect(response).to redirect_to(project_cluster_path(project, project.clusters.first))
- expect(project.clusters.first).to be_gcp
- expect(project.clusters.first).to be_kubernetes
- end
- end
-
- context 'when access token is expired' do
- before do
- stub_google_api_expired_token
- end
-
- it 'redirects to login page' do
- expect(go).to redirect_to(gcp_login_project_clusters_path(project))
- end
- end
-
- context 'when access token is not stored in session' do
- it 'redirects to login page' do
- expect(go).to redirect_to(gcp_login_project_clusters_path(project))
- end
- end
- end
-
- describe 'security' do
- it { expect { go }.to be_allowed_for(:admin) }
- it { expect { go }.to be_allowed_for(:owner).of(project) }
- it { expect { go }.to be_allowed_for(:master).of(project) }
- it { expect { go }.to be_denied_for(:developer).of(project) }
- it { expect { go }.to be_denied_for(:reporter).of(project) }
- it { expect { go }.to be_denied_for(:guest).of(project) }
- it { expect { go }.to be_denied_for(:user) }
- it { expect { go }.to be_denied_for(:external) }
- end
-
- def go
- post :create, params.merge(namespace_id: project.namespace, project_id: project)
- end
- end
-end
diff --git a/spec/controllers/projects/clusters/user_controller_spec.rb b/spec/controllers/projects/clusters/user_controller_spec.rb
deleted file mode 100644
index 913976d187f..00000000000
--- a/spec/controllers/projects/clusters/user_controller_spec.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-require 'spec_helper'
-
-describe Projects::Clusters::UserController do
- include AccessMatchersForController
-
- set(:project) { create(:project) }
-
- describe 'GET new' do
- describe 'functionality' do
- let(:user) { create(:user) }
-
- before do
- project.add_master(user)
- sign_in(user)
- end
-
- it 'has new object' do
- go
-
- expect(assigns(:cluster)).to be_an_instance_of(Clusters::Cluster)
- end
- end
-
- describe 'security' do
- it { expect { go }.to be_allowed_for(:admin) }
- it { expect { go }.to be_allowed_for(:owner).of(project) }
- it { expect { go }.to be_allowed_for(:master).of(project) }
- it { expect { go }.to be_denied_for(:developer).of(project) }
- it { expect { go }.to be_denied_for(:reporter).of(project) }
- it { expect { go }.to be_denied_for(:guest).of(project) }
- it { expect { go }.to be_denied_for(:user) }
- it { expect { go }.to be_denied_for(:external) }
- end
-
- def go
- get :new, namespace_id: project.namespace, project_id: project
- end
- end
-
- describe 'POST create' do
- let(:params) do
- {
- cluster: {
- name: 'new-cluster',
- platform_kubernetes_attributes: {
- api_url: 'http://my-url',
- token: 'test',
- namespace: 'aaa'
- }
- }
- }
- end
-
- describe 'functionality' do
- let(:user) { create(:user) }
-
- before do
- project.add_master(user)
- sign_in(user)
- end
-
- context 'when creates a cluster' do
- it 'creates a new cluster' do
- expect(ClusterProvisionWorker).to receive(:perform_async)
- expect { go }.to change { Clusters::Cluster.count }
- .and change { Clusters::Platforms::Kubernetes.count }
- expect(response).to redirect_to(project_cluster_path(project, project.clusters.first))
- expect(project.clusters.first).to be_user
- expect(project.clusters.first).to be_kubernetes
- end
- end
- end
-
- describe 'security' do
- it { expect { go }.to be_allowed_for(:admin) }
- it { expect { go }.to be_allowed_for(:owner).of(project) }
- it { expect { go }.to be_allowed_for(:master).of(project) }
- it { expect { go }.to be_denied_for(:developer).of(project) }
- it { expect { go }.to be_denied_for(:reporter).of(project) }
- it { expect { go }.to be_denied_for(:guest).of(project) }
- it { expect { go }.to be_denied_for(:user) }
- it { expect { go }.to be_denied_for(:external) }
- end
-
- def go
- post :create, params.merge(namespace_id: project.namespace, project_id: project)
- end
- end
-end
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index 380e50c8cac..e47ccdc9aea 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe Projects::ClustersController do
include AccessMatchersForController
+ include GoogleApi::CloudPlatformHelpers
set(:project) { create(:project) }
@@ -73,6 +74,231 @@ describe Projects::ClustersController do
end
end
+ describe 'GET new' do
+ describe 'functionality for new cluster' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+ end
+
+ context 'when omniauth has been configured' do
+ let(:key) { 'secret-key' }
+ let(:session_key_for_redirect_uri) do
+ GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(key)
+ end
+
+ before do
+ allow(SecureRandom).to receive(:hex).and_return(key)
+ end
+
+ it 'has authorize_url' do
+ go
+
+ expect(assigns(:authorize_url)).to include(key)
+ expect(session[session_key_for_redirect_uri]).to eq(new_project_cluster_path(project))
+ end
+ end
+
+ context 'when omniauth has not configured' do
+ before do
+ stub_omniauth_setting(providers: [])
+ end
+
+ it 'does not have authorize_url' do
+ go
+
+ expect(assigns(:authorize_url)).to be_nil
+ end
+ end
+
+ context 'when access token is valid' do
+ before do
+ stub_google_api_validate_token
+ end
+
+ it 'has new object' do
+ go
+
+ expect(assigns(:gcp_cluster)).to be_an_instance_of(Clusters::Cluster)
+ end
+ end
+
+ context 'when access token is expired' do
+ before do
+ stub_google_api_expired_token
+ end
+
+ it { expect(@valid_gcp_token).to be_falsey }
+ end
+
+ context 'when access token is not stored in session' do
+ it { expect(@valid_gcp_token).to be_falsey }
+ end
+ end
+
+ describe 'functionality for existing cluster' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+ end
+
+ it 'has new object' do
+ go
+
+ expect(assigns(:user_cluster)).to be_an_instance_of(Clusters::Cluster)
+ end
+ end
+
+ describe 'security' do
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(project) }
+ it { expect { go }.to be_allowed_for(:master).of(project) }
+ it { expect { go }.to be_denied_for(:developer).of(project) }
+ it { expect { go }.to be_denied_for(:reporter).of(project) }
+ it { expect { go }.to be_denied_for(:guest).of(project) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+
+ def go
+ get :new, namespace_id: project.namespace, project_id: project
+ end
+ end
+
+ describe 'POST create for new cluster' do
+ let(:params) do
+ {
+ cluster: {
+ name: 'new-cluster',
+ provider_gcp_attributes: {
+ gcp_project_id: 'gcp-project-12345'
+ }
+ }
+ }
+ end
+
+ describe 'functionality' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+ end
+
+ context 'when access token is valid' do
+ before do
+ stub_google_api_validate_token
+ end
+
+ it 'creates a new cluster' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+ expect { go }.to change { Clusters::Cluster.count }
+ .and change { Clusters::Providers::Gcp.count }
+ expect(response).to redirect_to(project_cluster_path(project, project.clusters.first))
+ expect(project.clusters.first).to be_gcp
+ expect(project.clusters.first).to be_kubernetes
+ end
+ end
+
+ context 'when access token is expired' do
+ before do
+ stub_google_api_expired_token
+ end
+
+ it { expect(@valid_gcp_token).to be_falsey }
+ end
+
+ context 'when access token is not stored in session' do
+ it { expect(@valid_gcp_token).to be_falsey }
+ end
+ end
+
+ describe 'security' do
+ before do
+ allow_any_instance_of(described_class)
+ .to receive(:token_in_session).and_return('token')
+ allow_any_instance_of(described_class)
+ .to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s)
+ allow_any_instance_of(GoogleApi::CloudPlatform::Client)
+ .to receive(:projects_zones_clusters_create) do
+ OpenStruct.new(
+ self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
+ status: 'RUNNING'
+ )
+ end
+
+ allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil)
+ end
+
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(project) }
+ it { expect { go }.to be_allowed_for(:master).of(project) }
+ it { expect { go }.to be_denied_for(:developer).of(project) }
+ it { expect { go }.to be_denied_for(:reporter).of(project) }
+ it { expect { go }.to be_denied_for(:guest).of(project) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+
+ def go
+ post :create_gcp, params.merge(namespace_id: project.namespace, project_id: project)
+ end
+ end
+
+ describe 'POST create for existing cluster' do
+ let(:params) do
+ {
+ cluster: {
+ name: 'new-cluster',
+ platform_kubernetes_attributes: {
+ api_url: 'http://my-url',
+ token: 'test',
+ namespace: 'aaa'
+ }
+ }
+ }
+ end
+
+ describe 'functionality' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+ end
+
+ context 'when creates a cluster' do
+ it 'creates a new cluster' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+ expect { go }.to change { Clusters::Cluster.count }
+ .and change { Clusters::Platforms::Kubernetes.count }
+ expect(response).to redirect_to(project_cluster_path(project, project.clusters.first))
+ expect(project.clusters.first).to be_user
+ expect(project.clusters.first).to be_kubernetes
+ end
+ end
+ end
+
+ describe 'security' do
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(project) }
+ it { expect { go }.to be_allowed_for(:master).of(project) }
+ it { expect { go }.to be_denied_for(:developer).of(project) }
+ it { expect { go }.to be_denied_for(:reporter).of(project) }
+ it { expect { go }.to be_denied_for(:guest).of(project) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+
+ def go
+ post :create_user, params.merge(namespace_id: project.namespace, project_id: project)
+ end
+ end
+
describe 'GET status' do
let(:cluster) { create(:cluster, :providing_by_gcp, projects: [project]) }
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index 3db384e5b65..df21a42c3d3 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -16,9 +16,9 @@ feature 'Gcp Cluster', :js do
let(:project_id) { 'test-project-1234' }
before do
- allow_any_instance_of(Projects::Clusters::GcpController)
+ allow_any_instance_of(Projects::ClustersController)
.to receive(:token_in_session).and_return('token')
- allow_any_instance_of(Projects::Clusters::GcpController)
+ allow_any_instance_of(Projects::ClustersController)
.to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s)
end
@@ -27,7 +27,7 @@ feature 'Gcp Cluster', :js do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
- click_link 'Create on Google Kubernetes Engine'
+ click_link 'Create new Cluster on GKE'
end
context 'when user filled form with valid parameters' do
@@ -148,7 +148,7 @@ feature 'Gcp Cluster', :js do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
- click_link 'Create on Google Kubernetes Engine'
+ click_link 'Create new Cluster on GKE'
end
it 'user sees a login page' do
@@ -187,7 +187,7 @@ feature 'Gcp Cluster', :js do
it 'user sees offer on cluster GCP login page' do
click_link 'Add Kubernetes cluster'
- click_link 'Create on Google Kubernetes Engine'
+ click_link 'Create new Cluster on GKE'
expect(page).to have_css('.gcp-signup-offer')
end
diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb
index 698b64a659c..766ea58cc17 100644
--- a/spec/features/projects/clusters/user_spec.rb
+++ b/spec/features/projects/clusters/user_spec.rb
@@ -17,7 +17,7 @@ feature 'User Cluster', :js do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
- click_link 'Add an existing Kubernetes cluster'
+ click_link 'Add existing cluster'
end
context 'when user filled form with valid parameters' do
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
index a251a2f4e52..64241102c8b 100644
--- a/spec/features/projects/clusters_spec.rb
+++ b/spec/features/projects/clusters_spec.rb
@@ -83,7 +83,7 @@ feature 'Clusters', :js do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
- click_link 'Create on Google Kubernetes Engine'
+ click_link 'Create new Cluster on GKE'
end
it 'user sees a login page' do