foreman_discovery 16.3.6 → 17.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/api/v2/discovered_hosts_controller.rb +1 -0
- data/app/controllers/discovered_hosts_controller.rb +24 -35
- data/app/controllers/discovery_rules_controller.rb +12 -1
- data/app/helpers/discovered_hosts_helper.rb +1 -1
- data/app/helpers/discovery_rules_helper.rb +1 -0
- data/app/models/discovery_rule.rb +10 -5
- data/app/services/foreman_discovery/fact_to_category_resolver.rb +106 -0
- data/app/services/foreman_discovery/ui_notifications/failed_discovery.rb +34 -0
- data/app/services/foreman_discovery/ui_notifications/new_host.rb +2 -1
- data/app/views/discovered_hosts/_discovered_hosts_list.html.erb +44 -40
- data/app/views/discovery_rules/clone.erb +3 -0
- data/app/views/discovery_rules/index.html.erb +4 -0
- data/app/views/discovery_rules/welcome.html.erb +15 -0
- data/app/views/foreman_discovery/debian_kexec.erb +1 -1
- data/app/views/foreman_discovery/redhat_kexec.erb +1 -1
- data/config/routes.rb +2 -0
- data/db/seeds.d/80_discovery_ui_notification.rb +11 -5
- data/lib/foreman_discovery/engine.rb +3 -7
- data/lib/foreman_discovery/version.rb +1 -1
- data/locale/ca/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ca/foreman_discovery.po +36 -9
- data/locale/de/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/de/foreman_discovery.po +45 -18
- data/locale/en/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/en/foreman_discovery.po +31 -4
- data/locale/en_GB/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/en_GB/foreman_discovery.po +36 -9
- data/locale/es/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/es/foreman_discovery.po +70 -41
- data/locale/foreman_discovery.pot +142 -97
- data/locale/fr/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/fr/foreman_discovery.po +76 -49
- data/locale/gl/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/gl/foreman_discovery.po +32 -5
- data/locale/it/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/it/foreman_discovery.po +44 -17
- data/locale/ja/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ja/foreman_discovery.po +79 -54
- data/locale/ko/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ko/foreman_discovery.po +43 -16
- data/locale/pt_BR/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/pt_BR/foreman_discovery.po +69 -39
- data/locale/ru/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ru/foreman_discovery.po +43 -16
- data/locale/sv_SE/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/sv_SE/foreman_discovery.po +34 -7
- data/locale/zh_CN/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/zh_CN/foreman_discovery.po +114 -90
- data/locale/zh_TW/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/zh_TW/foreman_discovery.po +43 -16
- data/package.json +6 -6
- data/test/functional/api/v2/discovered_hosts_controller_test.rb +9 -0
- data/test/functional/discovery_rules_controller_test.rb +6 -1
- data/test/integration/discovered_hosts_test.rb +53 -5
- data/test/test_helper_discovery.rb +5 -0
- data/test/unit/discovery_rule_test.rb +24 -2
- data/test/unit/fact_to_category_resolver_test.rb +41 -0
- data/test/unit/ui_notifications/destroy_host_test.rb +2 -9
- data/test/unit/ui_notifications/new_host_test.rb +3 -3
- data/webpack/__mocks__/foremanReact/common/I18n.js +3 -0
- data/webpack/__mocks__/foremanReact/common/helpers.js +1 -0
- data/webpack/__mocks__/foremanReact/common/index.js +5 -0
- data/webpack/__mocks__/foremanReact/components/common/EmptyState/DefaultEmptyState.js +69 -0
- data/webpack/__mocks__/foremanReact/components/common/EmptyState/EmptyStatePattern.js +77 -0
- data/webpack/__mocks__/foremanReact/components/common/EmptyState/EmptyStatePropTypes.js +29 -0
- data/webpack/__mocks__/foremanReact/components/common/EmptyState/index.js +5 -0
- data/webpack/index.js +9 -8
- data/webpack/src/ForemanDiscovery/DiscoveredHosts/Components/EmptyState/EmptyState.js +7 -7
- data/webpack/src/ForemanDiscovery/DiscoveredHosts/Components/EmptyState/__test__/EmptyState.test.js +12 -0
- data/webpack/src/ForemanDiscovery/DiscoveredHosts/Components/EmptyState/__test__/__snapshots__/EmptyState.test.js.snap +16 -0
- data/webpack/src/ForemanDiscovery/DiscoveredHosts/Components/EmptyState/index.js +1 -1
- data/webpack/src/ForemanDiscovery/DiscoveredHosts/index.js +3 -3
- data/webpack/src/ForemanDiscovery/DiscoveryRules/Components/EmptyState/EmptyState.js +34 -0
- data/webpack/src/ForemanDiscovery/DiscoveryRules/Components/EmptyState/index.js +1 -0
- data/webpack/src/ForemanDiscovery/DiscoveryRules/Components/__test__/EmptyState.test.js +19 -0
- data/webpack/src/ForemanDiscovery/DiscoveryRules/Components/__test__/__snapshots__/EmptyState.test.js.snap +22 -0
- data/webpack/src/ForemanDiscovery/DiscoveryRules/index.js +6 -0
- data/webpack/src/reducers.js +0 -2
- metadata +25 -3
@@ -5,9 +5,9 @@
|
|
5
5
|
# Translators:
|
6
6
|
msgid ""
|
7
7
|
msgstr ""
|
8
|
-
"Project-Id-Version: foreman_discovery 16.
|
8
|
+
"Project-Id-Version: foreman_discovery 16.3.4\n"
|
9
9
|
"Report-Msgid-Bugs-To: \n"
|
10
|
-
"PO-Revision-Date:
|
10
|
+
"PO-Revision-Date: 2021-01-25 08:35+0000\n"
|
11
11
|
"Last-Translator: Transifex Bot <>\n"
|
12
12
|
"Language-Team: Chinese (Taiwan) (http://www.transifex.com/foreman/foreman/lang"
|
13
13
|
"uage/zh_TW/)\n"
|
@@ -20,9 +20,6 @@ msgstr ""
|
|
20
20
|
msgid "%s - The following hosts are about to be changed"
|
21
21
|
msgstr "%s - 以下主機即將受到更改"
|
22
22
|
|
23
|
-
msgid "%s ago"
|
24
|
-
msgstr "%s 之前"
|
25
|
-
|
26
23
|
msgid "%s discovered hosts were provisioned"
|
27
24
|
msgstr ""
|
28
25
|
|
@@ -33,7 +30,7 @@ msgid "A summary of discovered hosts"
|
|
33
30
|
msgstr ""
|
34
31
|
|
35
32
|
msgid "Action with sub plans"
|
36
|
-
msgstr ""
|
33
|
+
msgstr "有子計畫的動作"
|
37
34
|
|
38
35
|
msgid "Actions"
|
39
36
|
msgstr "動作"
|
@@ -80,6 +77,12 @@ msgstr ""
|
|
80
77
|
msgid "Clean all reported facts during provisioning (except discovery facts)"
|
81
78
|
msgstr ""
|
82
79
|
|
80
|
+
msgid "Clone"
|
81
|
+
msgstr ""
|
82
|
+
|
83
|
+
msgid "Clone %s"
|
84
|
+
msgstr ""
|
85
|
+
|
83
86
|
msgid "Collapse All"
|
84
87
|
msgstr "全部收回"
|
85
88
|
|
@@ -145,9 +148,15 @@ msgstr[1] ""
|
|
145
148
|
msgid "Discovered Hosts"
|
146
149
|
msgstr ""
|
147
150
|
|
151
|
+
msgid "Discovered Rules"
|
152
|
+
msgstr ""
|
153
|
+
|
148
154
|
msgid "Discovered host '%{host}' has all NICs filtered out, filter: %{filter}"
|
149
155
|
msgstr ""
|
150
156
|
|
157
|
+
msgid "Discovered host reported from unknown subnet, communication will not be proxied."
|
158
|
+
msgstr ""
|
159
|
+
|
151
160
|
msgid "Discovered host: %s"
|
152
161
|
msgstr "發現的主機:%s"
|
153
162
|
|
@@ -160,6 +169,9 @@ msgstr ""
|
|
160
169
|
msgid "Discovered hosts from Foreman server at %{foreman_url}"
|
161
170
|
msgstr ""
|
162
171
|
|
172
|
+
msgid "Discovered hosts reported from unknown subnet are %s, communication will not be proxied."
|
173
|
+
msgstr ""
|
174
|
+
|
163
175
|
msgid "Discovered hosts summary"
|
164
176
|
msgstr ""
|
165
177
|
|
@@ -226,6 +238,9 @@ msgstr "啟用"
|
|
226
238
|
msgid "Enable rule '%s'?"
|
227
239
|
msgstr ""
|
228
240
|
|
241
|
+
msgid "Error message goes here"
|
242
|
+
msgstr ""
|
243
|
+
|
229
244
|
msgid "Error on existing NIC"
|
230
245
|
msgstr ""
|
231
246
|
|
@@ -280,6 +295,9 @@ msgstr "刷新 %s 的詳情失敗"
|
|
280
295
|
msgid "Failed to refresh facts for %{hostname} with error %{error_message}"
|
281
296
|
msgstr ""
|
282
297
|
|
298
|
+
msgid "For more information please see "
|
299
|
+
msgstr ""
|
300
|
+
|
283
301
|
msgid "Force DNS"
|
284
302
|
msgstr ""
|
285
303
|
|
@@ -304,6 +322,9 @@ msgstr ""
|
|
304
322
|
msgid "Host"
|
305
323
|
msgstr "主機"
|
306
324
|
|
325
|
+
msgid "Host %s has been dicovered"
|
326
|
+
msgstr ""
|
327
|
+
|
307
328
|
msgid "Host %{host} was provisioned with rule %{rule}"
|
308
329
|
msgstr ""
|
309
330
|
|
@@ -324,10 +345,10 @@ msgid "Host of type %s can not be rebooted"
|
|
324
345
|
msgstr ""
|
325
346
|
|
326
347
|
msgid "Host's owner type"
|
327
|
-
msgstr ""
|
348
|
+
msgstr "主機的擁有者類型"
|
328
349
|
|
329
350
|
msgid "Host's parameters (array or indexed hash)"
|
330
|
-
msgstr ""
|
351
|
+
msgstr "主機參數(陣列或索引過的雜湊)"
|
331
352
|
|
332
353
|
msgid "Hostname facts"
|
333
354
|
msgstr ""
|
@@ -378,10 +399,10 @@ msgid "Image API returned HTTP/%{code} with '%{body}"
|
|
378
399
|
msgstr ""
|
379
400
|
|
380
401
|
msgid "Import Puppet classes"
|
381
|
-
msgstr ""
|
402
|
+
msgstr "匯入 Puppet 類別"
|
382
403
|
|
383
404
|
msgid "Import facts"
|
384
|
-
msgstr ""
|
405
|
+
msgstr "匯入詳情"
|
385
406
|
|
386
407
|
msgid "In addition to @host attribute function rand for random integers is available. Examples:"
|
387
408
|
msgstr ""
|
@@ -471,7 +492,7 @@ msgid "Name"
|
|
471
492
|
msgstr "名稱"
|
472
493
|
|
473
494
|
msgid "Name of the parameter"
|
474
|
-
msgstr ""
|
495
|
+
msgstr "參數名稱"
|
475
496
|
|
476
497
|
msgid "Network"
|
477
498
|
msgstr "網路"
|
@@ -482,6 +503,9 @@ msgstr ""
|
|
482
503
|
msgid "New Discovery Rule"
|
483
504
|
msgstr ""
|
484
505
|
|
506
|
+
msgid "New hosts"
|
507
|
+
msgstr ""
|
508
|
+
|
485
509
|
msgid "New in the last 24 hours"
|
486
510
|
msgstr ""
|
487
511
|
|
@@ -534,7 +558,7 @@ msgid "PXELinux template to be used when pinning a host to discovery"
|
|
534
558
|
msgstr ""
|
535
559
|
|
536
560
|
msgid "Parameter value"
|
537
|
-
msgstr ""
|
561
|
+
msgstr "參數值"
|
538
562
|
|
539
563
|
msgid "Please Confirm"
|
540
564
|
msgstr "請確認"
|
@@ -600,7 +624,7 @@ msgid "Reloading kernel on %s"
|
|
600
624
|
msgstr ""
|
601
625
|
|
602
626
|
msgid "Remote action:"
|
603
|
-
msgstr ""
|
627
|
+
msgstr "遠端動作:"
|
604
628
|
|
605
629
|
msgid "Reported in the last 7 days"
|
606
630
|
msgstr ""
|
@@ -728,6 +752,9 @@ msgstr ""
|
|
728
752
|
msgid "defines a pattern to assign human-readable hostnames to the matching hosts"
|
729
753
|
msgstr ""
|
730
754
|
|
755
|
+
msgid "documentation"
|
756
|
+
msgstr ""
|
757
|
+
|
731
758
|
msgid "enables to limit maximum amount of provisioned hosts per rule"
|
732
759
|
msgstr ""
|
733
760
|
|
@@ -777,13 +804,13 @@ msgid "represents rule name shown to the users"
|
|
777
804
|
msgstr ""
|
778
805
|
|
779
806
|
msgid "required if host is managed and custom partition has not been defined"
|
780
|
-
msgstr ""
|
807
|
+
msgstr "若主機是個受管理的主機,並且尚未定義自訂分割區的話便需要"
|
781
808
|
|
782
809
|
msgid "required if host is managed and value is not inherited from host group"
|
783
|
-
msgstr ""
|
810
|
+
msgstr "若主機是個受管理的主機,並且值不是由主機群組所繼承的話便需要"
|
784
811
|
|
785
812
|
msgid "required if not imaged based provisioning and host is managed and value is not inherited from host group"
|
786
|
-
msgstr ""
|
813
|
+
msgstr "若不是基於映像檔的佈建,而主機受管理並且值並非由主機群組所繼承的話便需要"
|
787
814
|
|
788
815
|
msgid "required if value is not inherited from host group or default password in settings"
|
789
816
|
msgstr ""
|
data/package.json
CHANGED
@@ -21,15 +21,15 @@
|
|
21
21
|
"url": "http://projects.theforeman.org/projects/foreman_discovery/issues"
|
22
22
|
},
|
23
23
|
"peerDependencies": {
|
24
|
-
"@theforeman/vendor": "
|
24
|
+
"@theforeman/vendor": "^6.0.0"
|
25
25
|
},
|
26
26
|
"devDependencies": {
|
27
27
|
"@babel/core": "^7.7.0",
|
28
|
-
"@theforeman/builder": "^
|
29
|
-
"@theforeman/eslint-plugin-foreman": "
|
30
|
-
"@theforeman/stories": "^
|
31
|
-
"@theforeman/test": "^
|
32
|
-
"@theforeman/vendor-dev": "^
|
28
|
+
"@theforeman/builder": "^6.0.0",
|
29
|
+
"@theforeman/eslint-plugin-foreman": "^6.0.0",
|
30
|
+
"@theforeman/stories": "^7.0.0",
|
31
|
+
"@theforeman/test": "^8.0.0",
|
32
|
+
"@theforeman/vendor-dev": "^6.0.0",
|
33
33
|
"babel-eslint": "^10.0.3",
|
34
34
|
"eslint": "^6.7.2",
|
35
35
|
"prettier": "^1.19.1",
|
@@ -4,6 +4,8 @@ class Api::V2::DiscoveredHostsControllerTest < ActionController::TestCase
|
|
4
4
|
include FactImporterIsolation
|
5
5
|
allow_transactions_for_any_importer
|
6
6
|
|
7
|
+
alias_method :blueprint, :failed_discovery_blueprint
|
8
|
+
|
7
9
|
def switch_controller(klass)
|
8
10
|
old_controller = @controller
|
9
11
|
@controller = klass.new
|
@@ -26,6 +28,8 @@ class Api::V2::DiscoveredHostsControllerTest < ActionController::TestCase
|
|
26
28
|
set_default_settings
|
27
29
|
::ForemanDiscovery::NodeAPI::PowerService.any_instance.stubs(:reboot).returns(true)
|
28
30
|
::ForemanDiscovery::HostConverter.stubs(:unused_ip_for_host)
|
31
|
+
|
32
|
+
assert blueprint
|
29
33
|
end
|
30
34
|
|
31
35
|
def test_get_index
|
@@ -206,4 +210,9 @@ class Api::V2::DiscoveredHostsControllerTest < ActionController::TestCase
|
|
206
210
|
assert_response :success
|
207
211
|
end
|
208
212
|
|
213
|
+
def test_failed_discovery_notification
|
214
|
+
bad_facts = { this_is: 'bad' }
|
215
|
+
post :facts, params: { facts: bad_facts }
|
216
|
+
assert_equal 1, Notification.all.count
|
217
|
+
end
|
209
218
|
end
|
@@ -12,7 +12,6 @@ class DiscoveryRulesControllerTest < ActionController::TestCase
|
|
12
12
|
test "reader role should get index" do
|
13
13
|
get :index, params: {}, session: set_session_user_default_reader
|
14
14
|
assert_response :success
|
15
|
-
assert_not_nil assigns(:discovery_rules)
|
16
15
|
end
|
17
16
|
|
18
17
|
test "should get new" do
|
@@ -72,6 +71,12 @@ class DiscoveryRulesControllerTest < ActionController::TestCase
|
|
72
71
|
assert_redirected_to discovery_rules_path
|
73
72
|
end
|
74
73
|
|
74
|
+
test 'clone' do
|
75
|
+
rule = FactoryBot.create(:discovery_rule)
|
76
|
+
get :clone, params: { :id => rule.id }, session: set_session_user
|
77
|
+
assert_template 'clone'
|
78
|
+
end
|
79
|
+
|
75
80
|
private
|
76
81
|
|
77
82
|
def initialize_host
|
@@ -3,6 +3,7 @@ require 'integration_test_helper'
|
|
3
3
|
|
4
4
|
class DiscoveredHostsTest < IntegrationTestWithJavascript
|
5
5
|
let(:discovered_host) { FactoryBot.create(:discovered_host, :with_facts) }
|
6
|
+
let(:subnet) { FactoryBot.create(:subnet_ipv4, :network => "192.168.100.0") }
|
6
7
|
let(:discovered_hosts) { Host::Discovered.all }
|
7
8
|
|
8
9
|
setup do
|
@@ -17,8 +18,9 @@ class DiscoveredHostsTest < IntegrationTestWithJavascript
|
|
17
18
|
Host::Discovered.destroy_all
|
18
19
|
end
|
19
20
|
|
20
|
-
describe '
|
21
|
-
test 'triggers reboot on
|
21
|
+
describe 'Perform host Reboot' do
|
22
|
+
test 'triggers reboot on a single discovered_host' do
|
23
|
+
Host::Discovered.any_instance.stubs(:subnet).returns(subnet)
|
22
24
|
Host::Discovered.any_instance
|
23
25
|
.expects(:reboot)
|
24
26
|
.at_least(discovered_hosts.count)
|
@@ -29,24 +31,70 @@ class DiscoveredHostsTest < IntegrationTestWithJavascript
|
|
29
31
|
assert page.has_text?('The following hosts are about to be changed')
|
30
32
|
page.find_button('Submit').click
|
31
33
|
end
|
34
|
+
|
35
|
+
test 'triggers reboot on all discovered_hosts' do
|
36
|
+
Host::Discovered.any_instance.stubs(:subnet).returns(subnet)
|
37
|
+
Host::Discovered.any_instance
|
38
|
+
.expects(:reboot)
|
39
|
+
.at_least(discovered_hosts.count)
|
40
|
+
select_all_hosts
|
41
|
+
page.find_link('Select Action').click
|
42
|
+
page.find_link('Reboot').click
|
43
|
+
wait_for_ajax
|
44
|
+
assert page.has_text?('The following hosts are about to be changed')
|
45
|
+
page.find_button('Submit').click
|
46
|
+
end
|
47
|
+
|
48
|
+
test 'shows warning for all hosts with missing subnet' do
|
49
|
+
select_all_hosts
|
50
|
+
page.find_link('Select Action').click
|
51
|
+
page.find_link('Auto Provision').click
|
52
|
+
wait_for_ajax
|
53
|
+
assert page.has_text?('The following hosts are about to be changed')
|
54
|
+
page.find_button('Submit').click
|
55
|
+
wait_for_ajax
|
56
|
+
assert page.has_text?("Discovered hosts reported from unknown subnet")
|
57
|
+
end
|
32
58
|
end
|
33
59
|
|
34
|
-
describe '
|
35
|
-
test 'converts
|
60
|
+
describe 'Perform host Autoprovision' do
|
61
|
+
test 'converts single discovered to managed host' do
|
62
|
+
Host::Discovered.any_instance.stubs(:subnet).returns(subnet)
|
36
63
|
select_host_checkbox(discovered_host.id)
|
37
64
|
page.find_link('Select Action').click
|
38
65
|
page.find_link('Auto Provision').click
|
39
66
|
wait_for_ajax
|
40
67
|
assert page.has_text?('The following hosts are about to be changed')
|
41
68
|
page.find_button('Submit').click
|
69
|
+
end
|
70
|
+
|
71
|
+
test 'converts all discovered to managed hosts' do
|
72
|
+
Host::Discovered.any_instance.stubs(:subnet).returns(subnet)
|
73
|
+
select_all_hosts
|
74
|
+
page.find_link('Select Action').click
|
75
|
+
page.find_link('Auto Provision').click
|
76
|
+
wait_for_ajax
|
77
|
+
assert page.has_text?('The following hosts are about to be changed')
|
78
|
+
page.find_button('Submit').click
|
42
79
|
wait_for_ajax
|
43
80
|
assert page.has_text?('Discovered hosts are provisioning now')
|
44
81
|
end
|
82
|
+
|
83
|
+
test 'shows warning for all hosts with missing subnet' do
|
84
|
+
select_all_hosts
|
85
|
+
page.find_link('Select Action').click
|
86
|
+
page.find_link('Auto Provision').click
|
87
|
+
wait_for_ajax
|
88
|
+
assert page.has_text?('The following hosts are about to be changed')
|
89
|
+
page.find_button('Submit').click
|
90
|
+
wait_for_ajax
|
91
|
+
assert page.has_text?("Discovered hosts reported from unknown subnet")
|
92
|
+
end
|
45
93
|
end
|
46
94
|
|
47
95
|
describe 'Delete hosts' do
|
48
96
|
test 'it removes all hosts' do
|
49
|
-
|
97
|
+
select_all_hosts
|
50
98
|
page.find_link('Select Action').click
|
51
99
|
page.find_link('Delete').click
|
52
100
|
wait_for_ajax
|
@@ -172,6 +172,11 @@ def discovered_notification_blueprint
|
|
172
172
|
name: 'new_discovered_host')
|
173
173
|
end
|
174
174
|
|
175
|
+
def failed_discovery_blueprint
|
176
|
+
@blueprint ||= FactoryBot.create(:notification_blueprint,
|
177
|
+
name: 'failed_discovery')
|
178
|
+
end
|
179
|
+
|
175
180
|
def parse_json_fixture(filename, remove_root_element = false)
|
176
181
|
raw = JSON.parse(File.read(File.expand_path(File.dirname(__FILE__) + "/facts/#{filename}.json")))
|
177
182
|
remove_root_element ? raw['facts'] : raw
|
@@ -155,7 +155,7 @@ class DiscoveryRuleTest < ActiveSupport::TestCase
|
|
155
155
|
:search => "cpu_count > 1",
|
156
156
|
:hostgroup_id => @hostgroup.id
|
157
157
|
refute_valid rule
|
158
|
-
assert_equal "Host group organization #{organization_one.name} must also be associated to the discovery rule", rule.errors[:
|
158
|
+
assert_equal "Host group organization #{organization_one.name} must also be associated to the discovery rule", rule.errors[:base].first
|
159
159
|
end
|
160
160
|
|
161
161
|
test "should enforce hostgroup organizations and locations" do
|
@@ -168,7 +168,7 @@ class DiscoveryRuleTest < ActiveSupport::TestCase
|
|
168
168
|
:organization_ids => [organization_one.id],
|
169
169
|
:location_ids => [location_one.id]
|
170
170
|
refute_valid rule
|
171
|
-
assert_equal "Host group location #{loc.name} must also be associated to the discovery rule", rule.errors[:
|
171
|
+
assert_equal "Host group location #{loc.name} must also be associated to the discovery rule", rule.errors[:base].first
|
172
172
|
end
|
173
173
|
|
174
174
|
context 'auditing related to discovery rule' do
|
@@ -218,4 +218,26 @@ class DiscoveryRuleTest < ActiveSupport::TestCase
|
|
218
218
|
assert_equal DiscoveryRule::STEP, second_new.priority - first_new.priority
|
219
219
|
end
|
220
220
|
end
|
221
|
+
|
222
|
+
context 'suggest next priority' do
|
223
|
+
setup do
|
224
|
+
@organization = FactoryBot.create(:organization)
|
225
|
+
@location = FactoryBot.create(:location)
|
226
|
+
end
|
227
|
+
|
228
|
+
test 'when there exists a discovery_rule of the given organization' do
|
229
|
+
hostgroup = FactoryBot.create(:hostgroup, organizations: [@organization], locations: [@location] )
|
230
|
+
discovery_rule = FactoryBot.create(:discovery_rule,
|
231
|
+
priority: rand(100),
|
232
|
+
hostgroup: hostgroup,
|
233
|
+
organizations: [@organization],
|
234
|
+
locations: [@location])
|
235
|
+
|
236
|
+
assert_equal DiscoveryRule.suggest_priority(@organization), (discovery_rule.priority + DiscoveryRule::STEP)
|
237
|
+
end
|
238
|
+
|
239
|
+
test 'when there is no discovery_rule of the given organization' do
|
240
|
+
assert_equal DiscoveryRule.suggest_priority(@organization), DiscoveryRule::STEP
|
241
|
+
end
|
242
|
+
end
|
221
243
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative '../test_plugin_helper'
|
2
|
+
|
3
|
+
class FactToCategoryResolverTest < ActiveSupport::TestCase
|
4
|
+
class FakePrimaryInterface < OpenStruct
|
5
|
+
def subnet
|
6
|
+
nil
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
setup do
|
11
|
+
interfaces = [{
|
12
|
+
identifier: 'eth0',
|
13
|
+
mac: 'aa:bb:cc:dd:ee:f1',
|
14
|
+
ip: '192.168.1.1',
|
15
|
+
}.with_indifferent_access]
|
16
|
+
facts = {
|
17
|
+
:macaddress_eth0 => 'aa:bb:cc:dd:ee:f1',
|
18
|
+
:ipaddress_eth0 => '192.168.1.1',
|
19
|
+
manufacturer: 'TEST-Creator',
|
20
|
+
hardwaremodel: 'TEST_X64',
|
21
|
+
bios_vendor: 'TEST_BIOS',
|
22
|
+
}.with_indifferent_access
|
23
|
+
|
24
|
+
@host = Host::Discovered.new(name: 'dummy')
|
25
|
+
@host.stubs(:facts_hash).returns(facts)
|
26
|
+
@host.stubs(:interfaces).returns(interfaces)
|
27
|
+
@host.stubs(:primary_interface).returns(FakePrimaryInterface.new)
|
28
|
+
@resolver = ForemanDiscovery::FactToCategoryResolver.new(@host)
|
29
|
+
end
|
30
|
+
|
31
|
+
test 'resolve facts to right category' do
|
32
|
+
categories = @resolver.categories
|
33
|
+
hardware_category = categories[2]
|
34
|
+
network_category = categories[3]
|
35
|
+
software_category = categories[4]
|
36
|
+
|
37
|
+
assert_equal hardware_category['hardwaremodel'], 'TEST_X64'
|
38
|
+
assert_equal network_category['ipaddress_eth0'], '192.168.1.1'
|
39
|
+
assert_equal software_category['bios_vendor'], 'TEST_BIOS'
|
40
|
+
end
|
41
|
+
end
|
@@ -21,13 +21,6 @@ class DestroyHostNotificationTest < ActiveSupport::TestCase
|
|
21
21
|
ForemanDiscovery::UINotifications::NewHost.deliver!(host)
|
22
22
|
end
|
23
23
|
assert_equal 1, blueprint.notifications.count
|
24
|
-
assert_no_difference('blueprint.notifications.count') do
|
25
|
-
host = FactoryBot.create(:discovered_host)
|
26
|
-
ForemanDiscovery::UINotifications::NewHost.deliver!(host)
|
27
|
-
end
|
28
|
-
assert_no_difference('blueprint.notifications.count') do
|
29
|
-
Host::Discovered.all.last.destroy
|
30
|
-
end
|
31
24
|
Host::Discovered.destroy_all
|
32
25
|
assert_equal 0, blueprint.notifications.count
|
33
26
|
end
|
@@ -55,9 +48,9 @@ class DestroyHostNotificationTest < ActiveSupport::TestCase
|
|
55
48
|
ForemanDiscovery::UINotifications::NewHost.deliver!(host1)
|
56
49
|
host2 = FactoryBot.create(:discovered_host)
|
57
50
|
ForemanDiscovery::UINotifications::NewHost.deliver!(host2)
|
58
|
-
assert_equal
|
51
|
+
assert_equal 2, blueprint.notifications.count
|
59
52
|
new_host = ::ForemanDiscovery::HostConverter.to_managed(host1, false, false)
|
60
53
|
assert new_host.save!
|
61
|
-
assert_equal
|
54
|
+
assert_equal 2, blueprint.notifications.count
|
62
55
|
end
|
63
56
|
end
|
@@ -16,14 +16,14 @@ class NewHostNotificationTest < ActiveSupport::TestCase
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
test 'multiple discovered hosts should generate
|
19
|
+
test 'multiple discovered hosts should generate multiple notifications' do
|
20
20
|
host1 = FactoryBot.create :discovered_host
|
21
21
|
ForemanDiscovery::UINotifications::NewHost.deliver!(host1)
|
22
22
|
expired_at = blueprint.notifications.first.expired_at
|
23
23
|
Time.any_instance.stubs(:utc).returns(expired_at + 1.hour)
|
24
24
|
host2 = FactoryBot.create :discovered_host
|
25
25
|
ForemanDiscovery::UINotifications::NewHost.deliver!(host2)
|
26
|
-
assert_equal
|
27
|
-
assert_not_equal expired_at, blueprint.notifications.
|
26
|
+
assert_equal 2, blueprint.notifications.count
|
27
|
+
assert_not_equal expired_at, blueprint.notifications.last.expired_at
|
28
28
|
end
|
29
29
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
export const foremanUrl = path => `${window.URL_PREFIX}${path}`;
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { useDispatch } from 'react-redux';
|
3
|
+
import { push } from 'connected-react-router';
|
4
|
+
import { Button } from '@patternfly/react-core';
|
5
|
+
import EmptyStatePattern from './EmptyStatePattern';
|
6
|
+
import { defaultEmptyStatePropTypes } from './EmptyStatePropTypes';
|
7
|
+
|
8
|
+
const DefaultEmptyState = props => {
|
9
|
+
const {
|
10
|
+
icon,
|
11
|
+
iconType,
|
12
|
+
header,
|
13
|
+
description,
|
14
|
+
documentation,
|
15
|
+
action,
|
16
|
+
secondaryActions,
|
17
|
+
} = props;
|
18
|
+
|
19
|
+
const dispatch = useDispatch();
|
20
|
+
const actionButtonClickHandler = ({ url, onClick }) => {
|
21
|
+
if (onClick) onClick();
|
22
|
+
else if (url) dispatch(push(url));
|
23
|
+
};
|
24
|
+
|
25
|
+
const ActionButton = action ? (
|
26
|
+
<Button
|
27
|
+
component="a"
|
28
|
+
onClick={() => actionButtonClickHandler(action)}
|
29
|
+
variant="primary"
|
30
|
+
>
|
31
|
+
{action.title}
|
32
|
+
</Button>
|
33
|
+
) : null;
|
34
|
+
|
35
|
+
const SecondaryButton = secondaryActions
|
36
|
+
? secondaryActions.map(({ title, url, onClick }) => (
|
37
|
+
<Button
|
38
|
+
component="a"
|
39
|
+
key={`sec-button-${title}`}
|
40
|
+
onClick={() => actionButtonClickHandler({ url, onClick })}
|
41
|
+
variant="secondary"
|
42
|
+
>
|
43
|
+
{title}
|
44
|
+
</Button>
|
45
|
+
))
|
46
|
+
: null;
|
47
|
+
|
48
|
+
return (
|
49
|
+
<EmptyStatePattern
|
50
|
+
icon={icon}
|
51
|
+
iconType={iconType}
|
52
|
+
header={header}
|
53
|
+
description={description}
|
54
|
+
documentation={documentation}
|
55
|
+
action={ActionButton}
|
56
|
+
secondaryActions={SecondaryButton}
|
57
|
+
/>
|
58
|
+
);
|
59
|
+
};
|
60
|
+
|
61
|
+
DefaultEmptyState.propTypes = defaultEmptyStatePropTypes;
|
62
|
+
|
63
|
+
DefaultEmptyState.defaultProps = {
|
64
|
+
icon: 'add-circle-o',
|
65
|
+
secondaryActions: [],
|
66
|
+
iconType: 'pf',
|
67
|
+
};
|
68
|
+
|
69
|
+
export default DefaultEmptyState;
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { Icon } from 'patternfly-react';
|
3
|
+
import {
|
4
|
+
Title,
|
5
|
+
EmptyState,
|
6
|
+
EmptyStateVariant,
|
7
|
+
EmptyStateBody,
|
8
|
+
EmptyStateSecondaryActions,
|
9
|
+
} from '@patternfly/react-core';
|
10
|
+
import { emptyStatePatternPropTypes } from './EmptyStatePropTypes';
|
11
|
+
import { translate as __ } from '../../../common/I18n';
|
12
|
+
|
13
|
+
const EmptyStatePattern = props => {
|
14
|
+
const {
|
15
|
+
documentation,
|
16
|
+
action,
|
17
|
+
secondaryActions,
|
18
|
+
iconType,
|
19
|
+
icon,
|
20
|
+
header,
|
21
|
+
description,
|
22
|
+
} = props;
|
23
|
+
|
24
|
+
const DocumentationBlock = () => {
|
25
|
+
if (!documentation) {
|
26
|
+
return null;
|
27
|
+
}
|
28
|
+
// The documentation prop can also be a customized node
|
29
|
+
if (React.isValidElement(documentation)) {
|
30
|
+
return documentation;
|
31
|
+
}
|
32
|
+
const {
|
33
|
+
label = __('For more information please see '), // eslint-disable-line react/prop-types
|
34
|
+
buttonLabel = __('documentation'), // eslint-disable-line react/prop-types
|
35
|
+
url, // eslint-disable-line react/prop-types
|
36
|
+
} = documentation;
|
37
|
+
return (
|
38
|
+
<span>
|
39
|
+
{label}
|
40
|
+
<a href={url}>{buttonLabel}</a>
|
41
|
+
</span>
|
42
|
+
);
|
43
|
+
};
|
44
|
+
|
45
|
+
return (
|
46
|
+
<EmptyState variant={EmptyStateVariant.xl}>
|
47
|
+
<span className="empty-state-icon">
|
48
|
+
{/* TODO: Add pf4 icons, Redmine issue: #30865 */}
|
49
|
+
<Icon name={icon} type={iconType} size="2x" />
|
50
|
+
</span>
|
51
|
+
<Title headingLevel="h5" size="4xl">
|
52
|
+
{header}
|
53
|
+
</Title>
|
54
|
+
<EmptyStateBody>
|
55
|
+
<div className="empty-state-description">{description}</div>
|
56
|
+
<DocumentationBlock />
|
57
|
+
</EmptyStateBody>
|
58
|
+
{action}
|
59
|
+
<EmptyStateSecondaryActions>
|
60
|
+
{secondaryActions}
|
61
|
+
</EmptyStateSecondaryActions>
|
62
|
+
</EmptyState>
|
63
|
+
);
|
64
|
+
};
|
65
|
+
|
66
|
+
EmptyStatePattern.propTypes = emptyStatePatternPropTypes;
|
67
|
+
|
68
|
+
EmptyStatePattern.defaultProps = {
|
69
|
+
icon: 'add-circle-o',
|
70
|
+
secondaryActions: [],
|
71
|
+
documentation: {
|
72
|
+
url: '#',
|
73
|
+
},
|
74
|
+
iconType: 'pf',
|
75
|
+
};
|
76
|
+
|
77
|
+
export default EmptyStatePattern;
|