diff options
author | João Cunha <j.a.cunha@gmail.com> | 2019-02-18 20:06:51 +0300 |
---|---|---|
committer | jerasmus <jerasmus@gitlab.com> | 2019-03-05 09:32:51 +0300 |
commit | f8234d9a086a43a95698da13d2734fe62ddb9ad7 (patch) | |
tree | 14ac13feff76a5e622e26e58393863761a9eaa19 /app | |
parent | cf1b85dd726c1947f9ff2af8d89aa240747f462d (diff) |
Creates Clusterss::ApplciationsController update endpoint
- Creates new route
- Creates new controller action
- Creates call stack:
Clusterss::ApplciationsController calls -->
Clusters::Applications::UpdateService calls -->
Clusters::Applications::ScheduleUpdateService calls -->
ClusterUpdateAppWorker calls -->
Clusters::Applications::PatchService -->
ClusterWaitForAppInstallationWorker
DRY req params
Adds gcp_cluster:cluster_update_app queue
Schedule_update_service is uneeded
Extract common logic to a parent class (UpdateService will need it)
Introduce new UpdateService
Fix rescue class namespace
Fix RuboCop offenses
Adds BaseService for create and update services
Remove request_handler code duplication
Fixes update command
Move update_command to ApplicationCore so all apps can use it
Adds tests for Knative update_command
Adds specs for PatchService
Raise error if update receives an unistalled app
Adds update_service spec
Fix RuboCop offense
Use subject in favor of go
Adds update endpoint specs for project namespace
Adds update endpoint specs for group namespace
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/clusters/applications_controller.rb | 29 | ||||
-rw-r--r-- | app/models/clusters/concerns/application_core.rb | 6 | ||||
-rw-r--r-- | app/services/clusters/applications/base_helm_service.rb | 4 | ||||
-rw-r--r-- | app/services/clusters/applications/base_service.rb | 76 | ||||
-rw-r--r-- | app/services/clusters/applications/create_service.rb | 57 | ||||
-rw-r--r-- | app/services/clusters/applications/patch_service.rb | 26 | ||||
-rw-r--r-- | app/services/clusters/applications/update_service.rb | 34 | ||||
-rw-r--r-- | app/workers/all_queues.yml | 1 | ||||
-rw-r--r-- | app/workers/cluster_update_app_worker.rb | 13 |
9 files changed, 185 insertions, 61 deletions
diff --git a/app/controllers/clusters/applications_controller.rb b/app/controllers/clusters/applications_controller.rb index c4e7fc950f9..73c744efeba 100644 --- a/app/controllers/clusters/applications_controller.rb +++ b/app/controllers/clusters/applications_controller.rb @@ -3,26 +3,41 @@ class Clusters::ApplicationsController < Clusters::BaseController before_action :cluster before_action :authorize_create_cluster!, only: [:create] + before_action :authorize_update_cluster!, only: [:update] def create - Clusters::Applications::CreateService - .new(@cluster, current_user, create_cluster_application_params) - .execute(request) + request_handler do + Clusters::Applications::CreateService + .new(@cluster, current_user, cluster_application_params) + .execute(request) + end + end + + def update + request_handler do + Clusters::Applications::UpdateService + .new(@cluster, current_user, cluster_application_params) + .execute(request) + end + end + + private + + def request_handler + yield head :no_content - rescue Clusters::Applications::CreateService::InvalidApplicationError + rescue Clusters::Applications::BaseService::InvalidApplicationError render_404 rescue StandardError head :bad_request end - private - def cluster @cluster ||= clusterable.clusters.find(params[:id]) || render_404 end - def create_cluster_application_params + def cluster_application_params params.permit(:application, :hostname, :email) end end diff --git a/app/models/clusters/concerns/application_core.rb b/app/models/clusters/concerns/application_core.rb index 683b45331f6..cdb42117281 100644 --- a/app/models/clusters/concerns/application_core.rb +++ b/app/models/clusters/concerns/application_core.rb @@ -30,6 +30,12 @@ module Clusters # Override if you need extra data synchronized # from K8s after installation end + + def update_command + command = install_command + command.version = version + command + end end end end diff --git a/app/services/clusters/applications/base_helm_service.rb b/app/services/clusters/applications/base_helm_service.rb index 8a71730d5ec..c38b2656260 100644 --- a/app/services/clusters/applications/base_helm_service.rb +++ b/app/services/clusters/applications/base_helm_service.rb @@ -46,6 +46,10 @@ module Clusters @install_command ||= app.install_command end + def update_command + @update_command ||= app.update_command + end + def upgrade_command(new_values = "") app.upgrade_command(new_values) end diff --git a/app/services/clusters/applications/base_service.rb b/app/services/clusters/applications/base_service.rb new file mode 100644 index 00000000000..cbd1cf03ae1 --- /dev/null +++ b/app/services/clusters/applications/base_service.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +module Clusters + module Applications + class BaseService + InvalidApplicationError = Class.new(StandardError) + + attr_reader :cluster, :current_user, :params + + def initialize(cluster, user, params = {}) + @cluster = cluster + @current_user = user + @params = params.dup + end + + def execute(request) + instantiate_application.tap do |application| + if application.has_attribute?(:hostname) + application.hostname = params[:hostname] + end + + if application.has_attribute?(:email) + application.email = params[:email] + end + + if application.respond_to?(:oauth_application) + application.oauth_application = create_oauth_application(application, request) + end + + worker = worker_class(application) + + application.make_scheduled! + + worker.perform_async(application.name, application.id) + end + end + + protected + + def worker_class(application) + raise NotImplementedError + end + + def builders + raise NotImplementedError + end + + def project_builders + raise NotImplementedError + end + + def instantiate_application + builder.call(@cluster) || raise(InvalidApplicationError, "invalid application: #{application_name}") + end + + def builder + builders[application_name] || raise(InvalidApplicationError, "invalid application: #{application_name}") + end + + def application_name + params[:application] + end + + def create_oauth_application(application, request) + oauth_application_params = { + name: params[:application], + redirect_uri: application.callback_url, + scopes: 'api read_user openid', + owner: current_user + } + + ::Applications::CreateService.new(current_user, oauth_application_params).execute(request) + end + end + end +end diff --git a/app/services/clusters/applications/create_service.rb b/app/services/clusters/applications/create_service.rb index 12f8c849d41..bd7c31bb981 100644 --- a/app/services/clusters/applications/create_service.rb +++ b/app/services/clusters/applications/create_service.rb @@ -2,47 +2,11 @@ module Clusters module Applications - class CreateService - InvalidApplicationError = Class.new(StandardError) - - attr_reader :cluster, :current_user, :params - - def initialize(cluster, user, params = {}) - @cluster = cluster - @current_user = user - @params = params.dup - end - - def execute(request) - create_application.tap do |application| - if application.has_attribute?(:hostname) - application.hostname = params[:hostname] - end - - if application.has_attribute?(:email) - application.email = params[:email] - end - - if application.respond_to?(:oauth_application) - application.oauth_application = create_oauth_application(application, request) - end - - worker = application.updateable? ? ClusterUpgradeAppWorker : ClusterInstallAppWorker - - application.make_scheduled! - - worker.perform_async(application.name, application.id) - end - end - + class CreateService < Clusters::Applications::BaseService private - def create_application - builder.call(@cluster) - end - - def builder - builders[application_name] || raise(InvalidApplicationError, "invalid application: #{application_name}") + def worker_class(application) + application.updateable? ? ClusterUpgradeAppWorker : ClusterInstallAppWorker end def builders @@ -65,21 +29,6 @@ module Clusters "knative" => -> (cluster) { cluster.application_knative || cluster.build_application_knative } } end - - def application_name - params[:application] - end - - def create_oauth_application(application, request) - oauth_application_params = { - name: params[:application], - redirect_uri: application.callback_url, - scopes: 'api read_user openid', - owner: current_user - } - - ::Applications::CreateService.new(current_user, oauth_application_params).execute(request) - end end end end diff --git a/app/services/clusters/applications/patch_service.rb b/app/services/clusters/applications/patch_service.rb new file mode 100644 index 00000000000..67fc8fd9800 --- /dev/null +++ b/app/services/clusters/applications/patch_service.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Clusters + module Applications + class PatchService < BaseHelmService + def execute + return unless app.scheduled? + + begin + app.make_updating! + + helm_api.update(update_command) + + ClusterWaitForAppInstallationWorker.perform_in( + ClusterWaitForAppInstallationWorker::INTERVAL, app.name, app.id) + rescue Kubeclient::HttpError => e + log_error(e) + app.make_update_errored!("Kubernetes error: #{e.error_code}") + rescue StandardError => e + log_error(e) + app.make_update_errored!("Can't start update process.") + end + end + end + end +end diff --git a/app/services/clusters/applications/update_service.rb b/app/services/clusters/applications/update_service.rb new file mode 100644 index 00000000000..979d870cc94 --- /dev/null +++ b/app/services/clusters/applications/update_service.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Clusters + module Applications + class UpdateService < Clusters::Applications::BaseService + private + + def worker_class(application) + ClusterUpdateAppWorker + end + + def builders + { + "helm" => -> (cluster) { cluster.application_helm }, + "ingress" => -> (cluster) { cluster.application_ingress }, + "cert_manager" => -> (cluster) { cluster.application_cert_manager } + }.tap do |hash| + hash.merge!(project_builders) if cluster.project_type? + end + end + + # These applications will need extra configuration to enable them to work + # with groups of projects + def project_builders + { + "prometheus" => -> (cluster) { cluster.application_prometheus }, + "runner" => -> (cluster) { cluster.application_runner }, + "jupyter" => -> (cluster) { cluster.application_jupyter }, + "knative" => -> (cluster) { cluster.application_knative } + } + end + end + end +end diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index d86f654dd44..bc7db5669e1 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -23,6 +23,7 @@ - cronjob:prune_web_hook_logs - gcp_cluster:cluster_install_app +- gcp_cluster:cluster_update_app - gcp_cluster:cluster_upgrade_app - gcp_cluster:cluster_provision - gcp_cluster:cluster_wait_for_app_installation diff --git a/app/workers/cluster_update_app_worker.rb b/app/workers/cluster_update_app_worker.rb new file mode 100644 index 00000000000..bec422c34a9 --- /dev/null +++ b/app/workers/cluster_update_app_worker.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class ClusterUpdateAppWorker + include ApplicationWorker + include ClusterQueue + include ClusterApplications + + def perform(app_name, app_id) + find_application(app_name, app_id) do |app| + Clusters::Applications::PatchService.new(app).execute + end + end +end |