foreman_puppet 10.0.0 → 10.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/foreman_puppet/api/v2/hosts_bulk_actions_controller.rb +102 -0
  3. data/app/services/concerns/foreman_puppet/extensions/bulk_hosts_manager.rb +24 -0
  4. data/config/api_routes.rb +11 -0
  5. data/lib/foreman_puppet/engine.rb +1 -0
  6. data/lib/foreman_puppet/register.rb +2 -0
  7. data/lib/foreman_puppet/version.rb +1 -1
  8. data/test/controllers/foreman_puppet/api/v2/hosts_bulk_actions_controller_test.rb +171 -0
  9. data/test/services/foreman_puppet/bulk_hosts_manager_test.rb +33 -0
  10. data/webpack/global_index.js +42 -0
  11. data/webpack/src/Extends/Hosts/ActionsBar/ActionsBar.scss +14 -0
  12. data/webpack/src/Extends/Hosts/ActionsBar/index.js +73 -0
  13. data/webpack/src/Extends/Hosts/BulkActions/BulkChangeProxyCommon/__tests__/actions.test.js +78 -0
  14. data/webpack/src/Extends/Hosts/BulkActions/BulkChangeProxyCommon/actions.js +36 -0
  15. data/webpack/src/Extends/Hosts/BulkActions/BulkChangeProxyCommon/index.js +252 -0
  16. data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetCAProxy/__tests__/index.test.js +66 -0
  17. data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetCAProxy/index.js +40 -0
  18. data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetProxy/__tests__/index.test.js +66 -0
  19. data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetProxy/index.js +40 -0
  20. data/webpack/src/Extends/Hosts/BulkActions/BulkRemoveProxyCommon/__tests__/actions.test.js +64 -0
  21. data/webpack/src/Extends/Hosts/BulkActions/BulkRemoveProxyCommon/actions.js +24 -0
  22. data/webpack/src/Extends/Hosts/BulkActions/BulkRemoveProxyCommon/index.js +164 -0
  23. data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetCAProxy/__tests__/index.test.js +65 -0
  24. data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetCAProxy/index.js +39 -0
  25. data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetProxy/__tests__/index.test.js +61 -0
  26. data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetProxy/index.js +39 -0
  27. data/webpack/src/Extends/Hosts/BulkActions/__tests__/toastHelpers.test.js +55 -0
  28. data/webpack/src/Extends/Hosts/BulkActions/toastHelpers.js +17 -0
  29. data/webpack/src/foreman_puppet_host_form.test.js +4 -4
  30. metadata +26 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc7813b3e70470b1ede75609466fd1f395b2b24415a6fc30dea85fcf9431c10a
4
- data.tar.gz: 3f6e2c28bdb0143c86e1182b201afb8eb81a9753c0fcd8198c5bf4996a3e995f
3
+ metadata.gz: 6897f1c5899747e2b70508bfa86bd240db54e8cef027b369941302e4de585814
4
+ data.tar.gz: 81360486bd6be95f0a73be4132766b4a8b561e0020e26589e4a08b90b6318ba7
5
5
  SHA512:
6
- metadata.gz: 5c2df904975315458ad27f09262c0025c9240d8750b89f2325a86bcd53abbd7c9e8d4d5ded37aebe594b069b86f3e0697be806652bfba01a8a42931a2b38cbca
7
- data.tar.gz: 9708de0a826955c059856924d0fd206d76b2b21f8905e450b030c8876659f7f02692520cea3888701028e330947c4e556f1741dd3f21f6397124b1dc2281b1a9
6
+ metadata.gz: 2391cce05ed4cf77c2f84ffa205306d563add4ad6a361002583a791debae0b8166d6ef4f196fd57b9b1896dd983d8d35f4e7e6b79fac3362a1ceb0d11a65d82e
7
+ data.tar.gz: 852d1503ca1443e667ccf8f70f7271ba4baaadd067878ad62a28ff0426921d6597f9f245a1232948e9ac1e2b0573b4c74634b0012ab80991895899b11a7ccff1
@@ -0,0 +1,102 @@
1
+ module ForemanPuppet
2
+ module Api
3
+ module V2
4
+ class HostsBulkActionsController < ::ForemanPuppet::Api::V2::PuppetBaseController
5
+ include ::Api::V2::BulkHostsExtension
6
+ before_action :find_editable_hosts, only: %i[change_puppet_proxy remove_puppet_proxy]
7
+ before_action :find_smart_proxy, only: %i[change_puppet_proxy]
8
+
9
+ def_param_group :bulk_params do
10
+ param :organization_id, :number, required: true, desc: N_('ID of the organization')
11
+ param :included, Hash, required: true, action_aware: true do
12
+ param :search, String, required: false, desc: N_('Search string for hosts to perform an action on')
13
+ param :ids, Array, required: false, desc: N_('List of host ids to perform an action on')
14
+ end
15
+ param :excluded, Hash, required: true, action_aware: true do
16
+ param :ids, Array, required: false, desc: N_('List of host ids to exclude and not run an action on')
17
+ end
18
+ end
19
+
20
+ api :PUT, '/hosts/bulk/change_puppet_proxy', N_('Change Puppet (CA) Proxy')
21
+ param_group :bulk_params
22
+ param :proxy_id, :number, required: true, desc: N_('ID of the Puppet proxy to reassign the hosts to')
23
+ param :ca_proxy, :bool, required: true, desc: N_('True, if Puppet CA proxy should be changed instead of the Puppet proxy')
24
+ def change_puppet_proxy
25
+ error_hosts = ::BulkHostsManager.new(hosts: @hosts).change_puppet_proxy(@proxy, ca_proxy?)
26
+ process_bulk_puppet_proxy_response(
27
+ error_hosts,
28
+ success_message: format(n_(
29
+ 'Updated host: changed %{proxy_type}',
30
+ 'Updated hosts: changed %{proxy_type}',
31
+ @hosts.count
32
+ ), proxy_type: proxy_type),
33
+ error_message: format(n_(
34
+ 'Failed to change %{proxy_type} for %{count} host',
35
+ 'Failed to change %{proxy_type} for %{count} hosts',
36
+ error_hosts.count
37
+ ), proxy_type: proxy_type, count: error_hosts.count)
38
+ )
39
+ end
40
+
41
+ api :PUT, '/hosts/bulk/remove_puppet_proxy', N_('Remove Puppet (CA) Proxy')
42
+ param_group :bulk_params
43
+ param :ca_proxy, :bool, required: true, desc: N_('True, if Puppet CA proxy should be removed instead of the Puppet proxy')
44
+ def remove_puppet_proxy
45
+ error_hosts = ::BulkHostsManager.new(hosts: @hosts).change_puppet_proxy(nil, ca_proxy?)
46
+ process_bulk_puppet_proxy_response(
47
+ error_hosts,
48
+ success_message: format(n_(
49
+ 'Updated host: removed %{proxy_type}',
50
+ 'Updated hosts: removed %{proxy_type}',
51
+ @hosts.count
52
+ ), proxy_type: proxy_type),
53
+ error_message: format(n_(
54
+ 'Failed to remove %{proxy_type} for %{count} host',
55
+ 'Failed to remove %{proxy_type} for %{count} hosts',
56
+ error_hosts.count
57
+ ), proxy_type: proxy_type, count: error_hosts.count)
58
+ )
59
+ end
60
+
61
+ private
62
+
63
+ def find_editable_hosts
64
+ find_bulk_hosts(:edit_hosts, params)
65
+ end
66
+
67
+ def process_bulk_puppet_proxy_response(error_hosts, success_message:, error_message:)
68
+ if error_hosts.empty?
69
+ process_response(true, { message: success_message })
70
+ else
71
+ render_error(:bulk_hosts_error, status: :unprocessable_entity,
72
+ locals: { message: error_message, failed_host_ids: error_hosts })
73
+ end
74
+ end
75
+
76
+ def find_smart_proxy
77
+ feature = ca_proxy? ? 'Puppet CA' : 'Puppet'
78
+ @proxy = SmartProxy.with_features(feature).find_by(id: params[:proxy_id])
79
+
80
+ if @proxy.nil?
81
+ render json: {
82
+ error: {
83
+ message: format(_('A Smart Proxy with id %{id} and the %{proxy_type} feature could not be found.'), id: params[:proxy_id], proxy_type: proxy_type),
84
+ },
85
+ }, status: :unprocessable_entity
86
+ false
87
+ else
88
+ true
89
+ end
90
+ end
91
+
92
+ def ca_proxy?
93
+ Foreman::Cast.to_bool(params[:ca_proxy])
94
+ end
95
+
96
+ def proxy_type
97
+ ca_proxy? ? _('Puppet CA proxy') : _('Puppet proxy')
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,24 @@
1
+ module ForemanPuppet
2
+ module Extensions
3
+ module BulkHostsManager
4
+ extend ActiveSupport::Concern
5
+
6
+ def change_puppet_proxy(proxy, is_ca_proxy)
7
+ error_hosts = []
8
+ @hosts.each do |host|
9
+ if is_ca_proxy
10
+ host.puppet_ca_proxy = proxy
11
+ else
12
+ host.puppet_proxy = proxy
13
+ end
14
+ host.save(validate: false)
15
+ rescue StandardError => e
16
+ message = format(_('Failed to set proxy for %{host}.'), host: host)
17
+ Foreman::Logging.exception(message, e)
18
+ error_hosts << host.id
19
+ end
20
+ error_hosts
21
+ end
22
+ end
23
+ end
24
+ end
data/config/api_routes.rb CHANGED
@@ -1,3 +1,14 @@
1
+ Foreman::Application.routes.draw do
2
+ scope module: 'foreman_puppet' do
3
+ namespace :api, defaults: { format: 'json' } do
4
+ scope '(:apiv)', module: :v2, defaults: { apiv: 'v2' }, apiv: /v1|v2/, constraints: ApiConstraints.new(version: 2, default: true) do
5
+ match 'hosts/bulk/change_puppet_proxy', to: 'hosts_bulk_actions#change_puppet_proxy', via: [:put]
6
+ match 'hosts/bulk/remove_puppet_proxy', to: 'hosts_bulk_actions#remove_puppet_proxy', via: [:put]
7
+ end
8
+ end
9
+ end
10
+ end
11
+
1
12
  ForemanPuppet::Engine.routes.draw do
2
13
  namespace :api, defaults: { format: 'json' } do
3
14
  scope '(:apiv)', module: :v2, defaults: { apiv: 'v2' }, apiv: /v1|v2/, constraints: ApiConstraints.new(version: 2, default: true) do
@@ -49,6 +49,7 @@ module ForemanPuppet
49
49
  ::ProvisioningTemplate.include ForemanPuppet::Extensions::ProvisioningTemplate
50
50
 
51
51
  ::HostCounter.prepend ForemanPuppet::Extensions::HostCounter
52
+ ::BulkHostsManager.include ForemanPuppet::Extensions::BulkHostsManager
52
53
 
53
54
  ::Api::V2::BaseController.include ForemanPuppet::Extensions::ApiBaseController
54
55
  ::Api::V2::HostsController.include ForemanPuppet::Extensions::ApiV2HostsController
@@ -62,6 +62,8 @@ Foreman::Plugin.register :foreman_puppet do
62
62
  p.actions << 'hosts/update_multiple_environment'
63
63
  p.actions << 'hosts/select_multiple_puppet_proxy'
64
64
  p.actions << 'hosts/update_multiple_puppet_proxy'
65
+ p.actions << 'foreman_puppet/api/v2/hosts_bulk_actions/change_puppet_proxy'
66
+ p.actions << 'foreman_puppet/api/v2/hosts_bulk_actions/remove_puppet_proxy'
65
67
  end
66
68
  p.actions << 'foreman_puppet/puppetclasses/parameters'
67
69
  end
@@ -1,3 +1,3 @@
1
1
  module ForemanPuppet
2
- VERSION = '10.0.0'.freeze
2
+ VERSION = '10.1.0'.freeze
3
3
  end
@@ -0,0 +1,171 @@
1
+ require 'test_puppet_helper'
2
+
3
+ module ForemanPuppet
4
+ module Api
5
+ module V2
6
+ class HostsBulkActionsControllerTest < ActionController::TestCase
7
+ tests ::ForemanPuppet::Api::V2::HostsBulkActionsController
8
+
9
+ setup do
10
+ @routes = ::Foreman::Application.routes
11
+ end
12
+
13
+ let(:host) { FactoryBot.create(:host, :with_puppet_enc) }
14
+ let(:host2) do
15
+ FactoryBot.create(:host, :with_puppet_enc,
16
+ organization: host.organization,
17
+ location: host.location)
18
+ end
19
+ let(:proxy) { FactoryBot.create(:puppet_and_ca_smart_proxy, organizations: [host.organization], locations: [host.location]) }
20
+
21
+ test 'changes puppet proxy for selected hosts' do
22
+ put :change_puppet_proxy,
23
+ params: bulk_params.merge(proxy_id: proxy.id, ca_proxy: false)
24
+
25
+ assert_response :success
26
+ assert_equal proxy.id, host2.reload.puppet_proxy_id
27
+ assert_equal proxy.id, host.reload.puppet_proxy_id
28
+ end
29
+
30
+ test 'changes puppet ca proxy for selected hosts' do
31
+ put :change_puppet_proxy,
32
+ params: bulk_params.merge(proxy_id: proxy.id, ca_proxy: true)
33
+
34
+ assert_response :success
35
+ assert_equal proxy.id, host2.reload.puppet_ca_proxy_id
36
+ assert_equal proxy.id, host.reload.puppet_ca_proxy_id
37
+ end
38
+
39
+ test 'removes puppet proxy for selected hosts' do
40
+ host.update!(puppet_proxy: proxy)
41
+ host2.update!(puppet_proxy: proxy)
42
+
43
+ assert_equal proxy, host.reload.puppet_proxy
44
+
45
+ put :remove_puppet_proxy,
46
+ params: bulk_params.merge(ca_proxy: false),
47
+ session: set_session_user
48
+
49
+ assert_response :success
50
+ assert_nil host.reload.puppet_proxy
51
+ assert_nil host2.reload.puppet_proxy
52
+ end
53
+
54
+ test 'returns error when puppet proxy is missing' do
55
+ missing_proxy_id = 999_999
56
+
57
+ put :change_puppet_proxy,
58
+ params: bulk_params.merge(proxy_id: missing_proxy_id, ca_proxy: false),
59
+ session: set_session_user
60
+
61
+ assert_response :unprocessable_entity
62
+ response = JSON.parse(@response.body)
63
+ assert_equal "A Smart Proxy with id #{missing_proxy_id} and the Puppet proxy feature could not be found.",
64
+ response.dig('error', 'message')
65
+ end
66
+
67
+ test 'returns error when puppet ca proxy is missing' do
68
+ missing_proxy_id = 999_999
69
+
70
+ put :change_puppet_proxy,
71
+ params: bulk_params.merge(proxy_id: missing_proxy_id, ca_proxy: true),
72
+ session: set_session_user
73
+
74
+ assert_response :unprocessable_entity
75
+ response = JSON.parse(@response.body)
76
+ assert_equal "A Smart Proxy with id #{missing_proxy_id} and the Puppet CA proxy feature could not be found.",
77
+ response.dig('error', 'message')
78
+ end
79
+
80
+ test 'returns error when smart proxy is missing puppet feature' do
81
+ invalid_proxy = FactoryBot.create(:smart_proxy, organizations: [host.organization], locations: [host.location])
82
+ invalid_proxy.smart_proxy_feature_by_name('Puppet')&.destroy!
83
+
84
+ put :change_puppet_proxy,
85
+ params: bulk_params.merge(proxy_id: invalid_proxy.id, ca_proxy: false),
86
+ session: set_session_user
87
+
88
+ assert_response :unprocessable_entity
89
+ response = JSON.parse(@response.body)
90
+ assert_equal "A Smart Proxy with id #{invalid_proxy.id} and the Puppet proxy feature could not be found.",
91
+ response.dig('error', 'message')
92
+ end
93
+
94
+ test 'returns error when smart proxy is missing puppet ca feature' do
95
+ invalid_proxy = FactoryBot.create(:puppet_smart_proxy, organizations: [host.organization], locations: [host.location])
96
+
97
+ put :change_puppet_proxy,
98
+ params: bulk_params.merge(proxy_id: invalid_proxy.id, ca_proxy: true),
99
+ session: set_session_user
100
+
101
+ assert_response :unprocessable_entity
102
+ response = JSON.parse(@response.body)
103
+ assert_equal "A Smart Proxy with id #{invalid_proxy.id} and the Puppet CA proxy feature could not be found.",
104
+ response.dig('error', 'message')
105
+ end
106
+
107
+ test 'returns error when changing puppet proxy fails for some hosts' do
108
+ ::BulkHostsManager.any_instance.expects(:change_puppet_proxy)
109
+ .with(proxy, false)
110
+ .returns([host2.id])
111
+
112
+ put :change_puppet_proxy,
113
+ params: bulk_params.merge(proxy_id: proxy.id, ca_proxy: false),
114
+ session: set_session_user
115
+
116
+ assert_response :unprocessable_entity
117
+ response = JSON.parse(@response.body)
118
+ assert_equal 'Failed to change Puppet proxy for 1 host',
119
+ response.dig('error', 'message')
120
+ assert_equal [host2.id], response.dig('error', 'failed_host_ids')
121
+ end
122
+
123
+ test 'returns error when removing puppet proxy fails for some hosts' do
124
+ host.update!(puppet_proxy: proxy)
125
+ host2.update!(puppet_proxy: proxy)
126
+ ::BulkHostsManager.any_instance.expects(:change_puppet_proxy)
127
+ .with(nil, false)
128
+ .returns([host.id])
129
+
130
+ put :remove_puppet_proxy,
131
+ params: bulk_params.merge(ca_proxy: false),
132
+ session: set_session_user
133
+
134
+ assert_response :unprocessable_entity
135
+ response = JSON.parse(@response.body)
136
+ assert_equal 'Failed to remove Puppet proxy for 1 host',
137
+ response.dig('error', 'message')
138
+ assert_equal [host.id], response.dig('error', 'failed_host_ids')
139
+ assert_equal proxy.id, host.reload.puppet_proxy_id
140
+ end
141
+
142
+ test 'returns error when removing puppet ca proxy fails for some hosts' do
143
+ host.update!(puppet_ca_proxy: proxy)
144
+ host2.update!(puppet_ca_proxy: proxy)
145
+ ::BulkHostsManager.any_instance.expects(:change_puppet_proxy)
146
+ .with(nil, true)
147
+ .returns([host.id])
148
+
149
+ put :remove_puppet_proxy,
150
+ params: bulk_params.merge(ca_proxy: true),
151
+ session: set_session_user
152
+
153
+ assert_response :unprocessable_entity
154
+ response = JSON.parse(@response.body)
155
+ assert_equal 'Failed to remove Puppet CA proxy for 1 host',
156
+ response.dig('error', 'message')
157
+ assert_equal [host.id], response.dig('error', 'failed_host_ids')
158
+ assert_equal proxy.id, host.reload.puppet_ca_proxy_id
159
+ end
160
+
161
+ def bulk_params
162
+ {
163
+ organization_id: host.organization_id,
164
+ included: { ids: [host.id, host2.id] },
165
+ excluded: { ids: [] },
166
+ }
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,33 @@
1
+ require 'test_puppet_helper'
2
+
3
+ class BulkHostsManagerTest < ActiveSupport::TestCase
4
+ let(:hosts) { FactoryBot.create_list(:host, 2, :with_puppet_enc) }
5
+ let(:manager) { ::BulkHostsManager.new(hosts: hosts) }
6
+ let(:proxy) { FactoryBot.create(:puppet_smart_proxy) }
7
+
8
+ test 'changes puppet proxy for hosts' do
9
+ manager.change_puppet_proxy(proxy, false)
10
+
11
+ hosts.each do |host|
12
+ assert_equal proxy.id, host.reload.puppet_proxy_id
13
+ end
14
+ end
15
+
16
+ test 'changes puppet ca proxy for hosts' do
17
+ manager.change_puppet_proxy(proxy, true)
18
+
19
+ hosts.each do |host|
20
+ assert_equal proxy.id, host.reload.puppet_ca_proxy_id
21
+ end
22
+ end
23
+
24
+ test 'clears puppet proxy when proxy is nil' do
25
+ hosts.each { |host| host.update!(puppet_proxy: proxy) }
26
+
27
+ manager.change_puppet_proxy(nil, false)
28
+
29
+ hosts.each do |host|
30
+ assert_nil host.reload.puppet_proxy
31
+ end
32
+ end
33
+ end
@@ -1,9 +1,16 @@
1
+ import React from 'react';
2
+ import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
1
3
  import { registerReducer } from 'foremanReact/common/MountingService';
2
4
  import { registerColumns } from 'foremanReact/components/HostsIndex/Columns/core';
3
5
  import { translate as __ } from 'foremanReact/common/I18n';
4
6
  import reducers from './src/reducers';
5
7
  import { registerFills } from './src/Extends/Fills';
6
8
  import { registerLegacy } from './legacy';
9
+ import HostsIndexActionsBar from './src/Extends/Hosts/ActionsBar';
10
+ import BulkChangePuppetProxy from './src/Extends/Hosts/BulkActions/BulkChangePuppetProxy';
11
+ import BulkChangePuppetCAProxy from './src/Extends/Hosts/BulkActions/BulkChangePuppetCAProxy';
12
+ import BulkRemovePuppetProxy from './src/Extends/Hosts/BulkActions/BulkRemovePuppetProxy';
13
+ import BulkRemovePuppetCAProxy from './src/Extends/Hosts/BulkActions/BulkRemovePuppetCAProxy';
7
14
 
8
15
  // register reducers
9
16
  registerReducer('puppet', reducers);
@@ -29,4 +36,39 @@ puppetHostsIndexColumns.forEach(column => {
29
36
  column.categoryKey = 'puppet';
30
37
  });
31
38
 
39
+ addGlobalFill(
40
+ 'hosts-index-kebab',
41
+ 'puppet-hosts-index-kebab',
42
+ <HostsIndexActionsBar key="puppet-hosts-index-kebab" />,
43
+ 100
44
+ );
45
+
46
+ addGlobalFill(
47
+ '_all-hosts-modals',
48
+ 'BulkChangePuppetProxy',
49
+ <BulkChangePuppetProxy key="bulk-change-puppet-proxy" />,
50
+ 100
51
+ );
52
+
53
+ addGlobalFill(
54
+ '_all-hosts-modals',
55
+ 'BulkChangePuppetCAProxy',
56
+ <BulkChangePuppetCAProxy key="bulk-change-puppet-ca-proxy" />,
57
+ 100
58
+ );
59
+
60
+ addGlobalFill(
61
+ '_all-hosts-modals',
62
+ 'BulkRemovePuppetCAProxy',
63
+ <BulkRemovePuppetCAProxy key="bulk-remove-puppet-ca-proxy" />,
64
+ 100
65
+ );
66
+
67
+ addGlobalFill(
68
+ '_all-hosts-modals',
69
+ 'BulkRemovePuppetProxy',
70
+ <BulkRemovePuppetProxy key="bulk-remove-puppet-proxy" />,
71
+ 100
72
+ );
73
+
32
74
  registerColumns(puppetHostsIndexColumns);
@@ -0,0 +1,14 @@
1
+ .disabled-menu-item-span {
2
+ width: 25em;
3
+ display: flex;
4
+ flex-direction: row;
5
+ }
6
+
7
+ .disabled-menu-item-p {
8
+ margin-left: 0.6em;
9
+ word-break: normal;
10
+ }
11
+
12
+ .disabled-menu-item-icon {
13
+ font-size: small;
14
+ }
@@ -0,0 +1,73 @@
1
+ import React, { useContext } from 'react';
2
+ import { Menu, MenuItem, MenuContent, MenuList } from '@patternfly/react-core';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+ import { ForemanHostsIndexActionsBarContext } from 'foremanReact/components/HostsIndex';
5
+ import { openBulkModal } from 'foremanReact/common/BulkModalStateHelper';
6
+ import './ActionsBar.scss';
7
+
8
+ const HostActionsBar = () => {
9
+ const { selectedCount, setMenuOpen } = useContext(
10
+ ForemanHostsIndexActionsBarContext
11
+ );
12
+
13
+ const handleOpenBulkModal = modalId => {
14
+ setMenuOpen(false);
15
+ setTimeout(() => openBulkModal(modalId, true), 0);
16
+ };
17
+
18
+ return (
19
+ <MenuItem
20
+ itemId="content-flyout-item"
21
+ key="content-flyout"
22
+ isDisabled={selectedCount === 0}
23
+ flyoutMenu={
24
+ <Menu ouiaId="content-flyout-menu" onSelect={() => setMenuOpen(false)}>
25
+ <MenuContent>
26
+ <MenuList>
27
+ <MenuItem
28
+ itemId="bulk-change-puppet-proxy-menu-item"
29
+ key="bulk-change-puppet-proxy-menu-item"
30
+ onClick={() => handleOpenBulkModal('bulk-change-puppet-proxy')}
31
+ isDisabled={selectedCount === 0}
32
+ >
33
+ {__('Change Puppet proxy')}
34
+ </MenuItem>
35
+ <MenuItem
36
+ itemId="bulk-remove-puppet-proxy-menu-item"
37
+ key="bulk-remove-puppet-proxy-menu-item"
38
+ onClick={() => handleOpenBulkModal('bulk-remove-puppet-proxy')}
39
+ isDisabled={selectedCount === 0}
40
+ >
41
+ {__('Remove Puppet proxy')}
42
+ </MenuItem>
43
+ <MenuItem
44
+ itemId="bulk-change-puppet-ca-proxy-menu-item"
45
+ key="bulk-change-puppet-ca-proxy-menu-item"
46
+ onClick={() =>
47
+ handleOpenBulkModal('bulk-change-puppet-ca-proxy')
48
+ }
49
+ isDisabled={selectedCount === 0}
50
+ >
51
+ {__('Change Puppet CA proxy')}
52
+ </MenuItem>
53
+ <MenuItem
54
+ itemId="bulk-remove-puppet-ca-proxy-menu-item"
55
+ key="bulk-remove-puppet-ca-proxy-menu-item"
56
+ onClick={() =>
57
+ handleOpenBulkModal('bulk-remove-puppet-ca-proxy')
58
+ }
59
+ isDisabled={selectedCount === 0}
60
+ >
61
+ {__('Remove Puppet CA proxy')}
62
+ </MenuItem>
63
+ </MenuList>
64
+ </MenuContent>
65
+ </Menu>
66
+ }
67
+ >
68
+ {__('Puppet')}
69
+ </MenuItem>
70
+ );
71
+ };
72
+
73
+ export default HostActionsBar;
@@ -0,0 +1,78 @@
1
+ import { APIActions } from 'foremanReact/redux/API';
2
+ import { foremanUrl } from 'foremanReact/common/helpers';
3
+
4
+ import {
5
+ fetchSmartProxies,
6
+ SMART_PROXY_KEY,
7
+ bulkChangePuppetProxy,
8
+ BULK_CHANGE_PUPPET_CA_PROXY_KEY,
9
+ BULK_CHANGE_PUPPET_PROXY_KEY,
10
+ } from '../actions';
11
+
12
+ jest.mock('foremanReact/redux/API', () => ({
13
+ APIActions: {
14
+ get: jest.fn(),
15
+ put: jest.fn(),
16
+ },
17
+ }));
18
+
19
+ describe('BulkChangeProxyCommon actions', () => {
20
+ const smartProxiesUrl = foremanUrl('/api/smart_proxies');
21
+ const bulkChangeUrl = foremanUrl('/api/v2/hosts/bulk/change_puppet_proxy');
22
+
23
+ beforeEach(() => {
24
+ jest.clearAllMocks();
25
+ });
26
+
27
+ it('fetches smart proxies list filtered by feature search', () => {
28
+ fetchSmartProxies('Puppet');
29
+
30
+ expect(APIActions.get).toHaveBeenCalledWith({
31
+ key: SMART_PROXY_KEY,
32
+ url: smartProxiesUrl,
33
+ params: { per_page: 'all', search: 'feature = "Puppet"' },
34
+ });
35
+ });
36
+
37
+ it('calls bulk change puppet proxy endpoint for Puppet Proxy changes', () => {
38
+ const params = { included: { ids: [1] }, proxy_id: '1', ca_proxy: false };
39
+ const handleSuccess = jest.fn();
40
+ const handleError = jest.fn();
41
+
42
+ bulkChangePuppetProxy(
43
+ params,
44
+ handleSuccess,
45
+ handleError,
46
+ BULK_CHANGE_PUPPET_PROXY_KEY
47
+ );
48
+
49
+ expect(APIActions.put).toHaveBeenCalledWith({
50
+ key: BULK_CHANGE_PUPPET_PROXY_KEY,
51
+ url: bulkChangeUrl,
52
+ handleSuccess,
53
+ handleError,
54
+ params,
55
+ });
56
+ });
57
+
58
+ it('calls bulk change puppet proxy endpoint for Puppet CA Proxy changes', () => {
59
+ const params = { included: { ids: [1] }, proxy_id: '1', ca_proxy: true };
60
+ const handleSuccess = jest.fn();
61
+ const handleError = jest.fn();
62
+
63
+ bulkChangePuppetProxy(
64
+ params,
65
+ handleSuccess,
66
+ handleError,
67
+ BULK_CHANGE_PUPPET_CA_PROXY_KEY
68
+ );
69
+
70
+ expect(APIActions.put).toHaveBeenCalledWith({
71
+ key: BULK_CHANGE_PUPPET_CA_PROXY_KEY,
72
+ url: bulkChangeUrl,
73
+ handleSuccess,
74
+ handleError,
75
+ params,
76
+ });
77
+ });
78
+ });
@@ -0,0 +1,36 @@
1
+ import { APIActions } from 'foremanReact/redux/API';
2
+ import { foremanUrl } from 'foremanReact/common/helpers';
3
+
4
+ export const SMART_PROXY_KEY = 'SMART_PROXY_KEY';
5
+ export const BULK_CHANGE_PUPPET_CA_PROXY_KEY = 'BULK_CHANGE_PUPPET_CA_PROXY';
6
+ export const BULK_CHANGE_PUPPET_PROXY_KEY = 'BULK_CHANGE_PUPPET_PROXY';
7
+
8
+ export const fetchSmartProxies = feature => {
9
+ const url = foremanUrl('/api/smart_proxies');
10
+ return APIActions.get({
11
+ key: SMART_PROXY_KEY,
12
+ url,
13
+ params: {
14
+ per_page: 'all',
15
+ ...(feature ? { search: `feature = "${feature}"` } : {}),
16
+ },
17
+ });
18
+ };
19
+
20
+ export const bulkChangePuppetProxy = (
21
+ params,
22
+ handleSuccess,
23
+ handleError,
24
+ key
25
+ ) => {
26
+ const url = foremanUrl(`/api/v2/hosts/bulk/change_puppet_proxy`);
27
+ return APIActions.put({
28
+ key,
29
+ url,
30
+ handleSuccess,
31
+ handleError,
32
+ params,
33
+ });
34
+ };
35
+
36
+ export default fetchSmartProxies;