-
Notifications
You must be signed in to change notification settings - Fork 993
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes #36867 - Add host delete & create
Add bulk modal with bulk params add register/create buttons; fix links address UX comments Remove icon from delete action in the toolbar’s kebab In the delete modal as a primary button use just “Delete” (not delete host) To the top part: Add a kebab with legacy UI button Ensure the loading screen doesn't say 'No Results' support foreman_remote_execution slot Refs #36867 - move action to new controller move bulk hosts extension test to Foreman
- Loading branch information
1 parent
8dda6a6
commit f03e699
Showing
23 changed files
with
603 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
module Api | ||
module V2 | ||
class HostsBulkActionsController < V2::BaseController | ||
include Api::Version2 | ||
include Api::V2::BulkHostsExtension | ||
|
||
before_action :find_deletable_hosts, :only => [:bulk_destroy] | ||
|
||
def_param_group :bulk_host_ids do | ||
param :organization_id, :number, :required => true, :desc => N_("ID of the organization") | ||
param :included, Hash, :desc => N_("Hosts to include in the action"), :required => true, :action_aware => true do | ||
param :search, String, :required => false, :desc => N_("Search string describing which hosts to perform the action on") | ||
param :ids, Array, :required => false, :desc => N_("List of host ids to perform the action on") | ||
end | ||
param :excluded, Hash, :desc => N_("Hosts to explicitly exclude in the action."\ | ||
" All other hosts will be included in the action,"\ | ||
" unless an included parameter is passed as well."), :required => true, :action_aware => true do | ||
param :ids, Array, :required => false, :desc => N_("List of host ids to exclude and not perform the action on") | ||
end | ||
end | ||
|
||
api :DELETE, "/hosts/bulk/", N_("Delete multiple hosts") | ||
param_group :bulk_host_ids | ||
def bulk_destroy | ||
process_response @hosts.destroy_all | ||
end | ||
|
||
private | ||
|
||
def find_deletable_hosts | ||
find_bulk_hosts(:destroy_hosts, params) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
module Api::V2::BulkHostsExtension | ||
extend ActiveSupport::Concern | ||
|
||
def bulk_hosts_relation(permission, org) | ||
relation = ::Host::Managed.authorized(permission) | ||
relation = relation.where(organization: org) if org | ||
relation | ||
end | ||
|
||
def find_bulk_hosts(permission, bulk_params, restrict_to = nil) | ||
# works on a structure of param_group bulk_params and transforms it into a list of systems | ||
bulk_params[:included] ||= {} | ||
bulk_params[:excluded] ||= {} | ||
search_param = bulk_params[:included][:search] || bulk_params[:search] | ||
|
||
if !params[:install_all] && bulk_params[:included][:ids].blank? && search_param.nil? | ||
render_error :custom_error, :status => :bad_request, :locals => { :message => _('No hosts have been specified') } | ||
end | ||
|
||
find_organization | ||
@hosts = bulk_hosts_relation(permission, @organization) | ||
|
||
if bulk_params[:included][:ids].present? | ||
@hosts = @hosts.where(id: bulk_params[:included][:ids]) | ||
end | ||
|
||
if search_param.present? | ||
@hosts = @hosts.search_for(search_param) | ||
end | ||
|
||
@hosts = restrict_to.call(@hosts) if restrict_to | ||
|
||
if bulk_params[:excluded][:ids].present? | ||
@hosts = @hosts.where.not(id: bulk_params[:excluded][:ids]) | ||
end | ||
if @hosts.empty? | ||
render_error :custom_error, :status => :forbidden, :locals => { :message => _('No hosts matched search, or action unauthorized for selected hosts.') } | ||
end | ||
@hosts | ||
end | ||
|
||
def find_organization | ||
@organization ||= Organization.find_by_id(params[:organization_id]) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
require 'test_helper' | ||
|
||
class BulkHostsExtensionTestController < ::Api::BaseController | ||
include Api::Version2 | ||
include ::Api::V2::BulkHostsExtension | ||
|
||
def initialize(params = {}) | ||
@params = params | ||
end | ||
|
||
attr_reader :params | ||
end | ||
|
||
class BulkHostsExtensionTest < ActiveSupport::TestCase | ||
def models | ||
as_admin do | ||
@organization = FactoryBot.create(:organization) | ||
@host1 = FactoryBot.create(:host, :managed, :organization => @organization) | ||
@host2 = FactoryBot.create(:host, :organization => @organization) | ||
@host3 = FactoryBot.create(:host, :organization => @organization) | ||
@host4 = FactoryBot.create(:host, :organization => @organization) | ||
@host5 = FactoryBot.create(:host, :organization => @organization) | ||
@host6 = FactoryBot.create(:host, :organization => @organization) | ||
@host_ids = [@host1, @host2, @host3, @host4, @host5, @host6].map(&:id) | ||
end | ||
end | ||
|
||
def permissions | ||
@edit = :edit_hosts | ||
end | ||
|
||
def setup | ||
# set_user | ||
models | ||
permissions | ||
@controller = BulkHostsExtensionTestController.new(organization_id: @organization.id) | ||
end | ||
|
||
def test_search | ||
bulk_params = { | ||
:included => { | ||
:search => "name = #{@host1.name}", | ||
}, | ||
} | ||
result = @controller.find_bulk_hosts(@edit, bulk_params) | ||
|
||
assert_equal result, [@host1] | ||
end | ||
|
||
def test_search_restrict | ||
bulk_params = { | ||
:included => { | ||
:search => "name ~ host", | ||
}, | ||
} | ||
restrict = ->(hosts) { hosts.where("id != #{@host2.id}") } | ||
result = @controller.find_bulk_hosts(@edit, bulk_params, restrict) | ||
|
||
assert_includes result, @host1 | ||
refute_includes result, @host2 | ||
assert_includes result, @host3 | ||
end | ||
|
||
def test_search_exclude | ||
bulk_params = { | ||
:included => { | ||
:search => "name ~ host", | ||
}, | ||
:excluded => { | ||
:ids => [@host1.id], | ||
}, | ||
} | ||
result = @controller.find_bulk_hosts(@edit, bulk_params) | ||
|
||
refute_includes result, @host1 | ||
assert_includes result, @host2 | ||
assert_includes result, @host3 | ||
end | ||
|
||
def test_no_hosts_specified | ||
bulk_params = { | ||
:included => {}, | ||
} | ||
@controller.expects(:render_error).with(:custom_error, :status => :bad_request, :locals => { :message => _('No hosts have been specified') }) | ||
@controller.find_bulk_hosts(@edit, bulk_params) | ||
end | ||
|
||
def test_ids | ||
bulk_params = { | ||
:included => { | ||
:ids => [@host1.id, @host2.id], | ||
}, | ||
} | ||
result = @controller.find_bulk_hosts(@edit, bulk_params) | ||
|
||
assert_equal [@host1, @host2].sort, result.sort | ||
end | ||
|
||
def test_ids_excluded | ||
bulk_params = { | ||
:included => { | ||
:ids => [@host1.id, @host2.id], | ||
}, | ||
:excluded => { | ||
:ids => [@host2.id], | ||
}, | ||
} | ||
result = @controller.find_bulk_hosts(@edit, bulk_params) | ||
|
||
assert_equal result, [@host1] | ||
end | ||
|
||
def test_ids_restricted | ||
bulk_params = { | ||
:included => { | ||
:ids => [@host1.id, @host2.id], | ||
}, | ||
} | ||
restrict = ->(hosts) { hosts.where("id != #{@host2.id}") } | ||
result = @controller.find_bulk_hosts(@edit, bulk_params, restrict) | ||
|
||
assert_equal result, [@host1] | ||
end | ||
|
||
def test_included_ids_with_nil_scoped_search | ||
bulk_params = { | ||
:included => { | ||
:ids => [@host1.id, @host2.id], | ||
:search => nil, | ||
}, | ||
} | ||
|
||
result = @controller.find_bulk_hosts(@edit, bulk_params) | ||
|
||
assert_equal [@host1, @host2].sort, result.sort | ||
end | ||
|
||
def test_ids_with_scoped_search | ||
bulk_params = { | ||
:included => { | ||
:ids => [@host1.id, @host2.id], | ||
:search => "name != #{@host2.name}", | ||
}, | ||
} | ||
|
||
result = @controller.find_bulk_hosts(@edit, bulk_params) | ||
|
||
assert_equal result, [@host1] | ||
end | ||
|
||
def test_forbidden | ||
bulk_params = { | ||
:included => { | ||
:ids => [@host1.id], | ||
}, | ||
:excluded => { | ||
:ids => [@host1.id], | ||
}, | ||
} | ||
@controller.expects(:render_error).with(:custom_error, :status => :forbidden, :locals => { :message => _('No hosts matched search, or action unauthorized for selected hosts.') }) | ||
@controller.find_bulk_hosts(@edit, bulk_params) | ||
end | ||
|
||
def test_empty_params | ||
@controller.expects(:render_error).with(:custom_error, :status => :bad_request, :locals => { :message => _('No hosts have been specified') }) | ||
@controller.find_bulk_hosts(@edit, {}) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.