foreman_puppet 11.0.0 → 11.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.
- checksums.yaml +4 -4
- data/app/controllers/concerns/foreman_puppet/extensions/hosts_controller_extensions.rb +1 -1
- data/app/controllers/foreman_puppet/api/v2/hosts_bulk_actions_controller.rb +75 -1
- data/app/services/concerns/foreman_puppet/extensions/bulk_hosts_manager.rb +18 -0
- data/config/api_routes.rb +1 -0
- data/db/seeds.d/111_puppet_proxy_feature.rb +1 -1
- data/lib/foreman_puppet/register.rb +1 -0
- data/lib/foreman_puppet/version.rb +1 -1
- data/test/controllers/foreman_puppet/api/v2/hosts_bulk_actions_controller_test.rb +93 -0
- data/test/services/foreman_puppet/bulk_hosts_manager_test.rb +45 -0
- data/webpack/__mocks__/foremanReact/redux/API/index.js +8 -0
- data/webpack/global_index.js +18 -1
- data/webpack/src/Extends/Hosts/ActionsBar/index.js +20 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangeProxyCommon/__tests__/actions.test.js +0 -7
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/BulkChangePuppetEnvironmentModal.js +239 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/__tests__/BulkChangePuppetEnvironmentModal.test.js +155 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/__tests__/actions.test.js +49 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/__tests__/index.test.js +66 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/actions.js +37 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment/index.js +30 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkChangePuppetProxy/__tests__/index.test.js +160 -47
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemoveProxyCommon/__tests__/actions.test.js +0 -6
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetCAProxy/__tests__/index.test.js +136 -39
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/BulkRemovePuppetEnvironmentModal.js +148 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/__tests__/BulkRemovePuppetEnvironmentModal.test.js +80 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/__tests__/index.test.js +66 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment/index.js +30 -0
- data/webpack/src/Extends/Hosts/BulkActions/BulkRemovePuppetProxy/__tests__/index.test.js +123 -34
- data/webpack/src/Router/routes.fixtures.js +13 -0
- data/webpack/src/Router/routes.test.js +68 -8
- data/webpack/src/foreman_puppet_host_form.test.js +3 -1
- data/webpack/test_setup.js +1 -0
- metadata +14 -3
- data/webpack/src/Router/__snapshots__/routes.test.js.snap +0 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5aa351556f85774a9796437e9ee6fd0671f46db4bb3519aa6a94c1691c90d6ca
|
|
4
|
+
data.tar.gz: a9507d1ae1d1961d4256eba509e88e72f5ee1124d2d2532751f6f3ff7b2e2ac2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 31593435b997b9202741f97a709aa40bbd57ed82f6c09aeadbe8e83432d0273b0f2523aebe0a13cf03f3e534592418091f21da8eb768cad3dfc7f0a68c1c3277
|
|
7
|
+
data.tar.gz: 4625c5cfbefe7af792e45ffad193ca1f0867aac29ac3596c003072aec34c366d3ade137244a861802ddab8d75c45651343c76901d871bfd0b145509ea4a67df1
|
|
@@ -3,7 +3,9 @@ module ForemanPuppet
|
|
|
3
3
|
module V2
|
|
4
4
|
class HostsBulkActionsController < ::ForemanPuppet::Api::V2::PuppetBaseController
|
|
5
5
|
include ::Api::V2::BulkHostsExtension
|
|
6
|
-
before_action :find_editable_hosts, only: %i[change_puppet_proxy remove_puppet_proxy]
|
|
6
|
+
before_action :find_editable_hosts, only: %i[change_puppet_environment change_puppet_proxy remove_puppet_proxy]
|
|
7
|
+
before_action :find_environment, only: %i[change_puppet_environment]
|
|
8
|
+
before_action :validate_environment_taxonomies, only: %i[change_puppet_environment]
|
|
7
9
|
before_action :find_smart_proxy, only: %i[change_puppet_proxy]
|
|
8
10
|
|
|
9
11
|
def_param_group :bulk_params do
|
|
@@ -17,6 +19,27 @@ module ForemanPuppet
|
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
|
|
22
|
+
api :PUT, '/hosts/bulk/change_puppet_environment', N_('Change Puppet environment')
|
|
23
|
+
param_group :bulk_params
|
|
24
|
+
param :environment_id, String, required: false, desc: N_('ID of the Puppet environment to set for the selected hosts')
|
|
25
|
+
def change_puppet_environment
|
|
26
|
+
error_hosts = ::BulkHostsManager.new(hosts: @hosts).change_puppet_environment(resolved_environment)
|
|
27
|
+
|
|
28
|
+
process_bulk_response(
|
|
29
|
+
error_hosts,
|
|
30
|
+
success_message: format(n_(
|
|
31
|
+
'Updated host: changed environment',
|
|
32
|
+
'Updated hosts: changed environment',
|
|
33
|
+
@hosts.count
|
|
34
|
+
)),
|
|
35
|
+
error_message: format(n_(
|
|
36
|
+
'Failed to change environment for %{count} host',
|
|
37
|
+
'Failed to change environment for %{count} hosts',
|
|
38
|
+
error_hosts.count
|
|
39
|
+
), count: error_hosts.count)
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
20
43
|
api :PUT, '/hosts/bulk/change_puppet_proxy', N_('Change Puppet (CA) Proxy')
|
|
21
44
|
param_group :bulk_params
|
|
22
45
|
param :proxy_id, :number, required: true, desc: N_('ID of the Puppet proxy to reassign the hosts to')
|
|
@@ -65,6 +88,14 @@ module ForemanPuppet
|
|
|
65
88
|
end
|
|
66
89
|
|
|
67
90
|
def process_bulk_puppet_proxy_response(error_hosts, success_message:, error_message:)
|
|
91
|
+
process_bulk_response(
|
|
92
|
+
error_hosts,
|
|
93
|
+
success_message: success_message,
|
|
94
|
+
error_message: error_message
|
|
95
|
+
)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def process_bulk_response(error_hosts, success_message:, error_message:)
|
|
68
99
|
if error_hosts.empty?
|
|
69
100
|
process_response(true, { message: success_message })
|
|
70
101
|
else
|
|
@@ -93,6 +124,49 @@ module ForemanPuppet
|
|
|
93
124
|
Foreman::Cast.to_bool(params[:ca_proxy])
|
|
94
125
|
end
|
|
95
126
|
|
|
127
|
+
def find_environment
|
|
128
|
+
return true if environment_value == 'inherit' || environment_value.blank?
|
|
129
|
+
|
|
130
|
+
@environment = ForemanPuppet::Environment.find_by(id: environment_value)
|
|
131
|
+
return true if @environment.present?
|
|
132
|
+
|
|
133
|
+
render json: {
|
|
134
|
+
error: {
|
|
135
|
+
message: format(_('A Puppet environment with id %{id} could not be found.'), id: environment_value),
|
|
136
|
+
},
|
|
137
|
+
}, status: :unprocessable_entity
|
|
138
|
+
false
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def validate_environment_taxonomies
|
|
142
|
+
return true if resolved_environment.blank? || resolved_environment == 'inherit'
|
|
143
|
+
|
|
144
|
+
invalid_host_ids = @hosts.reject do |host|
|
|
145
|
+
ForemanPuppet::Environment.with_taxonomy_scope(host.organization, host.location)
|
|
146
|
+
.exists?(id: resolved_environment.id)
|
|
147
|
+
end.map(&:id)
|
|
148
|
+
|
|
149
|
+
return true if invalid_host_ids.empty?
|
|
150
|
+
|
|
151
|
+
render_error(:bulk_hosts_error, status: :unprocessable_entity,
|
|
152
|
+
locals: {
|
|
153
|
+
message: _('Selected Puppet environment is not assigned to the proper organization and/or location for all hosts.'),
|
|
154
|
+
failed_host_ids: invalid_host_ids,
|
|
155
|
+
})
|
|
156
|
+
false
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def environment_value
|
|
160
|
+
params[:environment_id]
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def resolved_environment
|
|
164
|
+
return 'inherit' if environment_value == 'inherit'
|
|
165
|
+
return nil if environment_value.blank?
|
|
166
|
+
|
|
167
|
+
@environment
|
|
168
|
+
end
|
|
169
|
+
|
|
96
170
|
def proxy_type
|
|
97
171
|
ca_proxy? ? _('Puppet CA proxy') : _('Puppet proxy')
|
|
98
172
|
end
|
|
@@ -3,6 +3,24 @@ module ForemanPuppet
|
|
|
3
3
|
module BulkHostsManager
|
|
4
4
|
extend ActiveSupport::Concern
|
|
5
5
|
|
|
6
|
+
def change_puppet_environment(environment)
|
|
7
|
+
error_hosts = []
|
|
8
|
+
@hosts.each do |host|
|
|
9
|
+
puppet = host.puppet || host.build_puppet
|
|
10
|
+
puppet.environment = if environment == 'inherit'
|
|
11
|
+
host.hostgroup&.puppet&.environment
|
|
12
|
+
else
|
|
13
|
+
environment
|
|
14
|
+
end
|
|
15
|
+
host.save(validate: false)
|
|
16
|
+
rescue StandardError => e
|
|
17
|
+
message = format(_('Failed to set Puppet environment for %{host}.'), host: host)
|
|
18
|
+
Foreman::Logging.exception(message, e)
|
|
19
|
+
error_hosts << host.id
|
|
20
|
+
end
|
|
21
|
+
error_hosts
|
|
22
|
+
end
|
|
23
|
+
|
|
6
24
|
def change_puppet_proxy(proxy, is_ca_proxy)
|
|
7
25
|
error_hosts = []
|
|
8
26
|
@hosts.each do |host|
|
data/config/api_routes.rb
CHANGED
|
@@ -4,6 +4,7 @@ Foreman::Application.routes.draw do
|
|
|
4
4
|
scope '(:apiv)', module: :v2, defaults: { apiv: 'v2' }, apiv: /v1|v2/, constraints: ApiConstraints.new(version: 2, default: true) do
|
|
5
5
|
match 'hosts/bulk/change_puppet_proxy', to: 'hosts_bulk_actions#change_puppet_proxy', via: [:put]
|
|
6
6
|
match 'hosts/bulk/remove_puppet_proxy', to: 'hosts_bulk_actions#remove_puppet_proxy', via: [:put]
|
|
7
|
+
match 'hosts/bulk/change_puppet_environment', to: 'hosts_bulk_actions#change_puppet_environment', via: [:put]
|
|
7
8
|
end
|
|
8
9
|
end
|
|
9
10
|
end
|
|
@@ -4,5 +4,5 @@ proxy_features = %w[Puppet]
|
|
|
4
4
|
|
|
5
5
|
proxy_features.each do |f_name|
|
|
6
6
|
f = Feature.where(name: f_name).first_or_create
|
|
7
|
-
raise "Unable to create proxy feature: #{format_errors
|
|
7
|
+
raise "Unable to create proxy feature: #{SeedHelper.format_errors(f)}" if f.nil? || f.errors.any?
|
|
8
8
|
end
|
|
@@ -62,6 +62,7 @@ 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_environment'
|
|
65
66
|
p.actions << 'foreman_puppet/api/v2/hosts_bulk_actions/change_puppet_proxy'
|
|
66
67
|
p.actions << 'foreman_puppet/api/v2/hosts_bulk_actions/remove_puppet_proxy'
|
|
67
68
|
end
|
|
@@ -16,8 +16,101 @@ module ForemanPuppet
|
|
|
16
16
|
organization: host.organization,
|
|
17
17
|
location: host.location)
|
|
18
18
|
end
|
|
19
|
+
let(:environment) { FactoryBot.create(:environment, organizations: [host.organization], locations: [host.location]) }
|
|
20
|
+
let(:hostgroup_environment) { FactoryBot.create(:environment, organizations: [host.organization], locations: [host.location]) }
|
|
21
|
+
let(:hostgroup) do
|
|
22
|
+
FactoryBot.create(:hostgroup, :with_puppet_enc,
|
|
23
|
+
environment: hostgroup_environment,
|
|
24
|
+
organizations: [host.organization],
|
|
25
|
+
locations: [host.location])
|
|
26
|
+
end
|
|
19
27
|
let(:proxy) { FactoryBot.create(:puppet_and_ca_smart_proxy, organizations: [host.organization], locations: [host.location]) }
|
|
20
28
|
|
|
29
|
+
def put_change_puppet_environment(params:, session: nil)
|
|
30
|
+
put :change_puppet_environment, params: params, session: session
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
test 'changes puppet environment for selected hosts' do
|
|
34
|
+
put_change_puppet_environment(params: bulk_params.merge(environment_id: environment.id))
|
|
35
|
+
|
|
36
|
+
assert_response :success
|
|
37
|
+
assert_equal environment.id, host2.reload.puppet.environment_id
|
|
38
|
+
assert_equal environment.id, host.reload.puppet.environment_id
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
test 'inherits puppet environment from hostgroups for selected hosts' do
|
|
42
|
+
host.update!(hostgroup: hostgroup)
|
|
43
|
+
host2.update!(hostgroup: hostgroup)
|
|
44
|
+
|
|
45
|
+
put_change_puppet_environment(params: bulk_params.merge(environment_id: 'inherit'))
|
|
46
|
+
|
|
47
|
+
assert_response :success
|
|
48
|
+
assert_equal hostgroup_environment.id, host2.reload.puppet.environment_id
|
|
49
|
+
assert_equal hostgroup_environment.id, host.reload.puppet.environment_id
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
test 'clears puppet environment for selected hosts' do
|
|
53
|
+
host.puppet.update!(environment: environment)
|
|
54
|
+
host2.puppet.update!(environment: environment)
|
|
55
|
+
|
|
56
|
+
put_change_puppet_environment(
|
|
57
|
+
params: bulk_params.merge(environment_id: nil),
|
|
58
|
+
session: set_session_user
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
assert_response :success
|
|
62
|
+
assert_nil host.reload.puppet.environment
|
|
63
|
+
assert_nil host2.reload.puppet.environment
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
test 'returns error when puppet environment is missing' do
|
|
67
|
+
missing_environment_id = 999_999
|
|
68
|
+
|
|
69
|
+
put_change_puppet_environment(
|
|
70
|
+
params: bulk_params.merge(environment_id: missing_environment_id),
|
|
71
|
+
session: set_session_user
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
assert_response :unprocessable_entity
|
|
75
|
+
response = JSON.parse(@response.body)
|
|
76
|
+
assert_equal "A Puppet environment with id #{missing_environment_id} could not be found.",
|
|
77
|
+
response.dig('error', 'message')
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
test 'returns error when changing puppet environment fails for some hosts' do
|
|
81
|
+
::BulkHostsManager.any_instance.expects(:change_puppet_environment)
|
|
82
|
+
.with(environment)
|
|
83
|
+
.returns([host2.id])
|
|
84
|
+
|
|
85
|
+
put_change_puppet_environment(
|
|
86
|
+
params: bulk_params.merge(environment_id: environment.id),
|
|
87
|
+
session: set_session_user
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
assert_response :unprocessable_entity
|
|
91
|
+
response = JSON.parse(@response.body)
|
|
92
|
+
assert_equal 'Failed to change environment for 1 host',
|
|
93
|
+
response.dig('error', 'message')
|
|
94
|
+
assert_equal [host2.id], response.dig('error', 'failed_host_ids')
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
test 'returns error when puppet environment is outside host taxonomies' do
|
|
98
|
+
invalid_environment = FactoryBot.create(:environment,
|
|
99
|
+
organizations: [host.organization],
|
|
100
|
+
locations: [FactoryBot.create(:location)])
|
|
101
|
+
|
|
102
|
+
put_change_puppet_environment(
|
|
103
|
+
params: bulk_params.merge(environment_id: invalid_environment.id),
|
|
104
|
+
session: set_session_user
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
assert_response :unprocessable_entity
|
|
108
|
+
response = JSON.parse(@response.body)
|
|
109
|
+
assert_equal 'Selected Puppet environment is not assigned to the proper organization and/or location for all hosts.',
|
|
110
|
+
response.dig('error', 'message')
|
|
111
|
+
assert_equal [host.id, host2.id].sort, response.dig('error', 'failed_host_ids').sort
|
|
112
|
+
end
|
|
113
|
+
|
|
21
114
|
test 'changes puppet proxy for selected hosts' do
|
|
22
115
|
put :change_puppet_proxy,
|
|
23
116
|
params: bulk_params.merge(proxy_id: proxy.id, ca_proxy: false)
|
|
@@ -4,6 +4,51 @@ class BulkHostsManagerTest < ActiveSupport::TestCase
|
|
|
4
4
|
let(:hosts) { FactoryBot.create_list(:host, 2, :with_puppet_enc) }
|
|
5
5
|
let(:manager) { ::BulkHostsManager.new(hosts: hosts) }
|
|
6
6
|
let(:proxy) { FactoryBot.create(:puppet_smart_proxy) }
|
|
7
|
+
let(:environment) { FactoryBot.create(:environment, organizations: [hosts.first.organization], locations: [hosts.first.location]) }
|
|
8
|
+
|
|
9
|
+
test 'changes puppet environment for hosts' do
|
|
10
|
+
manager.change_puppet_environment(environment)
|
|
11
|
+
|
|
12
|
+
hosts.each do |host|
|
|
13
|
+
assert_equal environment.id, host.reload.puppet.environment_id
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
test 'inherits puppet environment from hostgroup' do
|
|
18
|
+
organization = FactoryBot.create(:organization)
|
|
19
|
+
location = FactoryBot.create(:location)
|
|
20
|
+
inherited_environment = FactoryBot.create(:environment, organizations: [organization], locations: [location])
|
|
21
|
+
initial_environment = FactoryBot.create(:environment, organizations: [organization], locations: [location])
|
|
22
|
+
hostgroup = FactoryBot.create(:hostgroup, :with_puppet_enc,
|
|
23
|
+
environment: inherited_environment,
|
|
24
|
+
organizations: [organization],
|
|
25
|
+
locations: [location])
|
|
26
|
+
inherited_hosts = FactoryBot.create_list(:host, 2, :with_puppet_enc,
|
|
27
|
+
environment: initial_environment,
|
|
28
|
+
hostgroup: hostgroup,
|
|
29
|
+
organization: organization,
|
|
30
|
+
location: location)
|
|
31
|
+
|
|
32
|
+
inherited_hosts.each do |host|
|
|
33
|
+
assert_not_equal inherited_environment.id, host.reload.puppet.environment_id
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
::BulkHostsManager.new(hosts: inherited_hosts).change_puppet_environment('inherit')
|
|
37
|
+
|
|
38
|
+
inherited_hosts.each do |host|
|
|
39
|
+
assert_equal inherited_environment.id, host.reload.puppet.environment_id
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
test 'clears puppet environment when environment is nil' do
|
|
44
|
+
hosts.each { |host| host.puppet.update!(environment: environment) }
|
|
45
|
+
|
|
46
|
+
manager.change_puppet_environment(nil)
|
|
47
|
+
|
|
48
|
+
hosts.each do |host|
|
|
49
|
+
assert_nil host.reload.puppet.environment
|
|
50
|
+
end
|
|
51
|
+
end
|
|
7
52
|
|
|
8
53
|
test 'changes puppet proxy for hosts' do
|
|
9
54
|
manager.change_puppet_proxy(proxy, false)
|
|
@@ -6,5 +6,13 @@ export const API = {
|
|
|
6
6
|
patch: jest.fn(),
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
+
export const APIActions = {
|
|
10
|
+
get: jest.fn(),
|
|
11
|
+
post: jest.fn(),
|
|
12
|
+
put: jest.fn(),
|
|
13
|
+
patch: jest.fn(),
|
|
14
|
+
delete: jest.fn(),
|
|
15
|
+
};
|
|
16
|
+
|
|
9
17
|
export const get = data => ({ type: 'get-some-type', ...data });
|
|
10
18
|
export const post = data => ({ type: 'post-some-type', ...data });
|
data/webpack/global_index.js
CHANGED
|
@@ -7,12 +7,15 @@ import reducers from './src/reducers';
|
|
|
7
7
|
import { registerFills } from './src/Extends/Fills';
|
|
8
8
|
import { registerLegacy } from './legacy';
|
|
9
9
|
import HostsIndexActionsBar from './src/Extends/Hosts/ActionsBar';
|
|
10
|
+
import BulkChangePuppetEnvironment from './src/Extends/Hosts/BulkActions/BulkChangePuppetEnvironment';
|
|
11
|
+
import BulkRemovePuppetEnvironment from './src/Extends/Hosts/BulkActions/BulkRemovePuppetEnvironment';
|
|
10
12
|
import BulkChangePuppetProxy from './src/Extends/Hosts/BulkActions/BulkChangePuppetProxy';
|
|
11
13
|
import BulkChangePuppetCAProxy from './src/Extends/Hosts/BulkActions/BulkChangePuppetCAProxy';
|
|
12
14
|
import BulkRemovePuppetProxy from './src/Extends/Hosts/BulkActions/BulkRemovePuppetProxy';
|
|
13
15
|
import BulkRemovePuppetCAProxy from './src/Extends/Hosts/BulkActions/BulkRemovePuppetCAProxy';
|
|
14
16
|
|
|
15
17
|
const GLOBAL_FILL_PRIORITY = 100;
|
|
18
|
+
const PUPPET_ENV_COLUMN_WEIGHT = 2700;
|
|
16
19
|
|
|
17
20
|
// register reducers
|
|
18
21
|
registerReducer('puppet', reducers);
|
|
@@ -28,7 +31,7 @@ const puppetHostsIndexColumns = [
|
|
|
28
31
|
title: __('Puppet env'),
|
|
29
32
|
isSorted: true,
|
|
30
33
|
wrapper: hostDetails => hostDetails.environment_name,
|
|
31
|
-
weight:
|
|
34
|
+
weight: PUPPET_ENV_COLUMN_WEIGHT,
|
|
32
35
|
},
|
|
33
36
|
];
|
|
34
37
|
|
|
@@ -45,6 +48,20 @@ addGlobalFill(
|
|
|
45
48
|
GLOBAL_FILL_PRIORITY
|
|
46
49
|
);
|
|
47
50
|
|
|
51
|
+
addGlobalFill(
|
|
52
|
+
'_all-hosts-modals',
|
|
53
|
+
'BulkChangePuppetEnvironment',
|
|
54
|
+
<BulkChangePuppetEnvironment key="bulk-change-puppet-environment" />,
|
|
55
|
+
GLOBAL_FILL_PRIORITY
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
addGlobalFill(
|
|
59
|
+
'_all-hosts-modals',
|
|
60
|
+
'BulkRemovePuppetEnvironment',
|
|
61
|
+
<BulkRemovePuppetEnvironment key="bulk-remove-puppet-environment" />,
|
|
62
|
+
GLOBAL_FILL_PRIORITY
|
|
63
|
+
);
|
|
64
|
+
|
|
48
65
|
addGlobalFill(
|
|
49
66
|
'_all-hosts-modals',
|
|
50
67
|
'BulkChangePuppetProxy',
|
|
@@ -24,6 +24,26 @@ const HostActionsBar = () => {
|
|
|
24
24
|
<Menu ouiaId="content-flyout-menu" onSelect={() => setMenuOpen(false)}>
|
|
25
25
|
<MenuContent>
|
|
26
26
|
<MenuList>
|
|
27
|
+
<MenuItem
|
|
28
|
+
itemId="bulk-change-puppet-environment-menu-item"
|
|
29
|
+
key="bulk-change-puppet-environment-menu-item"
|
|
30
|
+
onClick={() =>
|
|
31
|
+
handleOpenBulkModal('bulk-change-puppet-environment')
|
|
32
|
+
}
|
|
33
|
+
isDisabled={selectedCount === 0}
|
|
34
|
+
>
|
|
35
|
+
{__('Change Puppet environment')}
|
|
36
|
+
</MenuItem>
|
|
37
|
+
<MenuItem
|
|
38
|
+
itemId="bulk-remove-puppet-environment-menu-item"
|
|
39
|
+
key="bulk-remove-puppet-environment-menu-item"
|
|
40
|
+
onClick={() =>
|
|
41
|
+
handleOpenBulkModal('bulk-remove-puppet-environment')
|
|
42
|
+
}
|
|
43
|
+
isDisabled={selectedCount === 0}
|
|
44
|
+
>
|
|
45
|
+
{__('Remove Puppet environment')}
|
|
46
|
+
</MenuItem>
|
|
27
47
|
<MenuItem
|
|
28
48
|
itemId="bulk-change-puppet-proxy-menu-item"
|
|
29
49
|
key="bulk-change-puppet-proxy-menu-item"
|
|
@@ -9,13 +9,6 @@ import {
|
|
|
9
9
|
BULK_CHANGE_PUPPET_PROXY_KEY,
|
|
10
10
|
} from '../actions';
|
|
11
11
|
|
|
12
|
-
jest.mock('foremanReact/redux/API', () => ({
|
|
13
|
-
APIActions: {
|
|
14
|
-
get: jest.fn(),
|
|
15
|
-
put: jest.fn(),
|
|
16
|
-
},
|
|
17
|
-
}));
|
|
18
|
-
|
|
19
12
|
describe('BulkChangeProxyCommon actions', () => {
|
|
20
13
|
const smartProxiesUrl = foremanUrl('/api/smart_proxies');
|
|
21
14
|
const bulkChangeUrl = foremanUrl('/api/v2/hosts/bulk/change_puppet_proxy');
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { FormattedMessage } from 'react-intl';
|
|
4
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
5
|
+
import {
|
|
6
|
+
Modal,
|
|
7
|
+
Button,
|
|
8
|
+
TextContent,
|
|
9
|
+
Text,
|
|
10
|
+
Select,
|
|
11
|
+
SelectOption,
|
|
12
|
+
SelectList,
|
|
13
|
+
MenuToggle,
|
|
14
|
+
} from '@patternfly/react-core';
|
|
15
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
|
16
|
+
import { addToast } from 'foremanReact/components/ToastsList/slice';
|
|
17
|
+
import { useForemanOrganization } from 'foremanReact/Root/Context/ForemanContext';
|
|
18
|
+
import {
|
|
19
|
+
selectAPIStatus,
|
|
20
|
+
selectAPIResponse,
|
|
21
|
+
} from 'foremanReact/redux/API/APISelectors';
|
|
22
|
+
import { STATUS } from 'foremanReact/constants';
|
|
23
|
+
import { bulkActionErrorToastParams } from '../toastHelpers';
|
|
24
|
+
import {
|
|
25
|
+
fetchEnvironments,
|
|
26
|
+
bulkChangePuppetEnvironment,
|
|
27
|
+
PUPPET_ENVIRONMENTS_KEY,
|
|
28
|
+
BULK_CHANGE_PUPPET_ENVIRONMENT_KEY,
|
|
29
|
+
INHERIT_ENVIRONMENT,
|
|
30
|
+
} from './actions';
|
|
31
|
+
|
|
32
|
+
const BulkChangePuppetEnvironmentModal = ({
|
|
33
|
+
isOpen,
|
|
34
|
+
closeModal,
|
|
35
|
+
selectAllHostsMode,
|
|
36
|
+
selectedCount,
|
|
37
|
+
fetchBulkParams,
|
|
38
|
+
onSuccess: onSuccessCallback,
|
|
39
|
+
}) => {
|
|
40
|
+
const dispatch = useDispatch();
|
|
41
|
+
const [environmentId, setEnvironmentId] = useState(null);
|
|
42
|
+
const [environmentSelectOpen, setEnvironmentSelectOpen] = useState(false);
|
|
43
|
+
const currentOrganization = useForemanOrganization();
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
dispatch(fetchEnvironments(currentOrganization?.id));
|
|
47
|
+
}, [dispatch, currentOrganization?.id]);
|
|
48
|
+
|
|
49
|
+
const environments = useSelector(state =>
|
|
50
|
+
selectAPIResponse(state, PUPPET_ENVIRONMENTS_KEY)
|
|
51
|
+
);
|
|
52
|
+
const environmentsStatus = useSelector(state =>
|
|
53
|
+
selectAPIStatus(state, PUPPET_ENVIRONMENTS_KEY)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const onToggleClick = () => {
|
|
57
|
+
setEnvironmentSelectOpen(!environmentSelectOpen);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const handleEnvironmentSelect = (event, selection) => {
|
|
61
|
+
setEnvironmentId(selection);
|
|
62
|
+
setEnvironmentSelectOpen(false);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const getEnvironmentLabel = value => {
|
|
66
|
+
if (value === INHERIT_ENVIRONMENT) return __('*Inherit from host group*');
|
|
67
|
+
|
|
68
|
+
const selectedEnvironment = environments?.results?.find(
|
|
69
|
+
environment => `${environment.id}` === value
|
|
70
|
+
);
|
|
71
|
+
return selectedEnvironment?.name || __('Select an Environment');
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const toggle = toggleRef => (
|
|
75
|
+
<MenuToggle
|
|
76
|
+
ouiaId="bulk-change-env-common-select-toggle"
|
|
77
|
+
ref={toggleRef}
|
|
78
|
+
onClick={onToggleClick}
|
|
79
|
+
isExpanded={environmentSelectOpen}
|
|
80
|
+
style={{ width: '500px' }}
|
|
81
|
+
>
|
|
82
|
+
{environmentId
|
|
83
|
+
? getEnvironmentLabel(environmentId)
|
|
84
|
+
: __('Select an Environment')}
|
|
85
|
+
</MenuToggle>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const handleModalClose = () => {
|
|
89
|
+
setEnvironmentId(null);
|
|
90
|
+
closeModal();
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const handleError = response => {
|
|
94
|
+
handleModalClose();
|
|
95
|
+
dispatch(
|
|
96
|
+
addToast(
|
|
97
|
+
bulkActionErrorToastParams(
|
|
98
|
+
response,
|
|
99
|
+
__('Failed to change Puppet Environment'),
|
|
100
|
+
BULK_CHANGE_PUPPET_ENVIRONMENT_KEY
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const handleSuccess = response => {
|
|
107
|
+
dispatch(
|
|
108
|
+
addToast({
|
|
109
|
+
type: 'success',
|
|
110
|
+
message: response.data.message,
|
|
111
|
+
})
|
|
112
|
+
);
|
|
113
|
+
try {
|
|
114
|
+
if (onSuccessCallback) onSuccessCallback();
|
|
115
|
+
} finally {
|
|
116
|
+
handleModalClose();
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const handleConfirm = () => {
|
|
121
|
+
const requestBody = {
|
|
122
|
+
included: {
|
|
123
|
+
search: fetchBulkParams(),
|
|
124
|
+
},
|
|
125
|
+
environment_id: environmentId,
|
|
126
|
+
organization_id: currentOrganization?.id,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
dispatch(
|
|
130
|
+
bulkChangePuppetEnvironment(requestBody, handleSuccess, handleError)
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const modalActions = [
|
|
135
|
+
<Button
|
|
136
|
+
key="add"
|
|
137
|
+
ouiaId="bulk-change-environment-modal-add-button"
|
|
138
|
+
variant="primary"
|
|
139
|
+
onClick={handleConfirm}
|
|
140
|
+
isDisabled={environmentId === null}
|
|
141
|
+
isLoading={environmentsStatus === STATUS.PENDING}
|
|
142
|
+
>
|
|
143
|
+
{__('Change Puppet Environment')}
|
|
144
|
+
</Button>,
|
|
145
|
+
<Button
|
|
146
|
+
key="cancel"
|
|
147
|
+
ouiaId="bulk-change-environment-modal-cancel-button"
|
|
148
|
+
variant="link"
|
|
149
|
+
onClick={handleModalClose}
|
|
150
|
+
>
|
|
151
|
+
{__('Cancel')}
|
|
152
|
+
</Button>,
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<Modal
|
|
157
|
+
isOpen={isOpen}
|
|
158
|
+
onClose={handleModalClose}
|
|
159
|
+
onEscapePress={handleModalClose}
|
|
160
|
+
title={__('Change Puppet Environment')}
|
|
161
|
+
width="50%"
|
|
162
|
+
position="top"
|
|
163
|
+
actions={modalActions}
|
|
164
|
+
id="bulk-change-puppet-environment"
|
|
165
|
+
key="bulk-change-puppet-environment"
|
|
166
|
+
ouiaId="bulk-change-puppet-environment"
|
|
167
|
+
>
|
|
168
|
+
<TextContent>
|
|
169
|
+
<Text ouiaId="bulk-change-puppet-environment-options">
|
|
170
|
+
{selectAllHostsMode ? (
|
|
171
|
+
<FormattedMessage
|
|
172
|
+
id="bulk-change-puppet-environment-warning-message-all"
|
|
173
|
+
defaultMessage={__(
|
|
174
|
+
'Changing the Puppet environment will affect {boldCount} selected hosts. Some hosts may already have been associated with the selected environment.'
|
|
175
|
+
)}
|
|
176
|
+
values={{
|
|
177
|
+
boldCount: <strong>{__('All')}</strong>,
|
|
178
|
+
}}
|
|
179
|
+
/>
|
|
180
|
+
) : (
|
|
181
|
+
<FormattedMessage
|
|
182
|
+
id="bulk-change-puppet-environment-warning-message"
|
|
183
|
+
defaultMessage={__(
|
|
184
|
+
'Changing the Puppet environment will affect {boldCount} selected {count, plural, one {host} other {hosts}}. Some hosts may already have been associated with the selected environment.'
|
|
185
|
+
)}
|
|
186
|
+
values={{
|
|
187
|
+
count: selectedCount,
|
|
188
|
+
boldCount: <strong>{selectedCount}</strong>,
|
|
189
|
+
}}
|
|
190
|
+
/>
|
|
191
|
+
)}
|
|
192
|
+
</Text>
|
|
193
|
+
</TextContent>
|
|
194
|
+
{environmentsStatus === STATUS.RESOLVED && (
|
|
195
|
+
<Select
|
|
196
|
+
id="bulk-change-puppet-environment-select"
|
|
197
|
+
isOpen={environmentSelectOpen}
|
|
198
|
+
selected={environmentId}
|
|
199
|
+
onSelect={handleEnvironmentSelect}
|
|
200
|
+
onOpenChange={isSelectOpen => setEnvironmentSelectOpen(isSelectOpen)}
|
|
201
|
+
toggle={toggle}
|
|
202
|
+
shouldFocusToggleOnSelect
|
|
203
|
+
ouiaId="bulk-change-puppet-environment-select"
|
|
204
|
+
>
|
|
205
|
+
<SelectList>
|
|
206
|
+
<SelectOption value={INHERIT_ENVIRONMENT}>
|
|
207
|
+
{__('*Inherit from host group*')}
|
|
208
|
+
</SelectOption>
|
|
209
|
+
{environments?.results?.map(environment => (
|
|
210
|
+
<SelectOption
|
|
211
|
+
key={`${environment.id}`}
|
|
212
|
+
value={`${environment.id}`}
|
|
213
|
+
>
|
|
214
|
+
{environment.name}
|
|
215
|
+
</SelectOption>
|
|
216
|
+
))}
|
|
217
|
+
</SelectList>
|
|
218
|
+
</Select>
|
|
219
|
+
)}
|
|
220
|
+
</Modal>
|
|
221
|
+
);
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
BulkChangePuppetEnvironmentModal.propTypes = {
|
|
225
|
+
isOpen: PropTypes.bool,
|
|
226
|
+
closeModal: PropTypes.func,
|
|
227
|
+
fetchBulkParams: PropTypes.func.isRequired,
|
|
228
|
+
onSuccess: PropTypes.func,
|
|
229
|
+
selectedCount: PropTypes.number.isRequired,
|
|
230
|
+
selectAllHostsMode: PropTypes.bool.isRequired,
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
BulkChangePuppetEnvironmentModal.defaultProps = {
|
|
234
|
+
isOpen: false,
|
|
235
|
+
closeModal: () => {},
|
|
236
|
+
onSuccess: undefined,
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
export default BulkChangePuppetEnvironmentModal;
|