diff --git a/app/controllers/api/v2/hosts_bulk_actions_controller.rb b/app/controllers/api/v2/hosts_bulk_actions_controller.rb
index bed35b6f1c..0c7bce1830 100644
--- a/app/controllers/api/v2/hosts_bulk_actions_controller.rb
+++ b/app/controllers/api/v2/hosts_bulk_actions_controller.rb
@@ -9,7 +9,6 @@ class HostsBulkActionsController < V2::BaseController
before_action :validate_power_action, :only => [:change_power_state]
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")
diff --git a/app/controllers/concerns/api/v2/bulk_hosts_extension.rb b/app/controllers/concerns/api/v2/bulk_hosts_extension.rb
index b6d720964d..49e53b2b77 100644
--- a/app/controllers/concerns/api/v2/bulk_hosts_extension.rb
+++ b/app/controllers/concerns/api/v2/bulk_hosts_extension.rb
@@ -1,9 +1,10 @@
module Api::V2::BulkHostsExtension
extend ActiveSupport::Concern
- def bulk_hosts_relation(permission, org)
+ def bulk_hosts_relation(permission, org, location)
relation = ::Host::Managed.authorized(permission)
relation = relation.where(organization: org) if org
+ relation = relation.where(location: location) if location
relation
end
@@ -18,7 +19,8 @@ def find_bulk_hosts(permission, bulk_params, restrict_to = nil)
end
find_organization
- @hosts = bulk_hosts_relation(permission, @organization)
+ find_location
+ @hosts = bulk_hosts_relation(permission, @organization, @location)
if bulk_params[:included][:ids].present?
@hosts = @hosts.where(id: bulk_params[:included][:ids])
@@ -42,4 +44,8 @@ def find_bulk_hosts(permission, bulk_params, restrict_to = nil)
def find_organization
@organization ||= Organization.find_by_id(params[:organization_id])
end
+
+ def find_location
+ @location ||= Location.find_by_id(params[:location_id])
+ end
end
diff --git a/test/controllers/api/v2/hosts_bulk_actions_controller_test.rb b/test/controllers/api/v2/hosts_bulk_actions_controller_test.rb
index 0312d16308..f03af11fd5 100644
--- a/test/controllers/api/v2/hosts_bulk_actions_controller_test.rb
+++ b/test/controllers/api/v2/hosts_bulk_actions_controller_test.rb
@@ -17,6 +17,7 @@ def setup
def valid_bulk_params(host_ids = @host_ids)
{
:organization_id => @organization.id,
+ :location_id => @location.id,
:included => {
:ids => host_ids,
},
@@ -107,6 +108,33 @@ def valid_power_params(host_ids = @host_ids, action = 'start')
end
end
+ test "should scope searched hosts by organization and location" do
+ other_location = FactoryBot.create(:location)
+ other_host = FactoryBot.create(:host, :managed, :organization => @organization, :location => other_location)
+
+ put :change_owner, params: {
+ :organization_id => @organization.id,
+ :location_id => @location.id,
+ :included => {
+ :search => 'name ~ *',
+ },
+ :excluded => {
+ :ids => [],
+ },
+ :owner_id => @user.id_and_type,
+ }
+
+ assert_response :success
+
+ [@host1, @host2, @host3].each do |host|
+ host.reload
+ assert_equal @user.id_and_type, host.is_owned_by
+ end
+
+ other_host.reload
+ refute_equal @user.id_and_type, other_host.is_owned_by
+ end
+
context "change_power_state" do
test "successfully changes power state for all hosts" do
Host.any_instance.stubs(:supports_power?).returns(true)
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/__tests__/bulkDelete.test.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/__tests__/bulkDelete.test.js
index 5c76648968..f132aaffae 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/__tests__/bulkDelete.test.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/__tests__/bulkDelete.test.js
@@ -37,12 +37,16 @@ describe('bulkDeleteHosts', () => {
});
const bulkParams = 'id ^ (1,2,3)';
+ const organizationId = 1;
+ const locationId = 2;
const selectedCount = 3;
const destroyVmOnHostDelete = true;
it('dispatches openConfirmModal with correct parameters', () => {
bulkDeleteHosts({
bulkParams,
+ organizationId,
+ locationId,
selectedCount,
destroyVmOnHostDelete,
})(dispatch);
@@ -61,6 +65,8 @@ describe('bulkDeleteHosts', () => {
it('calls visit with /new/hosts when onDeleteSuccess is not provided', () => {
bulkDeleteHosts({
bulkParams,
+ organizationId,
+ locationId,
selectedCount,
destroyVmOnHostDelete,
})(dispatch);
@@ -70,8 +76,16 @@ describe('bulkDeleteHosts', () => {
expect(APIActions.delete).toHaveBeenCalledTimes(1);
const deleteParams = APIActions.delete.mock.calls[0][0];
-
- expect(deleteParams.url).toBe(`/api/v2/hosts/bulk?search=${bulkParams}`);
+ const requestUrl = new URL(deleteParams.url, 'https://example.test');
+
+ expect(requestUrl.pathname).toBe('/api/v2/hosts/bulk');
+ expect(requestUrl.searchParams.get('search')).toBe(bulkParams);
+ expect(requestUrl.searchParams.get('organization_id')).toBe(
+ String(organizationId)
+ );
+ expect(requestUrl.searchParams.get('location_id')).toBe(
+ String(locationId)
+ );
expect(deleteParams.key).toBe('BULK-HOSTS-DELETE');
expect(typeof deleteParams.successToast).toBe('function');
expect(typeof deleteParams.errorToast).toBe('function');
@@ -86,6 +100,8 @@ describe('bulkDeleteHosts', () => {
bulkDeleteHosts({
bulkParams,
+ organizationId,
+ locationId,
selectedCount,
destroyVmOnHostDelete,
onDeleteSuccess,
@@ -106,6 +122,8 @@ describe('bulkDeleteHosts', () => {
it('returns formatted success message with host count', () => {
bulkDeleteHosts({
bulkParams,
+ organizationId,
+ locationId,
selectedCount,
destroyVmOnHostDelete,
})(dispatch);
@@ -124,6 +142,8 @@ describe('bulkDeleteHosts', () => {
it('returns error message from response', () => {
bulkDeleteHosts({
bulkParams,
+ organizationId,
+ locationId,
selectedCount,
destroyVmOnHostDelete,
})(dispatch);
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/assignTaxonomy/BulkAssignTaxonomyModal.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/assignTaxonomy/BulkAssignTaxonomyModal.js
index 5bc8273709..3ae3450866 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/assignTaxonomy/BulkAssignTaxonomyModal.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/assignTaxonomy/BulkAssignTaxonomyModal.js
@@ -38,6 +38,7 @@ import {
API_REQUEST_KEY,
} from '../../../../routes/Hosts/constants';
import TaxonomySelect from './TaxonomySelect';
+import { buildBulkRequestBody } from '../helpers';
export const BulkAssignOrganizationModal = props => (
@@ -52,6 +53,8 @@ const BulkAssignTaxonomyModal = ({
selectAllHostsMode,
selectedCount,
fetchBulkParams,
+ organizationId,
+ locationId,
modalType,
}) => {
const org = modalType === MODAL_TYPES.ORGANIZATION;
@@ -136,13 +139,13 @@ const BulkAssignTaxonomyModal = ({
};
const handleSave = () => {
- const requestBody = {
- included: {
- search: fetchBulkParams(),
- },
+ const requestBody = buildBulkRequestBody({
+ fetchBulkParams,
+ organizationId,
+ locationId,
id: taxId,
mismatch_setting: fixRadioChecked,
- };
+ });
org
? dispatch(
@@ -243,10 +246,14 @@ BulkAssignTaxonomyModal.propTypes = {
selectedCount: PropTypes.number.isRequired,
selectAllHostsMode: PropTypes.bool.isRequired,
fetchBulkParams: PropTypes.func.isRequired,
+ organizationId: PropTypes.number,
+ locationId: PropTypes.number,
modalType: PropTypes.string.isRequired,
};
BulkAssignTaxonomyModal.defaultProps = {
isOpen: false,
closeModal: () => {},
+ organizationId: undefined,
+ locationId: undefined,
};
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/assignTaxonomy/index.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/assignTaxonomy/index.js
index 61d2fdfc5d..4375e6b447 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/assignTaxonomy/index.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/assignTaxonomy/index.js
@@ -7,15 +7,21 @@ import {
} from './BulkAssignTaxonomyModal';
export const BulkAssignOrganizationModalScene = ({ isOpen, closeModal }) => {
- const { selectAllHostsMode, selectedCount, fetchBulkParams } = useContext(
- ForemanActionsBarContext
- );
+ const {
+ selectAllHostsMode,
+ selectedCount,
+ fetchBulkParams,
+ organizationId,
+ locationId,
+ } = useContext(ForemanActionsBarContext);
return (
@@ -23,15 +29,21 @@ export const BulkAssignOrganizationModalScene = ({ isOpen, closeModal }) => {
};
export const BulkAssignLocationModalScene = ({ isOpen, closeModal }) => {
- const { selectAllHostsMode, selectedCount, fetchBulkParams } = useContext(
- ForemanActionsBarContext
- );
+ const {
+ selectAllHostsMode,
+ selectedCount,
+ fetchBulkParams,
+ organizationId,
+ locationId,
+ } = useContext(ForemanActionsBarContext);
return (
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 e492e0b0fc..eea9df3c7e 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
@@ -12,7 +12,7 @@ import {
} from '@patternfly/react-core';
import { addToast } from '../../../ToastsList/slice';
import { translate as __ } from '../../../../common/I18n';
-import { failedHostsToastParams } from '../helpers';
+import { buildBulkRequestBody, failedHostsToastParams } from '../helpers';
import { STATUS } from '../../../../constants';
import { selectAPIStatus } from '../../../../redux/API/APISelectors';
import { bulkBuildHosts, HOST_BUILD_KEY } from './actions';
@@ -22,6 +22,8 @@ const BulkBuildHostModal = ({
closeModal,
selectedCount,
fetchBulkParams,
+ organizationId,
+ locationId,
}) => {
const dispatch = useDispatch();
const [buildRadioChecked, setBuildRadioChecked] = useState(true);
@@ -44,13 +46,13 @@ const BulkBuildHostModal = ({
);
};
const handleSave = () => {
- const requestBody = {
- included: {
- search: fetchBulkParams(),
- },
+ const requestBody = buildBulkRequestBody({
+ fetchBulkParams,
+ organizationId,
+ locationId,
reboot: rebootChecked,
rebuild_configuration: !buildRadioChecked,
- };
+ });
dispatch(bulkBuildHosts(requestBody, handleModalClose, handleError));
};
@@ -156,11 +158,15 @@ BulkBuildHostModal.propTypes = {
closeModal: PropTypes.func,
selectedCount: PropTypes.number.isRequired,
fetchBulkParams: PropTypes.func.isRequired,
+ organizationId: PropTypes.number,
+ locationId: PropTypes.number,
};
BulkBuildHostModal.defaultProps = {
isOpen: false,
closeModal: () => {},
+ organizationId: undefined,
+ locationId: undefined,
};
export default BulkBuildHostModal;
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 f7e413862e..b143c30973 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
@@ -4,14 +4,19 @@ import { ForemanActionsBarContext } from '../../../../components/HostDetails/Act
import BulkBuildHostModal from './BulkBuildHostModal';
const BulkBuildHostModalScene = ({ isOpen, closeModal }) => {
- const { selectedCount, fetchBulkParams } = useContext(
- ForemanActionsBarContext
- );
+ const {
+ selectedCount,
+ fetchBulkParams,
+ organizationId,
+ locationId,
+ } = useContext(ForemanActionsBarContext);
return (
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/bulkDelete.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/bulkDelete.js
index 6ab889bd29..5c12e9d7f7 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/bulkDelete.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/bulkDelete.js
@@ -4,17 +4,24 @@ import { visit, foremanUrl } from '../../../common/helpers';
import { sprintf, translate as __ } from '../../../common/I18n';
import { openConfirmModal } from '../../ConfirmModal';
import { APIActions } from '../../../redux/API';
+import { bulkActionTaxonomyParams } from './helpers';
import './bulkDeleteModal.scss';
export const bulkDeleteHosts = ({
bulkParams,
+ organizationId,
+ locationId,
selectedCount,
destroyVmOnHostDelete,
onDeleteSuccess,
}) => dispatch => {
const successToast = () => sprintf(__('%s hosts deleted'), selectedCount);
const errorToast = ({ message }) => message;
- const url = foremanUrl(`/api/v2/hosts/bulk?search=${bulkParams}`);
+ const queryParams = new URLSearchParams({
+ search: bulkParams,
+ ...bulkActionTaxonomyParams({ organizationId, locationId }),
+ });
+ const url = foremanUrl(`/api/v2/hosts/bulk?${queryParams.toString()}`);
// TODO: Replace with a checkbox instead of a global setting for cascade host destroy
const cascadeMessage = () =>
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/changeOwner/BulkChangeOwnerModal.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/changeOwner/BulkChangeOwnerModal.js
index 34e7d9b456..d48e9d9e0c 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/changeOwner/BulkChangeOwnerModal.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/changeOwner/BulkChangeOwnerModal.js
@@ -34,7 +34,7 @@ import {
HOSTS_API_PATH,
API_REQUEST_KEY,
} from '../../../../routes/Hosts/constants';
-import { failedHostsToastParams } from '../helpers';
+import { buildBulkRequestBody, failedHostsToastParams } from '../helpers';
const BulkChangeOwnerModal = ({
isOpen,
@@ -42,6 +42,8 @@ const BulkChangeOwnerModal = ({
selectAllHostsMode,
selectedCount,
fetchBulkParams,
+ organizationId,
+ locationId,
}) => {
const dispatch = useDispatch();
const [ownerId, setOwnerId] = useState('');
@@ -131,12 +133,12 @@ const BulkChangeOwnerModal = ({
};
const handleConfirm = () => {
- const requestBody = {
- included: {
- search: fetchBulkParams(),
- },
+ const requestBody = buildBulkRequestBody({
+ fetchBulkParams,
+ organizationId,
+ locationId,
owner_id: ownerId,
- };
+ });
dispatch(bulkChangeOwner(requestBody, handleSuccess, handleError));
};
@@ -250,11 +252,15 @@ BulkChangeOwnerModal.propTypes = {
fetchBulkParams: PropTypes.func.isRequired,
selectedCount: PropTypes.number.isRequired,
selectAllHostsMode: PropTypes.bool.isRequired,
+ organizationId: PropTypes.number,
+ locationId: PropTypes.number,
};
BulkChangeOwnerModal.defaultProps = {
isOpen: false,
closeModal: () => {},
+ organizationId: undefined,
+ locationId: undefined,
};
export default BulkChangeOwnerModal;
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/changeOwner/index.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/changeOwner/index.js
index fd554d8662..454e56ca50 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/changeOwner/index.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/changeOwner/index.js
@@ -9,6 +9,8 @@ const BulkChangeOwnerModalScene = ({ isOpen, closeModal }) => {
selectedCount,
selectedResults,
fetchBulkParams,
+ organizationId,
+ locationId,
} = useContext(ForemanActionsBarContext);
return (
{
selectedCount={selectedCount}
selectedResults={selectedResults}
fetchBulkParams={fetchBulkParams}
+ organizationId={organizationId}
+ locationId={locationId}
isOpen={isOpen}
closeModal={closeModal}
/>
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/disassociate/BulkDisassociateModal.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/disassociate/BulkDisassociateModal.js
index 17a51be23d..d8b7ec3300 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/disassociate/BulkDisassociateModal.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/disassociate/BulkDisassociateModal.js
@@ -18,7 +18,7 @@ import {
HOSTS_API_PATH,
API_REQUEST_KEY,
} from '../../../../routes/Hosts/constants';
-import { failedHostsToastParams } from '../helpers';
+import { buildBulkRequestBody, failedHostsToastParams } from '../helpers';
const BulkDisassociateModal = ({
isOpen,
@@ -27,6 +27,8 @@ const BulkDisassociateModal = ({
selectedCount,
selectedResults,
fetchBulkParams,
+ organizationId,
+ locationId,
}) => {
const dispatch = useDispatch();
const hostsWithComputeResource = selectedResults?.filter(
@@ -91,11 +93,12 @@ const BulkDisassociateModal = ({
const queryString = selectedResultsEmpty
? fetchBulkParams()
: `id ^ (${hostsWithComputeResource.map(h => h.id).join(',')})`;
- const requestBody = {
- included: {
- search: queryString,
- },
- };
+ const requestBody = buildBulkRequestBody({
+ fetchBulkParams,
+ organizationId,
+ locationId,
+ includedSearch: queryString,
+ });
dispatch(bulkDisassociate(requestBody, handleSuccess, handleError));
};
@@ -188,12 +191,16 @@ BulkDisassociateModal.propTypes = {
fetchBulkParams: PropTypes.func.isRequired,
selectedCount: PropTypes.number.isRequired,
selectAllHostsMode: PropTypes.bool.isRequired,
+ organizationId: PropTypes.number,
+ locationId: PropTypes.number,
};
BulkDisassociateModal.defaultProps = {
isOpen: false,
closeModal: () => {},
selectedResults: [],
+ organizationId: undefined,
+ locationId: undefined,
};
export default BulkDisassociateModal;
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/disassociate/index.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/disassociate/index.js
index 45438eb4f2..169eb72f36 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/disassociate/index.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/disassociate/index.js
@@ -9,6 +9,8 @@ const BulkDisassociateModalScene = ({ isOpen, closeModal }) => {
selectedCount,
selectedResults,
fetchBulkParams,
+ organizationId,
+ locationId,
} = useContext(ForemanActionsBarContext);
return (
{
selectedCount={selectedCount}
selectedResults={selectedResults}
fetchBulkParams={fetchBulkParams}
+ organizationId={organizationId}
+ locationId={locationId}
isOpen={isOpen}
closeModal={closeModal}
/>
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/helpers.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/helpers.js
index 675c0c5bfb..e51c1ba8cc 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/helpers.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/helpers.js
@@ -8,6 +8,28 @@ export const searchLink = ({ query, message, baseUrl }) => ({
href: urlWithSearch(baseUrl, query),
});
+export const bulkActionTaxonomyParams = ({
+ organizationId,
+ locationId,
+} = {}) => ({
+ ...(organizationId != null ? { organization_id: organizationId } : {}),
+ ...(locationId != null ? { location_id: locationId } : {}),
+});
+
+export const buildBulkRequestBody = ({
+ fetchBulkParams,
+ organizationId,
+ locationId,
+ includedSearch,
+ ...params
+}) => ({
+ included: {
+ search: includedSearch || fetchBulkParams(),
+ },
+ ...bulkActionTaxonomyParams({ organizationId, locationId }),
+ ...params,
+});
+
export const failedHostsToastParams = ({
message,
failed_host_ids: failedHostIds,
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/powerState/BulkPowerStateModal.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/powerState/BulkPowerStateModal.js
index a21ab5bfcd..8cb93e5b10 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/powerState/BulkPowerStateModal.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/powerState/BulkPowerStateModal.js
@@ -19,7 +19,7 @@ import './BulkPowerStateModal.scss';
import { HostsPowerRefreshContext } from '../../HostsPowerRefreshContext';
import { POWER_STATES, BULK_POWER_STATE_KEY } from './constants';
import { bulkChangePowerState } from './actions';
-import { failedHostsToastParams } from '../helpers';
+import { buildBulkRequestBody, failedHostsToastParams } from '../helpers';
import { addToast } from '../../../ToastsList/slice';
import {
HOSTS_API_PATH,
@@ -31,6 +31,8 @@ import { APIActions } from '../../../../redux/API';
const BulkPowerStateModal = ({
selectedHostsCount,
fetchBulkParams,
+ organizationId,
+ locationId,
isOpen,
closeModal,
}) => {
@@ -102,12 +104,12 @@ const BulkPowerStateModal = ({
const handleSubmit = () => {
setIsLoading(true);
- const payload = {
- included: {
- search: fetchBulkParams(),
- },
+ const payload = buildBulkRequestBody({
+ fetchBulkParams,
+ organizationId,
+ locationId,
power: selectedPowerState,
- };
+ });
dispatch(bulkChangePowerState(payload, handleSuccess, handleError));
};
@@ -206,12 +208,16 @@ const BulkPowerStateModal = ({
BulkPowerStateModal.propTypes = {
selectedHostsCount: PropTypes.number,
fetchBulkParams: PropTypes.func.isRequired,
+ organizationId: PropTypes.number,
+ locationId: PropTypes.number,
isOpen: PropTypes.bool,
closeModal: PropTypes.func,
};
BulkPowerStateModal.defaultProps = {
selectedHostsCount: 0,
+ organizationId: undefined,
+ locationId: undefined,
isOpen: false,
closeModal: () => {},
};
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/powerState/index.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/powerState/index.js
index 80dcf1ba13..f67e800a9e 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/powerState/index.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/powerState/index.js
@@ -4,13 +4,18 @@ import { ForemanActionsBarContext } from '../../../../components/HostDetails/Act
import BulkPowerStateModal from './BulkPowerStateModal';
const BulkPowerStateModalScene = ({ isOpen, closeModal }) => {
- const { fetchBulkParams, selectedCount = 0 } = useContext(
- ForemanActionsBarContext
- );
+ const {
+ fetchBulkParams,
+ selectedCount = 0,
+ organizationId,
+ locationId,
+ } = useContext(ForemanActionsBarContext);
return (
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/reassignHostGroup/BulkReassignHostgroupModal.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/reassignHostGroup/BulkReassignHostgroupModal.js
index 308e4ee60f..3e6c051a85 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/reassignHostGroup/BulkReassignHostgroupModal.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/reassignHostGroup/BulkReassignHostgroupModal.js
@@ -11,7 +11,7 @@ import {
} from '@patternfly/react-core';
import { addToast } from '../../../ToastsList/slice';
import { translate as __ } from '../../../../common/I18n';
-import { failedHostsToastParams } from '../helpers';
+import { buildBulkRequestBody, failedHostsToastParams } from '../helpers';
import { STATUS } from '../../../../constants';
import {
selectAPIStatus,
@@ -77,6 +77,8 @@ const BulkReassignHostgroupModal = ({
closeModal,
selectedCount,
fetchBulkParams,
+ organizationId,
+ locationId,
}) => {
const dispatch = useDispatch();
const [hostgroupId, setHostgroupId] = useState('');
@@ -151,12 +153,12 @@ const BulkReassignHostgroupModal = ({
handleModalClose();
};
const handleSave = () => {
- const requestBody = {
- included: {
- search: fetchBulkParams(),
- },
+ const requestBody = buildBulkRequestBody({
+ fetchBulkParams,
+ organizationId,
+ locationId,
hostgroup_id: hostgroupId,
- };
+ });
dispatch(bulkReassignHostgroups(requestBody, handleSuccess, handleError));
};
@@ -285,11 +287,15 @@ BulkReassignHostgroupModal.propTypes = {
closeModal: PropTypes.func,
selectedCount: PropTypes.number.isRequired,
fetchBulkParams: PropTypes.func.isRequired,
+ organizationId: PropTypes.number,
+ locationId: PropTypes.number,
};
BulkReassignHostgroupModal.defaultProps = {
isOpen: false,
closeModal: () => {},
+ organizationId: undefined,
+ locationId: undefined,
};
export default BulkReassignHostgroupModal;
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/reassignHostGroup/index.js b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/reassignHostGroup/index.js
index 4712eaad4d..d7a4669a73 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/reassignHostGroup/index.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/reassignHostGroup/index.js
@@ -4,14 +4,19 @@ import { ForemanActionsBarContext } from '../../../../components/HostDetails/Act
import BulkReassignHostgroupModal from './BulkReassignHostgroupModal';
const BulkReassignHostgroupModalScene = ({ isOpen, closeModal }) => {
- const { selectedCount, fetchBulkParams } = useContext(
- ForemanActionsBarContext
- );
+ const {
+ selectedCount,
+ fetchBulkParams,
+ organizationId,
+ locationId,
+ } = useContext(ForemanActionsBarContext);
return (
diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/index.js b/webpack/assets/javascripts/react_app/components/HostsIndex/index.js
index 83c173ce6a..f8b82efd1e 100644
--- a/webpack/assets/javascripts/react_app/components/HostsIndex/index.js
+++ b/webpack/assets/javascripts/react_app/components/HostsIndex/index.js
@@ -45,6 +45,8 @@ import {
useForemanSettings,
useForemanHostsPageUrl,
useForemanContext,
+ useForemanOrganization,
+ useForemanLocation,
} from '../../Root/Context/ForemanContext';
import { bulkDeleteHosts } from './BulkActions/bulkDelete';
import {
@@ -114,6 +116,8 @@ const HostsIndex = () => {
syncWithOptions: true,
});
const contextData = useForemanContext();
+ const currentOrganization = useForemanOrganization();
+ const currentLocation = useForemanLocation();
const {
response: {
@@ -240,6 +244,8 @@ const HostsIndex = () => {
dispatch(
bulkDeleteHosts({
bulkParams,
+ organizationId: currentOrganization?.id,
+ locationId: currentLocation?.id,
selectedCount,
destroyVmOnHostDelete,
onDeleteSuccess: () => {
@@ -589,6 +595,8 @@ const HostsIndex = () => {
selectedCount,
selectedResults,
fetchBulkParams,
+ organizationId: currentOrganization?.id,
+ locationId: currentLocation?.id,
}}
>
({
})),
useForemanHostsPageUrl: jest.fn(() => '/hosts'),
useForemanContext: jest.fn(() => ({})),
+ useForemanOrganization: jest.fn(() => undefined),
+ useForemanLocation: jest.fn(() => undefined),
}));
jest.mock('../common/Slot', () => ({