diff --git a/app/controllers/foreman_salt/concerns/hosts_controller_extensions.rb b/app/controllers/foreman_salt/concerns/hosts_controller_extensions.rb index e1166363..c44556ed 100644 --- a/app/controllers/foreman_salt/concerns/hosts_controller_extensions.rb +++ b/app/controllers/foreman_salt/concerns/hosts_controller_extensions.rb @@ -2,6 +2,8 @@ module ForemanSalt module Concerns module HostsControllerExtensions extend ActiveSupport::Concern + MULTIPLE_EDIT_ACTIONS = %w(select_multiple_salt_environment update_multiple_salt_environment + select_multiple_salt_master update_multiple_salt_master) module Overrides def process_hostgroup @@ -30,6 +32,41 @@ def load_vars_for_ajax included do prepend Overrides + define_action_permission MULTIPLE_EDIT_ACTIONS, :edit + end + + def select_multiple_salt_master + find_multiple + end + + def update_multiple_salt_master + find_multiple + update_multiple_proxy(_('Salt Master'), :salt_proxy=) + end + + def select_multiple_salt_environment + find_multiple + end + + def update_multiple_salt_environment + # simple validations + if params[:salt_environment].nil? || (id = params[:salt_environment][:id]).nil? + error _('No salt environment selected!') + redirect_to(select_multiple_salt_environment_hosts_path) + return + end + + find_multiple + ev = ForemanSalt::SaltEnvironment.find_by_id(id) + + # update the hosts + @hosts.each do |host| + host.salt_environment = ev + host.save(:validate => false) + end + + success _('Updated hosts: changed salt environment') + redirect_back_or_to hosts_path end end end diff --git a/app/helpers/concerns/foreman_salt/hosts_helper_extensions.rb b/app/helpers/concerns/foreman_salt/hosts_helper_extensions.rb index 7ae51e73..e3a8c399 100644 --- a/app/helpers/concerns/foreman_salt/hosts_helper_extensions.rb +++ b/app/helpers/concerns/foreman_salt/hosts_helper_extensions.rb @@ -21,6 +21,15 @@ def host_title_actions(host) super(host) end + def multiple_actions + actions = super + if authorized_for(:controller => :hosts, :action => :edit) + actions << [_('Change Salt Master'), select_multiple_salt_master_hosts_path] if SmartProxy.unscoped.authorized.with_features("Salt") + actions << [_('Change Salt Environment'), select_multiple_salt_environment_hosts_path] if SmartProxy.unscoped.authorized.with_features("Salt") + end + actions + end + def overview_fields(host) fields = super(host) diff --git a/app/views/hosts/select_multiple_salt_environment.html.erb b/app/views/hosts/select_multiple_salt_environment.html.erb new file mode 100644 index 00000000..5fc0fd8a --- /dev/null +++ b/app/views/hosts/select_multiple_salt_environment.html.erb @@ -0,0 +1,8 @@ +<%= render 'selected_hosts', :hosts => @hosts %> + +<%= form_for :salt_environment, :url => update_multiple_salt_environment_hosts_path(:host_ids => params[:host_ids]) do |f| %> + <%= selectable_f f, :id, [[_("Select salt environment"), "None"]] + + [[_("*Clear environment*"), ""]] + + ForemanSalt::SaltEnvironment.all.map{|e| [e.name, e.id]},{}, + :label => _("Salt Environment"), :onchange => "toggle_multiple_ok_button(this)" %> +<% end %> diff --git a/app/views/hosts/select_multiple_salt_master.html.erb b/app/views/hosts/select_multiple_salt_master.html.erb new file mode 100644 index 00000000..2a55cb8a --- /dev/null +++ b/app/views/hosts/select_multiple_salt_master.html.erb @@ -0,0 +1,5 @@ +<%= render 'selected_hosts', :hosts => @hosts %> + +<%= form_for :proxy, :url => update_multiple_salt_master_hosts_path(:host_ids => params[:host_ids]) do |f| %> + <%= multiple_proxy_select(f, 'Salt') %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index 99f0bbad..45473bb9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -53,6 +53,17 @@ end end + constraints(:id => /[^\/]+/) do + resources :hosts do + collection do + post 'select_multiple_salt_master' + post 'update_multiple_salt_master' + post 'select_multiple_salt_environment' + post 'update_multiple_salt_environment' + end + end + end + constraints(:smart_proxy_id => /[^\/]+/) do resources :smart_proxies, :except => [:show] do constraints(:id => /[^\/]+/) do diff --git a/lib/foreman_salt/plugin.rb b/lib/foreman_salt/plugin.rb index c565ad9c..3cc0ca12 100644 --- a/lib/foreman_salt/plugin.rb +++ b/lib/foreman_salt/plugin.rb @@ -66,7 +66,9 @@ permission :edit_hosts, { :'foreman_salt/api/v2/salt_minions' => [:update], - :'foreman_salt/minions' => [:salt_environment_selected] }, + :'foreman_salt/minions' => [:salt_environment_selected], + :hosts => [:select_multiple_salt_master, :update_multiple_salt_master, + :select_multiple_salt_environment, :update_multiple_salt_environment] }, :resource_type => 'Host' permission :view_hosts, diff --git a/test/functional/hosts_controller_test.rb b/test/functional/hosts_controller_test.rb new file mode 100644 index 00000000..b7a126df --- /dev/null +++ b/test/functional/hosts_controller_test.rb @@ -0,0 +1,122 @@ +require 'test_plugin_helper' + +module ForemanSalt + class HostsControllerExtensionsTest < ActionController::TestCase + tests ::HostsController + + describe "setting salt master proxy on multiple hosts" do + before do + setup_user "edit" + as_admin do + @hosts = FactoryBot.create_list(:host, 2) + @proxy = FactoryBot.create(:smart_proxy, :with_salt_feature) + end + end + + test 'user without edit permission should not be able to change salt master' do + @request.env['HTTP_REFERER'] = hosts_path + + params = { :host_ids => @hosts.map(&:id), + :proxy => { :proxy_id => '' } } + + post :update_multiple_salt_master, params: params, + session: set_session_user.merge(:user => users(:one).id) + assert_response :forbidden + end + + test "should change the salt master proxy" do + @request.env['HTTP_REFERER'] = hosts_path + + params = { :host_ids => @hosts.map(&:id), + :proxy => { :proxy_id => @proxy.id } } + + post :update_multiple_salt_master, params: params, + session: set_session_user.merge(:user => users(:admin).id) + + assert_empty flash[:error] + + @hosts.each do |host| + as_admin do + assert_equal @proxy, host.reload.salt_proxy + end + end + end + + test "should clear the salt master proxy of multiple hosts" do + @request.env['HTTP_REFERER'] = hosts_path + + params = { :host_ids => @hosts.map(&:id), + :proxy => { :proxy_id => '' } } + + post :update_multiple_salt_master, params: params, + session: set_session_user.merge(:user => users(:admin).id) + + assert_empty flash[:error] + + @hosts.each do |host| + as_admin do + assert_nil host.reload.salt_proxy + end + end + end + end + + describe "setting salt environment on multiple hosts" do + before do + setup_user "edit" + as_admin do + @hosts = FactoryBot.create_list(:host, 2) + @proxy = FactoryBot.create(:smart_proxy, :with_salt_feature) + @salt_environment = FactoryBot.create :salt_environment + end + end + + test 'user without edit permission should not be able to change salt environment' do + @request.env['HTTP_REFERER'] = hosts_path + + params = { :host_ids => @hosts.map(&:id), + :salt_environment => { :id => @salt_environment.id } } + + post :update_multiple_salt_environment, params: params, + session: set_session_user.merge(:user => users(:one).id) + assert_response :forbidden + end + + test "should change the salt environment" do + @request.env['HTTP_REFERER'] = hosts_path + + params = { :host_ids => @hosts.map(&:id), + :salt_environment => { :id => @salt_environment.id } } + + post :update_multiple_salt_environment, params: params, + session: set_session_user.merge(:user => users(:admin).id) + + assert_empty flash[:error] + + @hosts.each do |host| + as_admin do + assert_equal @salt_environment, host.reload.salt_environment + end + end + end + + test "should clear the salt environment of multiple hosts" do + @request.env['HTTP_REFERER'] = hosts_path + + params = { :host_ids => @hosts.map(&:id), + :salt_environment => { :id => '' } } + + post :update_multiple_salt_environment, params: params, + session: set_session_user.merge(:user => users(:admin).id) + + assert_empty flash[:error] + + @hosts.each do |host| + as_admin do + assert_nil host.reload.salt_environment + end + end + end + end + end +end diff --git a/test/integration/hosts_js_test.rb b/test/integration/hosts_js_test.rb new file mode 100644 index 00000000..9f11d133 --- /dev/null +++ b/test/integration/hosts_js_test.rb @@ -0,0 +1,82 @@ +require 'test_plugin_helper' +require 'integration_test_helper' + +module ForemanSalt + class HostJSTest < IntegrationTestWithJavascript + def index_modal + page.find('#confirmation-modal') + end + + def multiple_actions_div + page.find('#submit_multiple') + end + + setup do + as_admin do + proxy = FactoryBot.create(:smart_proxy, :with_salt_feature) + salt_environment = FactoryBot.create(:salt_environment) + @host = FactoryBot.create(:host, :salt_proxy => proxy, :salt_environment => salt_environment) + end + end + + describe "hosts index salt multiple actions" do + test 'change salt master action' do + visit hosts_path + page.find('#check_all').trigger('click') + + # Ensure and wait for all hosts to be checked, and that no unchecked hosts remain + assert page.has_no_selector?('input.host_select_boxes:not(:checked)') + + # Dropdown visible? + assert multiple_actions_div.find('.dropdown-toggle').visible? + multiple_actions_div.find('.dropdown-toggle').click + assert multiple_actions_div.find('ul').visible? + + # Hosts are added to cookie + host_ids_on_cookie = JSON.parse(CGI.unescape(page.driver.cookies['_ForemanSelectedhosts'].value)) + assert(host_ids_on_cookie.include?(@host.id)) + + within('#submit_multiple') do + click_on('Change Salt Master') + end + + assert index_modal.visible?, "Modal window was shown" + page.find('#proxy_proxy_id').find("option[value='#{@host.salt_proxy.id}']").select_option + + # remove hosts cookie on submit + index_modal.find('.btn-primary').click + assert_current_path hosts_path + assert_empty(page.driver.cookies['_ForemanSelectedhosts']) + end + + test 'change salt environment action' do + visit hosts_path + page.find('#check_all').trigger('click') + + # Ensure and wait for all hosts to be checked, and that no unchecked hosts remain + assert page.has_no_selector?('input.host_select_boxes:not(:checked)') + + # Dropdown visible? + assert multiple_actions_div.find('.dropdown-toggle').visible? + multiple_actions_div.find('.dropdown-toggle').click + assert multiple_actions_div.find('ul').visible? + + # Hosts are added to cookie + host_ids_on_cookie = JSON.parse(CGI.unescape(page.driver.cookies['_ForemanSelectedhosts'].value)) + assert(host_ids_on_cookie.include?(@host.id)) + + within('#submit_multiple') do + click_on('Change Salt Environment') + end + + assert index_modal.visible?, "Modal window was shown" + page.find('#salt_environment_id').find("option[value='#{@host.salt_environment.id}']").select_option + + # remove hosts cookie on submit + index_modal.find('.btn-primary').click + assert_current_path hosts_path + assert_empty(page.driver.cookies['_ForemanSelectedhosts']) + end + end + end +end