diff options
author | Thong Kuah <tkuah@gitlab.com> | 2018-11-01 13:39:01 +1300 |
---|---|---|
committer | Thong Kuah <tkuah@gitlab.com> | 2018-11-01 19:37:33 +1300 |
commit | 1a1fdf8efe1923ba781e978e858c009264020e72 (patch) | |
tree | df98af221d7a722e4c67db450b78a5488bff6a3c /app/controllers/clusters | |
parent | 28dabc67f4db8271ac20c0db458ae2c86a906eee (diff) | |
download | gitlab-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.rb | 32 | ||||
-rw-r--r-- | app/controllers/clusters/clusters_controller.rb | 218 |
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 |