summaryrefslogtreecommitdiff
path: root/app/controllers/clusters
diff options
context:
space:
mode:
authorThong Kuah <tkuah@gitlab.com>2018-11-01 13:39:01 +1300
committerThong Kuah <tkuah@gitlab.com>2018-11-01 19:37:33 +1300
commit1a1fdf8efe1923ba781e978e858c009264020e72 (patch)
treedf98af221d7a722e4c67db450b78a5488bff6a3c /app/controllers/clusters
parent28dabc67f4db8271ac20c0db458ae2c86a906eee (diff)
downloadgitlab-ce-1a1fdf8efe1923ba781e978e858c009264020e72.tar.gz
Resolve controller sharing concern
Use ClustersController as base while having Projects::ClustersController to inform what `clusterable` is. Thanks @ayufan for the great suggestion ! - View changes to work with new approach - Fix javascript for new approach - Fix feature specs for new approach - Fix QA
Diffstat (limited to 'app/controllers/clusters')
-rw-r--r--app/controllers/clusters/base_controller.rb32
-rw-r--r--app/controllers/clusters/clusters_controller.rb218
2 files changed, 226 insertions, 24 deletions
diff --git a/app/controllers/clusters/base_controller.rb b/app/controllers/clusters/base_controller.rb
index 3a8575769c4..ef42f7c4074 100644
--- a/app/controllers/clusters/base_controller.rb
+++ b/app/controllers/clusters/base_controller.rb
@@ -2,31 +2,25 @@
class Clusters::BaseController < ApplicationController
include RoutableActions
- include ProjectUnauthorized
skip_before_action :authenticate_user!
- before_action :require_project_id
- before_action :project, if: :project_type?
- before_action :repository, if: :project_type?
before_action :authorize_read_cluster!
- layout :determine_layout
-
helper_method :clusterable
private
- # We can extend to `#group_type?` in the future
- def require_project_id
- not_found unless project_type?
+ def cluster
+ @cluster ||= clusterable.clusters.find(params[:id])
+ .present(current_user: current_user)
end
- def project
- @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]), not_found_or_authorized_proc: project_unauthorized_proc)
+ def authorize_update_cluster!
+ access_denied! unless can?(current_user, :update_cluster, cluster)
end
- def repository
- @repository ||= project.repository
+ def authorize_admin_cluster!
+ access_denied! unless can?(current_user, :admin_cluster, cluster)
end
def authorize_read_cluster!
@@ -37,17 +31,7 @@ class Clusters::BaseController < ApplicationController
access_denied! unless can?(current_user, :create_cluster, clusterable)
end
- def determine_layout
- if project_type?
- 'project'
- end
- end
-
def clusterable
- @clusterable ||= ClusterablePresenter.fabricate(project, current_user: current_user)
- end
-
- def project_type?
- params[:project_id].present?
+ raise NotImplementedError
end
end
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
new file mode 100644
index 00000000000..f6f2060ebb5
--- /dev/null
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -0,0 +1,218 @@
+# frozen_string_literal: true
+
+class Clusters::ClustersController < Clusters::BaseController
+ include RoutableActions
+
+ before_action :cluster, except: [:index, :new, :create_gcp, :create_user]
+ 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: [:cluster_status]
+
+ helper_method :token_in_session
+
+ STATUS_POLLING_INTERVAL = 10_000
+
+ def index
+ clusters = ClustersFinder.new(clusterable, current_user, :all).execute
+ @clusters = clusters.page(params[:page]).per(20)
+ end
+
+ def new
+ end
+
+ # Overridding ActionController::Metal#status is NOT a good idea
+ def cluster_status
+ respond_to do |format|
+ format.json do
+ Gitlab::PollingInterval.set_header(response, interval: STATUS_POLLING_INTERVAL)
+
+ render json: ClusterSerializer
+ .new(current_user: @current_user)
+ .represent_status(@cluster)
+ end
+ end
+ end
+
+ def show
+ end
+
+ def update
+ Clusters::UpdateService
+ .new(current_user, update_params)
+ .execute(cluster)
+
+ if cluster.valid?
+ respond_to do |format|
+ format.json do
+ head :no_content
+ end
+ format.html do
+ flash[:notice] = _('Kubernetes cluster was successfully updated.')
+ redirect_to cluster.show_path
+ end
+ end
+ else
+ respond_to do |format|
+ format.json { head :bad_request }
+ format.html { render :show }
+ end
+ end
+ end
+
+ def destroy
+ if cluster.destroy
+ flash[:notice] = _('Kubernetes cluster integration was successfully removed.')
+ redirect_to clusterable.index_path, status: :found
+ else
+ flash[:notice] = _('Kubernetes cluster integration was not removed.')
+ render :show
+ end
+ end
+
+ def create_gcp
+ @gcp_cluster = ::Clusters::CreateService
+ .new(current_user, create_gcp_cluster_params)
+ .execute(access_token: token_in_session)
+ .present(current_user: current_user)
+
+ if @gcp_cluster.persisted?
+ redirect_to @gcp_cluster.show_path
+ 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(current_user, create_user_cluster_params)
+ .execute(access_token: token_in_session)
+ .present(current_user: current_user)
+
+ if @user_cluster.persisted?
+ redirect_to @user_cluster.show_path
+ else
+ generate_gcp_authorize_url
+ validate_gcp_token
+ gcp_cluster
+
+ render :new, locals: { active_tab: 'user' }
+ end
+ end
+
+ private
+
+ def update_params
+ if cluster.managed?
+ params.require(:cluster).permit(
+ :enabled,
+ :environment_scope,
+ platform_kubernetes_attributes: [
+ :namespace
+ ]
+ )
+ else
+ params.require(:cluster).permit(
+ :enabled,
+ :name,
+ :environment_scope,
+ platform_kubernetes_attributes: [
+ :api_url,
+ :token,
+ :ca_cert,
+ :namespace
+ ]
+ )
+ 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,
+ :legacy_abac
+ ]).merge(
+ provider_type: :gcp,
+ platform_type: :kubernetes,
+ clusterable: clusterable.subject
+ )
+ end
+
+ def create_user_cluster_params
+ params.require(:cluster).permit(
+ :enabled,
+ :name,
+ :environment_scope,
+ platform_kubernetes_attributes: [
+ :namespace,
+ :api_url,
+ :token,
+ :ca_cert,
+ :authorization_type
+ ]).merge(
+ provider_type: :user,
+ platform_type: :kubernetes,
+ clusterable: clusterable.subject
+ )
+ end
+
+ def generate_gcp_authorize_url
+ state = generate_session_key_redirect(clusterable.new_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
+
+ 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 update_applications_status
+ @cluster.applications.each(&:schedule_status_update)
+ end
+end