From 639a00be77c595c65c3526d443ef01269c245c96 Mon Sep 17 00:00:00 2001 From: Partha Aji Date: Wed, 1 May 2024 17:35:55 -0400 Subject: [PATCH] Refs #37395 - Made the hosts controller handle both json and html --- .../api/v2/hosts_bulk_actions_controller.rb | 73 ------------------- app/controllers/hosts_controller.rb | 58 +++++++++++++-- app/registries/foreman/access_permissions.rb | 1 - config/routes/api/v2.rb | 1 - .../buildHosts/BulkBuildHostModal.js | 15 ++-- .../BulkActions/buildHosts/actions.js | 14 ++-- .../BulkActions/buildHosts/index.js | 5 +- 7 files changed, 71 insertions(+), 96 deletions(-) diff --git a/app/controllers/api/v2/hosts_bulk_actions_controller.rb b/app/controllers/api/v2/hosts_bulk_actions_controller.rb index 60cb9ffb8f09..0b548e8b4a76 100644 --- a/app/controllers/api/v2/hosts_bulk_actions_controller.rb +++ b/app/controllers/api/v2/hosts_bulk_actions_controller.rb @@ -5,7 +5,6 @@ class HostsBulkActionsController < V2::BaseController include Api::V2::BulkHostsExtension before_action :find_deletable_hosts, :only => [:bulk_destroy] - before_action :find_editable_hosts, :only => [:build] def_param_group :bulk_host_ids do param :organization_id, :number, :required => true, :desc => N_("ID of the organization") @@ -26,83 +25,11 @@ def bulk_destroy process_response @hosts.destroy_all end - api :POST, "/hosts/bulk/build", N_("Build") - param_group :bulk_host_ids - param :reboot,:bool, N_("Reboot after build") - param :rebuild_configuration, :bool, N_("Rebuild configuration only") - def build - reboot = Foreman::Cast.to_bool(params[:reboot]) - rebuild_configuration = Foreman::Cast.to_bool(params[:rebuild_configuration]) - if rebuild_configuration - rebuild_config - else - missed_hosts = @hosts.select do |host| - success = true - begin - host.built(false) if host.build? && host.token_expired? - host.setBuild - host.power.reset if host.supports_power_and_running? && reboot - rescue => error - message = _('Failed to redeploy %s.') % host - Foreman::Logging.exception(message, error) - success = false - end - !success - end - - if missed_hosts.empty? - process_response(true, { :message => _("Built %{host_count} %{hosts}") % { :host_count => @hosts.count, :hosts => 'host'.pluralize(@hosts.count) }}) - else - process_response(false, { :message => _("The following hosts failed the build operation: %s") % missed_hosts.map(&:name).to_sentence}) - end - end - end - - protected - def action_permission - case params[:action] - when 'build' - 'edit' - else - super - end - end - private def find_deletable_hosts find_bulk_hosts(:destroy_hosts, params) end - - def find_editable_hosts - find_bulk_hosts(:edit_hosts, params) - end - - def rebuild_config - all_fails = {} - @hosts.each do |host| - result = host.recreate_config - result.each_pair do |k, v| - all_fails[k] ||= [] - all_fails[k] << host.name unless v - end - end - - message = '' - all_fails.each_pair do |key, values| - unless values.empty? - message << ((n_("%{config_type} rebuild failed for host: %{host_names}.", - "%{config_type} rebuild failed for hosts: %{host_names}.", - values.count) % {:config_type => _(key), :host_names => values.to_sentence})) + " " - end - end - - if message.blank? - process_response(true, { :message => _("Rebuilt configuration for %{host_count} %{hosts}") % { :host_count => @hosts.count, :hosts => 'host'.pluralize(@hosts.count) }}) - else - process_response(false, { :message => message}) - end - end end end end diff --git a/app/controllers/hosts_controller.rb b/app/controllers/hosts_controller.rb index b5aeea614bb3..e58fc3058281 100644 --- a/app/controllers/hosts_controller.rb +++ b/app/controllers/hosts_controller.rb @@ -10,6 +10,7 @@ class HostsController < ApplicationController include Foreman::Controller::Puppet::HostsControllerExtensions include Foreman::Controller::CsvResponder include Foreman::Controller::ConsoleCommon + include Api::V2::BulkHostsExtension SEARCHABLE_ACTIONS = %w[index active errors out_of_sync pending disabled] AJAX_REQUESTS = %w{compute_resource_selected current_parameters process_hostgroup process_taxonomy review_before_build scheduler_hint_selected interfaces} @@ -512,15 +513,32 @@ def submit_rebuild_config end if message.blank? - success _('Configuration successfully rebuilt') + respond_to do |format| + format.html do + process_success :success_msg => _('Configuration successfully rebuilt') + redirect_to(helpers.current_hosts_path) + end + format.json do + render :json => { :success_msg => _('Configuration successfully rebuilt') } + end + end + success else - error message + respond_to do |format| + format.html do + process_response(false, {:message => message}) + redirect_to(helpers.current_hosts_path) + end + format.json do + render :json => { :error_msg => message } + end + end end - redirect_to helpers.current_hosts_path end + def submit_multiple_build - reboot = params[:host][:build] == '1' || false + reboot = Foreman::Cast.to_bool(params[:host][:build]) missed_hosts = @hosts.select do |host| success = true @@ -533,20 +551,41 @@ def submit_multiple_build message = _('Failed to redeploy %s.') % host Foreman::Logging.exception(message, error) success = false + message = _('Failed to reboot %s.') % @host + warning(message) + Foreman::Logging.exception(message, error) end !success end if missed_hosts.empty? if reboot - success _("The selected hosts were enabled for reboot and rebuild") + message = _("The selected hosts were enabled for reboot and rebuild") else - success _("The selected hosts will execute a build operation on next reboot") + message = _("The selected hosts will execute a build operation on next reboot") + end + + respond_to do |format| + format.html do + process_success :success_msg => message + redirect_to(helpers.current_hosts_path) + end + format.json do + render :json => { :success_msg => message } + end end else - error _("The following hosts failed the build operation: %s") % missed_hosts.map(&:name).to_sentence + message = _("The following hosts failed the build operation: %s") % missed_hosts.map(&:name).to_sentence + respond_to do |format| + format.html do + process_response(false, {:message => message}) + redirect_to(helpers.current_hosts_path) + end + format.json do + render :json => { :error_msg => message } + end + end end - redirect_to(helpers.current_hosts_path) end def submit_multiple_destroy @@ -770,6 +809,9 @@ def multiple_with_filter? end def find_multiple + if params.key?(:bulk_params) + return find_bulk_hosts(:edit_hosts, params[:bulk_params]) + end # Lets search by name or id and make sure one of them exists first if params.key?(:host_names) || params.key?(:host_ids) || multiple_with_filter? @hosts = resource_base.search_for(params[:search]) if multiple_with_filter? diff --git a/app/registries/foreman/access_permissions.rb b/app/registries/foreman/access_permissions.rb index f3d4ef2e263b..b20008811b57 100644 --- a/app/registries/foreman/access_permissions.rb +++ b/app/registries/foreman/access_permissions.rb @@ -273,7 +273,6 @@ :"api/v2/hosts" => [:update, :disassociate, :forget_status], :"api/v2/interfaces" => [:create, :update, :destroy], :"api/v2/compute_resources" => [:associate], - :"api/v2/hosts_bulk_actions" => [:build], } map.permission :destroy_hosts, {:hosts => [:destroy, :multiple_actions, :reset_multiple, :multiple_destroy, :submit_multiple_destroy], :"api/v2/hosts" => [:destroy], diff --git a/config/routes/api/v2.rb b/config/routes/api/v2.rb index 08fad8464755..8a021a66969b 100644 --- a/config/routes/api/v2.rb +++ b/config/routes/api/v2.rb @@ -4,7 +4,6 @@ # new v2 routes that point to v2 scope "(:apiv)", :module => :v2, :defaults => {:apiv => 'v2'}, :apiv => /v2/, :constraints => ApiConstraints.new(:version => 2, :default => true) do match 'hosts/bulk', :to => 'hosts_bulk_actions#bulk_destroy', :via => [:delete] - match 'hosts/bulk/build', :to => 'hosts_bulk_actions#build', :via => [:put] resources :architectures, :except => [:new, :edit] do constraints(:id => /[^\/]+/) do diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/buildHosts/BulkBuildHostModal.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/buildHosts/BulkBuildHostModal.js index 0c6b166f5af1..e1a0b584ec67 100644 --- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/buildHosts/BulkBuildHostModal.js +++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/buildHosts/BulkBuildHostModal.js @@ -21,6 +21,7 @@ const BulkBuildHostModal = ({ isOpen, closeModal, selectedCount, + orgId, fetchBulkParams, }) => { const dispatch = useDispatch(); @@ -39,15 +40,18 @@ const BulkBuildHostModal = ({ const handleSave = () => { const requestBody = { - included: { - search: fetchBulkParams(), + bulk_params: { + organization_id: orgId, + included: { + search: fetchBulkParams(), + } }, - reboot: rebootChecked, - "rebuild_configuration": !buildRadioChecked, + host: {build: rebootChecked}, + rebuild_configuration: !buildRadioChecked, }; dispatch(bulkBuildHosts( - requestBody, fetchBulkParams(), + requestBody, handleModalClose, handleModalClose, )); }; @@ -149,6 +153,7 @@ BulkBuildHostModal.propTypes = { closeModal: PropTypes.func, selectedCount: PropTypes.number.isRequired, fetchBulkParams: PropTypes.func.isRequired, + orgId: PropTypes.number.isRequired, }; BulkBuildHostModal.defaultProps = { diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/buildHosts/actions.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/buildHosts/actions.js index c1255b96ea1d..70f9b4b6ac9f 100644 --- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/buildHosts/actions.js +++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/buildHosts/actions.js @@ -4,17 +4,19 @@ import { foremanUrl } from '../../../../common/helpers'; export const bulkBuildHosts = ( params, - bulkParams, handleSuccess, handleError ) => { const errorToast = ({ message }) => message; - const url = foremanUrl(`/api/v2/hosts/bulk/build`); - return APIActions.put({ - type: API_OPERATIONS.PUT, + let url = '/hosts/submit_multiple_build'; + if (params['rebuild_configuration']) { + url = '/hosts/submit_rebuild_config'; + }; + + return APIActions.post({ + type: API_OPERATIONS.POST, key: 'HOST_BUILD_KEY', - url, - ...bulkParams, + url: foremanUrl(url), successToast: () => __('Built hosts.'), handleSuccess: response => { if (handleSuccess) handleSuccess(response); diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/buildHosts/index.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/buildHosts/index.js index 3e45d9873c38..8863c655ed1e 100644 --- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/buildHosts/index.js +++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/buildHosts/index.js @@ -1,13 +1,13 @@ import React, { useContext } from 'react'; import { ForemanActionsBarContext } from '../../../../components/HostDetails/ActionsBar'; import { useForemanModal } from '../../../../components/ForemanModal/ForemanModalHooks'; - +import { useForemanOrganization } from '../../../../Root/Context/ForemanContext'; import BulkBuildHostModal from './BulkBuildHostModal'; const BulkBuildHostModalScene = () => { const { selectedCount, fetchBulkParams } = useContext(ForemanActionsBarContext); const { modalOpen, setModalClosed } = useForemanModal({ id: 'bulk-build-hosts-modal' }); - + const org = useForemanOrganization(); return ( { fetchBulkParams={fetchBulkParams} isOpen={modalOpen} closeModal={setModalClosed} + orgId={org?.id} /> ); };