foreman_netbox 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +619 -0
  3. data/README.md +50 -0
  4. data/Rakefile +50 -0
  5. data/app/contracts/foreman_netbox/device_contract.rb +42 -0
  6. data/app/contracts/foreman_netbox/params/interface_params.rb +16 -0
  7. data/app/contracts/foreman_netbox/params/ip_address_params.rb +15 -0
  8. data/app/contracts/foreman_netbox/params/tenant_params.rb +13 -0
  9. data/app/contracts/foreman_netbox/virtual_machine_contract.rb +29 -0
  10. data/app/interactors/foreman_netbox/concerns/facts.rb +11 -0
  11. data/app/interactors/foreman_netbox/concerns/primary_ips.rb +25 -0
  12. data/app/interactors/foreman_netbox/delete_host/delete_device.rb +20 -0
  13. data/app/interactors/foreman_netbox/delete_host/delete_virtual_machine.rb +20 -0
  14. data/app/interactors/foreman_netbox/delete_host/organizer.rb +12 -0
  15. data/app/interactors/foreman_netbox/sync_host/organizer.rb +35 -0
  16. data/app/interactors/foreman_netbox/sync_host/sync_device/create.rb +36 -0
  17. data/app/interactors/foreman_netbox/sync_host/sync_device/find.rb +41 -0
  18. data/app/interactors/foreman_netbox/sync_host/sync_device/organizer.rb +30 -0
  19. data/app/interactors/foreman_netbox/sync_host/sync_device/save_netbox_url.rb +29 -0
  20. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_role/create.rb +32 -0
  21. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_role/find.rb +28 -0
  22. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_role/organizer.rb +20 -0
  23. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/create.rb +34 -0
  24. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/find.rb +28 -0
  25. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/organizer.rb +22 -0
  26. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/sync_manufacturer/create.rb +34 -0
  27. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/sync_manufacturer/find.rb +40 -0
  28. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/sync_manufacturer/organizer.rb +22 -0
  29. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/update.rb +33 -0
  30. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/create.rb +37 -0
  31. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/delete.rb +36 -0
  32. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/find.rb +30 -0
  33. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/organizer.rb +23 -0
  34. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/create.rb +46 -0
  35. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/delete.rb +40 -0
  36. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/find.rb +32 -0
  37. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/organizer.rb +24 -0
  38. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/update.rb +39 -0
  39. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/update.rb +38 -0
  40. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_site/create.rb +32 -0
  41. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_site/find.rb +28 -0
  42. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_site/organizer.rb +25 -0
  43. data/app/interactors/foreman_netbox/sync_host/sync_device/sync_site/update.rb +35 -0
  44. data/app/interactors/foreman_netbox/sync_host/sync_device/update.rb +85 -0
  45. data/app/interactors/foreman_netbox/sync_host/sync_device/validate.rb +25 -0
  46. data/app/interactors/foreman_netbox/sync_host/sync_tenant/create.rb +30 -0
  47. data/app/interactors/foreman_netbox/sync_host/sync_tenant/find.rb +26 -0
  48. data/app/interactors/foreman_netbox/sync_host/sync_tenant/organizer.rb +19 -0
  49. data/app/interactors/foreman_netbox/sync_host/sync_tenant/update.rb +33 -0
  50. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/create.rb +34 -0
  51. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/find.rb +34 -0
  52. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/organizer.rb +28 -0
  53. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/save_netbox_url.rb +31 -0
  54. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/create.rb +35 -0
  55. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/find.rb +28 -0
  56. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/organizer.rb +22 -0
  57. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/sync_cluster_type/create.rb +34 -0
  58. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/sync_cluster_type/find.rb +32 -0
  59. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/sync_cluster_type/organizer.rb +22 -0
  60. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/update.rb +35 -0
  61. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/create.rb +33 -0
  62. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/delete.rb +36 -0
  63. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/find.rb +30 -0
  64. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/organizer.rb +23 -0
  65. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/create.rb +46 -0
  66. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/delete.rb +40 -0
  67. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/find.rb +28 -0
  68. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/organizer.rb +24 -0
  69. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/update.rb +39 -0
  70. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/update.rb +38 -0
  71. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/update.rb +82 -0
  72. data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/validate.rb +25 -0
  73. data/app/jobs/foreman_netbox/sync_host_job.rb +19 -0
  74. data/app/lib/foreman_netbox/api.rb +12 -0
  75. data/app/models/concerns/foreman_netbox/host_extensions.rb +27 -0
  76. data/app/models/concerns/foreman_netbox/location_extensions.rb +13 -0
  77. data/app/models/concerns/foreman_netbox/nic/base_extensions.rb +23 -0
  78. data/app/models/concerns/foreman_netbox/user_usergroup_common_extensions.rb +18 -0
  79. data/app/models/foreman_netbox/netbox_facet.rb +34 -0
  80. data/app/models/orchestration/netbox.rb +64 -0
  81. data/app/models/setting/netbox.rb +32 -0
  82. data/app/services/foreman_netbox/cached_netbox_parameters.rb +103 -0
  83. data/app/services/foreman_netbox/netbox_parameters.rb +185 -0
  84. data/app/services/foreman_netbox/netbox_parameters_comparator.rb +96 -0
  85. data/app/views/hosts/_netbox_tab.html.erb +28 -0
  86. data/config/routes.rb +4 -0
  87. data/db/migrate/20200527135812_create_netbox_facet.rb +12 -0
  88. data/db/migrate/20200604141933_add_sync_info_to_netbox_facet.rb +8 -0
  89. data/db/migrate/20200708093607_add_raw_data_to_netbox_facet.rb +7 -0
  90. data/lib/foreman_netbox.rb +6 -0
  91. data/lib/foreman_netbox/engine.rb +64 -0
  92. data/lib/foreman_netbox/version.rb +5 -0
  93. data/lib/tasks/foreman_netbox_tasks.rake +67 -0
  94. data/test/factories/host.rb +17 -0
  95. data/test/factories/netbox_facet.rb +17 -0
  96. data/test/fixtures/facts/k8s_physical_host.json +328 -0
  97. data/test/fixtures/facts/rhel_physical_host.json +512 -0
  98. data/test/fixtures/facts/rhel_virtual_host.json +455 -0
  99. data/test/fixtures/netbox_device_raw_data.json +330 -0
  100. data/test/fixtures/netbox_virtual_machine_raw_data.json +241 -0
  101. data/test/integration/foreman_netbox/sync_k8s_physical_host_test.rb +81 -0
  102. data/test/integration/foreman_netbox/sync_rhel_physical_host_test.rb +81 -0
  103. data/test/integration/foreman_netbox/sync_rhel_virtual_host_test.rb +93 -0
  104. data/test/interactors/foreman_netbox/sync_host/organizer_test.rb +78 -0
  105. data/test/interactors/foreman_netbox/sync_host/sync_device/create_test.rb +65 -0
  106. data/test/interactors/foreman_netbox/sync_host/sync_device/find_test.rb +105 -0
  107. data/test/interactors/foreman_netbox/sync_host/sync_device/save_netbox_url_test.rb +39 -0
  108. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_role/create_test.rb +45 -0
  109. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_role/find_test.rb +58 -0
  110. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/create_test.rb +55 -0
  111. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/find_test.rb +63 -0
  112. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/sync_manufacturer/create_test.rb +48 -0
  113. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/sync_manufacturer/find_test.rb +105 -0
  114. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/update_test.rb +54 -0
  115. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/create_test.rb +51 -0
  116. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/delete_test.rb +41 -0
  117. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/find_test.rb +53 -0
  118. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/create_test.rb +80 -0
  119. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/delete_test.rb +72 -0
  120. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/find_test.rb +51 -0
  121. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/update_test.rb +64 -0
  122. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/update_test.rb +92 -0
  123. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_site/create_test.rb +51 -0
  124. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_site/find_test.rb +59 -0
  125. data/test/interactors/foreman_netbox/sync_host/sync_device/sync_site/update_test.rb +54 -0
  126. data/test/interactors/foreman_netbox/sync_host/sync_device/update_test.rb +188 -0
  127. data/test/interactors/foreman_netbox/sync_host/sync_tenant/create_test.rb +50 -0
  128. data/test/interactors/foreman_netbox/sync_host/sync_tenant/find_test.rb +58 -0
  129. data/test/interactors/foreman_netbox/sync_host/sync_tenant/update_test.rb +59 -0
  130. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/create_test.rb +74 -0
  131. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/find_test.rb +77 -0
  132. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/save_netbox_url_test.rb +39 -0
  133. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/create_test.rb +54 -0
  134. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/find_test.rb +58 -0
  135. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/sync_cluster_type/create_test.rb +50 -0
  136. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/sync_cluster_type/find_test.rb +65 -0
  137. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/update_test.rb +54 -0
  138. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/create_test.rb +53 -0
  139. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/delete_test.rb +37 -0
  140. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/find_test.rb +53 -0
  141. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/create_test.rb +80 -0
  142. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/delete_test.rb +73 -0
  143. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/find_test.rb +51 -0
  144. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/update_test.rb +64 -0
  145. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/update_test.rb +88 -0
  146. data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/update_test.rb +171 -0
  147. data/test/jobs/foreman_netbox/sync_host_job_test.rb +14 -0
  148. data/test/models/foreman_netbox/location_test.rb +42 -0
  149. data/test/models/foreman_netbox/netbox_facet_test.rb +219 -0
  150. data/test/models/foreman_netbox/nics/base_test.rb +81 -0
  151. data/test/models/foreman_netbox/usergroup_test.rb +23 -0
  152. data/test/models/host/managed_test.rb +63 -0
  153. data/test/services/foreman_netbox/netbox_attributes_test.rb +278 -0
  154. data/test/services/foreman_netbox/netbox_parameters_comparator_test.rb +136 -0
  155. data/test/test_plugin_helper.rb +25 -0
  156. metadata +343 -0
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ class SyncK8sPhysicalHostTest < ActiveSupport::TestCase
6
+ setup do
7
+ setup_netbox_integration_test
8
+ end
9
+
10
+ subject { ForemanNetbox::SyncHost::Organizer.call(host: host) }
11
+
12
+ let(:hostname) { 'k8s_physical_host' }
13
+ let(:file) { file_fixture("facts/#{hostname}.json").read }
14
+ let(:facts_json) { JSON.parse(file) }
15
+ let(:host) do
16
+ FactoryBot.build_stubbed(
17
+ :host,
18
+ hostname: "#{hostname}.tier.example.com",
19
+ owner: FactoryBot.build_stubbed(:usergroup, name: 'Owner'),
20
+ location: FactoryBot.build_stubbed(:location, name: 'Location'),
21
+ interfaces: [
22
+ FactoryBot.build_stubbed(
23
+ :nic_base,
24
+ identifier: 'eth0',
25
+ mac: 'C3:CD:63:54:21:60',
26
+ ip: '10.0.0.7',
27
+ subnet: FactoryBot.build_stubbed(:subnet_ipv4, organizations: [], locations: [])
28
+ ),
29
+ FactoryBot.build_stubbed(
30
+ :nic_base,
31
+ identifier: 'eth1',
32
+ mac: '45:E9:6A:83:02:20',
33
+ ip6: '1600:0:2d0:202::17',
34
+ subnet6: FactoryBot.build_stubbed(:subnet_ipv6, organizations: [], locations: [])
35
+ )
36
+ ]
37
+ ).tap do |host|
38
+ host.stubs(:ip).returns(host.interfaces.find(&:ip).ip)
39
+ host.stubs(:ip6).returns(host.interfaces.find(&:ip6).ip6)
40
+ host.stubs(:compute?).returns(false)
41
+ host.stubs(:facts).returns(facts_json)
42
+ end
43
+ end
44
+
45
+ test 'sync host' do
46
+ ForemanNetbox::NetboxFacet.any_instance.expects(:update).twice.returns(true)
47
+
48
+ assert subject.success?
49
+
50
+ assert_equal host.name, subject.device.name
51
+ assert_equal host.owner.netbox_tenant_name, subject.device.tenant.name
52
+ assert_equal host.location.netbox_site_name, subject.device.site.name
53
+ assert_equal host.facts['manufacturer'], subject.device.device_type.manufacturer.name
54
+ assert_equal host.facts['productname'], subject.device.device_type.model
55
+ assert_equal host.facts['serialnumber'], subject.device.serial
56
+
57
+ assert_equal IPAddress.parse("#{host.ip}/24"), subject.device.primary_ip4.address
58
+ assert_equal IPAddress.parse("#{host.ip6}/64"), subject.device.primary_ip6.address
59
+ host.interfaces.each do |h_interface|
60
+ nx_interface = subject.interfaces.find { |i| i.name == h_interface.identifier }
61
+
62
+ assert nx_interface.present?
63
+
64
+ h_interface.netbox_ips.each do |h_ip|
65
+ assert subject.ip_addresses.find { |nx_ip| nx_ip.interface.id == nx_interface.id && nx_ip.address == IPAddress.parse(h_ip) }.present?
66
+ end
67
+ end
68
+
69
+ expected_tags = ForemanNetbox::NetboxParameters::DEFAULT_TAGS
70
+ assert_equal expected_tags, subject.device.tags
71
+ assert_equal expected_tags, subject.device_type.tags
72
+ assert_equal expected_tags, subject.site.tags
73
+ assert_equal expected_tags, subject.tenant.tags
74
+ subject.interfaces.reload.each do |interface|
75
+ assert_equal expected_tags, interface.tags
76
+ end
77
+ subject.ip_addresses.reload.each do |interface|
78
+ assert_equal expected_tags, interface.tags
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ class SyncRhelPhysicalHostTest < ActiveSupport::TestCase
6
+ setup do
7
+ setup_netbox_integration_test
8
+ end
9
+
10
+ subject { ForemanNetbox::SyncHost::Organizer.call(host: host) }
11
+
12
+ let(:hostname) { 'rhel_physical_host' }
13
+ let(:file) { file_fixture("facts/#{hostname}.json").read }
14
+ let(:facts_json) { JSON.parse(file) }
15
+ let(:host) do
16
+ FactoryBot.build_stubbed(
17
+ :host,
18
+ hostname: "#{hostname}.tier.example.com",
19
+ owner: FactoryBot.build_stubbed(:usergroup, name: SecureRandom.hex(16)),
20
+ location: FactoryBot.build_stubbed(:location, name: 'Location'),
21
+ interfaces: [
22
+ FactoryBot.build_stubbed(
23
+ :nic_base,
24
+ identifier: 'eth0',
25
+ mac: 'C3:CD:63:54:21:61',
26
+ ip: '10.0.0.8',
27
+ subnet: FactoryBot.build_stubbed(:subnet_ipv4, organizations: [], locations: [])
28
+ ),
29
+ FactoryBot.build_stubbed(
30
+ :nic_base,
31
+ identifier: 'eth1',
32
+ mac: '45:E9:6A:83:02:21',
33
+ ip6: '1600:0:2d0:202::18',
34
+ subnet6: FactoryBot.build_stubbed(:subnet_ipv6, organizations: [], locations: [])
35
+ )
36
+ ]
37
+ ).tap do |host|
38
+ host.stubs(:ip).returns(host.interfaces.find(&:ip).ip)
39
+ host.stubs(:ip6).returns(host.interfaces.find(&:ip6).ip6)
40
+ host.stubs(:compute?).returns(false)
41
+ host.stubs(:facts).returns(facts_json)
42
+ end
43
+ end
44
+
45
+ test 'sync host' do
46
+ ForemanNetbox::NetboxFacet.any_instance.expects(:update).twice.returns(true)
47
+
48
+ assert subject.success?
49
+
50
+ assert_equal host.name, subject.device.name
51
+ assert_equal host.owner.netbox_tenant_name, subject.device.tenant.name
52
+ assert_equal host.location.netbox_site_name, subject.device.site.name
53
+ assert_equal host.facts['manufacturer'], subject.device.device_type.manufacturer.name
54
+ assert_equal host.facts['productname'], subject.device.device_type.model
55
+ assert_equal host.facts['serialnumber'], subject.device.serial
56
+
57
+ assert_equal IPAddress.parse("#{host.ip}/24"), subject.device.primary_ip4.address
58
+ assert_equal IPAddress.parse("#{host.ip6}/64"), subject.device.primary_ip6.address
59
+ host.interfaces.each do |h_interface|
60
+ nx_interface = subject.interfaces.find { |i| i.name == h_interface.identifier }
61
+
62
+ assert nx_interface.present?
63
+
64
+ h_interface.netbox_ips.each do |h_ip|
65
+ assert subject.ip_addresses.find { |nx_ip| nx_ip.interface.id == nx_interface.id && nx_ip.address == IPAddress.parse(h_ip) }.present?
66
+ end
67
+ end
68
+
69
+ expected_tags = ForemanNetbox::NetboxParameters::DEFAULT_TAGS
70
+ assert_equal expected_tags, subject.device.tags
71
+ assert_equal expected_tags, subject.device_type.tags
72
+ assert_equal expected_tags, subject.site.tags
73
+ assert_equal expected_tags, subject.tenant.tags
74
+ subject.interfaces.reload.each do |interface|
75
+ assert_equal expected_tags, interface.tags
76
+ end
77
+ subject.ip_addresses.reload.each do |interface|
78
+ assert_equal expected_tags, interface.tags
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ class SyncRhelVirtualHostTest < ActiveSupport::TestCase
6
+ setup do
7
+ setup_netbox_integration_test
8
+ end
9
+
10
+ subject { ForemanNetbox::SyncHost::Organizer.call(host: host) }
11
+
12
+ let(:hostname) { 'rhel_virtual_host' }
13
+ let(:file) { file_fixture("facts/#{hostname}.json").read }
14
+ let(:facts_json) { JSON.parse(file) }
15
+ let(:host) do
16
+ FactoryBot.build_stubbed(
17
+ :host,
18
+ hostname: "#{hostname}.tier.example.com",
19
+ owner: FactoryBot.build_stubbed(:usergroup, name: 'Owner'),
20
+ interfaces: [
21
+ FactoryBot.build_stubbed(
22
+ :nic_base,
23
+ identifier: 'eth0',
24
+ mac: 'C3:CD:63:54:21:62',
25
+ ip: '10.0.0.9',
26
+ subnet: FactoryBot.build_stubbed(:subnet_ipv4, organizations: [], locations: [])
27
+ ),
28
+ FactoryBot.build_stubbed(
29
+ :nic_base,
30
+ identifier: 'eth1',
31
+ mac: '45:E9:6A:83:02:22',
32
+ ip6: '1600:0:2d0:202::19',
33
+ subnet6: FactoryBot.build_stubbed(:subnet_ipv6, organizations: [], locations: [])
34
+ )
35
+ ]
36
+ ).tap do |host|
37
+ host.stubs(:ip).returns(host.interfaces.find(&:ip).ip)
38
+ host.stubs(:ip6).returns(host.interfaces.find(&:ip6).ip6)
39
+ host.stubs(:compute?).returns(true)
40
+ host.stubs(:compute_resource).returns(
41
+ OpenStruct.new(type: 'Foreman::Model::Vmware')
42
+ )
43
+ host.stubs(:compute_object).returns(
44
+ OpenStruct.new(
45
+ cluster: 'CLUSTER',
46
+ cpus: 1,
47
+ memory_mb: 1024,
48
+ volumes: [
49
+ OpenStruct.new(size_gb: 120)
50
+ ]
51
+ )
52
+ )
53
+ host.stubs(:facts).returns(facts_json)
54
+ end
55
+ end
56
+
57
+ test 'sync host' do
58
+ ForemanNetbox::NetboxFacet.any_instance.expects(:update).twice.returns(true)
59
+
60
+ assert subject.success?
61
+
62
+ assert_equal host.name, subject.virtual_machine.name
63
+ assert_equal host.owner.netbox_tenant_name, subject.virtual_machine.tenant.name
64
+ assert_equal host.compute_object.cpus, subject.virtual_machine.vcpus
65
+ assert_equal host.compute_object.memory_mb, subject.virtual_machine.memory
66
+ assert_equal host.compute_object.volumes.first.size_gb, subject.virtual_machine.disk
67
+ assert_equal host.compute_object.cluster, subject.virtual_machine.cluster.name
68
+ assert_equal 'VMware ESXi', subject.cluster_type.name
69
+
70
+ assert_equal IPAddress.parse("#{host.ip}/24"), subject.virtual_machine.primary_ip4.address
71
+ assert_equal IPAddress.parse("#{host.ip6}/64"), subject.virtual_machine.primary_ip6.address
72
+ host.interfaces.each do |h_interface|
73
+ nx_interface = subject.interfaces.find { |i| i.name == h_interface.identifier }
74
+
75
+ assert nx_interface.present?
76
+
77
+ h_interface.netbox_ips.each do |h_ip|
78
+ assert subject.ip_addresses.find { |nx_ip| nx_ip.interface.id == nx_interface.id && nx_ip.address == IPAddress.parse(h_ip) }.present?
79
+ end
80
+ end
81
+
82
+ expected_tags = ForemanNetbox::NetboxParameters::DEFAULT_TAGS
83
+ assert_equal expected_tags, subject.virtual_machine.tags
84
+ assert_equal expected_tags, subject.tenant.tags
85
+ assert_equal expected_tags, subject.cluster.tags
86
+ subject.interfaces.reload.each do |interface|
87
+ assert_equal expected_tags, interface.tags
88
+ end
89
+ subject.ip_addresses.reload.each do |interface|
90
+ assert_equal expected_tags, interface.tags
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ class SyncHostOrganizerTest < ActiveSupport::TestCase
6
+ subject { ForemanNetbox::SyncHost::Organizer.call(host: host) }
7
+
8
+ let(:host) do
9
+ FactoryBot.create(:host).tap do |host|
10
+ host.stubs(:interfaces).returns([])
11
+ host.stubs(:facts).returns({ serialnumber: 'abc123' })
12
+ end
13
+ end
14
+ let(:tags) { ForemanNetbox::NetboxParameters::DEFAULT_TAGS }
15
+
16
+ setup do
17
+ setup_default_netbox_settings
18
+ # rubocop:disable Layout/FirstArrayElementIndentation
19
+ stub_get_netbox_request('tenancy/tenants.json?limit=50&slug=admin-user', results: [
20
+ { id: 1, name: host.owner.name, slug: host.owner.name.parameterize, tags: tags }
21
+ ])
22
+ stub_get_netbox_request('dcim/sites.json?limit=50&slug=location-1', results: [
23
+ { id: 1, name: host.location.netbox_site_name, slug: host.location.netbox_site_slug, tags: tags }
24
+ ])
25
+ stub_get_netbox_request('dcim/device-roles.json?limit=50&slug=server', results: [
26
+ { id: 1, name: 'Device Role', slug: 'server' }
27
+ ])
28
+ stub_get_netbox_request('dcim/manufacturers.json?limit=50&slug=unknown', results: [
29
+ { id: 1, name: 'Unknown', slug: 'unknown' }
30
+ ])
31
+ stub_get_netbox_request('dcim/device-types.json?limit=50&slug=unknown', results: [
32
+ { id: 1, name: 'Unknown', slug: 'unknown', tags: tags }
33
+ ])
34
+ stub_get_netbox_request("dcim/devices.json?limit=50&serial=#{host.facts[:serialnumber]}", results: [
35
+ { id: 1, name: host.name, serial: host.facts[:serialnumber], tags: tags }
36
+ ])
37
+ stub_get_netbox_request('dcim/interfaces.json?device_id=1&limit=50', results: [])
38
+ stub_get_netbox_request('ipam/ip-addresses.json?device_id=1&limit=50', results: [])
39
+ # rubocop:enable Layout/FirstArrayElementIndentation
40
+ end
41
+
42
+ test 'save synchronization status when it succeeds' do
43
+ stub_request(:patch, "#{Setting::Netbox[:netbox_url]}/api/dcim/devices/1.json").to_return(
44
+ status: 200, headers: { 'Content-Type': 'application/json' },
45
+ body: { id: 1 }.to_json
46
+ )
47
+ subject
48
+ host.reload
49
+
50
+ assert_not_nil host.netbox_facet.synchronized_at
51
+ assert_equal "#{Setting::Netbox[:netbox_url]}/dcim/devices/1", host.netbox_facet.url
52
+ assert_nil host.netbox_facet.synchronization_error
53
+ end
54
+
55
+ test 'save synchronization status when it fails' do
56
+ stub_request(:patch, "#{Setting::Netbox[:netbox_url]}/api/dcim/devices/1.json").to_return(
57
+ status: 500, headers: { 'Content-Type': 'application/json' }
58
+ )
59
+ subject
60
+ host.reload
61
+
62
+ assert_not_nil host.netbox_facet.synchronized_at
63
+ assert_nil host.netbox_facet.url
64
+ assert_equal 'ForemanNetbox::SyncHost::SyncDevice::Update: 500 Remote Error', host.netbox_facet.synchronization_error
65
+ end
66
+
67
+ private
68
+
69
+ def stub_get_netbox_request(path, results:)
70
+ stub_request(:get, "#{Setting::Netbox[:netbox_url]}/api/#{path}").to_return(
71
+ status: 200, headers: { 'Content-Type': 'application/json' },
72
+ body: {
73
+ count: 1,
74
+ results: results
75
+ }.to_json
76
+ )
77
+ end
78
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ class CreateDeviceTest < ActiveSupport::TestCase
6
+ subject do
7
+ ForemanNetbox::SyncHost::SyncDevice::Create.call(
8
+ host: host,
9
+ netbox_params: host.netbox_facet.netbox_params,
10
+ device_type: device_type,
11
+ device_role: device_role,
12
+ site: site,
13
+ tenant: tenant,
14
+ device: device
15
+ )
16
+ end
17
+
18
+ let(:device_id) { 1 }
19
+ let(:host) do
20
+ FactoryBot.build_stubbed(:host, hostname: 'host.dev.example.com').tap do |host|
21
+ host.stubs(:facts).returns({ 'serialnumber' => 'abc123' })
22
+ end
23
+ end
24
+ let(:device_type) { OpenStruct.new(id: 1) }
25
+ let(:device_role) { OpenStruct.new(id: 1) }
26
+ let(:site) { OpenStruct.new(id: 1) }
27
+ let(:tenant) { OpenStruct.new(id: 1) }
28
+ let(:netbox_device_params) { host.netbox_facet.netbox_params.fetch(:device) }
29
+
30
+ setup do
31
+ setup_default_netbox_settings
32
+ end
33
+
34
+ context 'when device is not assigned to the context' do
35
+ let(:device) { nil }
36
+
37
+ it 'creates a device' do
38
+ stub_post = stub_request(:post, "#{Setting[:netbox_url]}/api/dcim/devices/").with(
39
+ body: {
40
+ name: netbox_device_params[:name],
41
+ serial: netbox_device_params[:serial],
42
+ tags: netbox_device_params[:tags],
43
+ device_type: device_type.id,
44
+ device_role: device_role.id,
45
+ site: site.id,
46
+ tenant: tenant.id
47
+ }.to_json
48
+ ).to_return(
49
+ status: 201, headers: { 'Content-Type': 'application/json' },
50
+ body: { id: device_id }.to_json
51
+ )
52
+
53
+ assert_equal device_id, subject.device.id
54
+ assert_requested(stub_post)
55
+ end
56
+ end
57
+
58
+ context 'when device is already assigned to the context' do
59
+ let(:device) { OpenStruct.new(id: device_id) }
60
+
61
+ it 'does not create a device' do
62
+ assert_equal device_id, subject.device.id
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ class FindDeviceTest < ActiveSupport::TestCase
6
+ subject { ForemanNetbox::SyncHost::SyncDevice::Find.call(host: host, netbox_params: host.netbox_facet.netbox_params) }
7
+
8
+ let(:host) do
9
+ FactoryBot.build_stubbed(:host).tap do |host|
10
+ host.stubs(:mac).returns('C3:CD:63:54:21:62')
11
+ host.stubs(:facts).returns({ 'serialnumber' => 'abc123' })
12
+ end
13
+ end
14
+
15
+ setup do
16
+ setup_default_netbox_settings
17
+ end
18
+
19
+ context 'when device already exists in Netbox' do
20
+ test 'find device by host name' do
21
+ stub_get_by_serial = stub_request(:get, "#{Setting[:netbox_url]}/api/dcim/devices.json").with(
22
+ query: { limit: 50, serial: host.netbox_facet.netbox_params.dig(:device, :serial) }
23
+ ).to_return(
24
+ status: 200, headers: { 'Content-Type': 'application/json' },
25
+ body: { count: 0, results: [] }.to_json
26
+ )
27
+ stub_get_by_mac_addres = stub_request(:get, "#{Setting[:netbox_url]}/api/dcim/devices.json").with(
28
+ query: { limit: 50, mac_address: host.mac }
29
+ ).to_return(
30
+ status: 200, headers: { 'Content-Type': 'application/json' },
31
+ body: { count: 0, results: [] }.to_json
32
+ )
33
+ stub_get_by_name = stub_request(:get, "#{Setting[:netbox_url]}/api/dcim/devices.json").with(
34
+ query: { limit: 50, name: host.name }
35
+ ).to_return(
36
+ status: 200, headers: { 'Content-Type': 'application/json' },
37
+ body: { count: 1, results: [{ id: 1, name: host.name }] }.to_json
38
+ )
39
+
40
+ assert_equal 1, subject.device.id
41
+ assert_requested(stub_get_by_serial)
42
+ assert_requested(stub_get_by_mac_addres)
43
+ assert_requested(stub_get_by_name)
44
+ end
45
+
46
+ test 'find device by mac address' do
47
+ stub_get_by_serial = stub_request(:get, "#{Setting[:netbox_url]}/api/dcim/devices.json").with(
48
+ query: { limit: 50, serial: host.netbox_facet.netbox_params.dig(:device, :serial) }
49
+ ).to_return(
50
+ status: 200, headers: { 'Content-Type': 'application/json' },
51
+ body: { count: 0, results: [] }.to_json
52
+ )
53
+ stub_get_by_mac_addres = stub_request(:get, "#{Setting[:netbox_url]}/api/dcim/devices.json").with(
54
+ query: { limit: 50, mac_address: host.mac }
55
+ ).to_return(
56
+ status: 200, headers: { 'Content-Type': 'application/json' },
57
+ body: { count: 1, results: [{ id: 1, name: host.netbox_facet.netbox_params.dig(:device, :name) }] }.to_json
58
+ )
59
+
60
+ assert_equal 1, subject.device.id
61
+ assert_requested(stub_get_by_serial)
62
+ assert_requested(stub_get_by_mac_addres)
63
+ end
64
+
65
+ test 'find device by serial number' do
66
+ stub_get_by_serial = stub_request(:get, "#{Setting[:netbox_url]}/api/dcim/devices.json").with(
67
+ query: { limit: 50, serial: host.netbox_facet.netbox_params.dig(:device, :serial) }
68
+ ).to_return(
69
+ status: 200, headers: { 'Content-Type': 'application/json' },
70
+ body: { count: 1, results: [{ id: 1, name: host.name }] }.to_json
71
+ )
72
+
73
+ assert_equal 1, subject.device.id
74
+ assert_requested(stub_get_by_serial)
75
+ end
76
+ end
77
+
78
+ context 'when device does not exist in NetBox' do
79
+ it 'does not assign device to context' do
80
+ stub_get_by_serial = stub_request(:get, "#{Setting[:netbox_url]}/api/dcim/devices.json").with(
81
+ query: { limit: 50, serial: host.netbox_facet.netbox_params.dig(:device, :serial) }
82
+ ).to_return(
83
+ status: 200, headers: { 'Content-Type': 'application/json' },
84
+ body: { count: 0, results: [] }.to_json
85
+ )
86
+ stub_get_by_mac_addres = stub_request(:get, "#{Setting[:netbox_url]}/api/dcim/devices.json").with(
87
+ query: { limit: 50, mac_address: host.mac }
88
+ ).to_return(
89
+ status: 200, headers: { 'Content-Type': 'application/json' },
90
+ body: { count: 0, results: [] }.to_json
91
+ )
92
+ stub_get_by_name = stub_request(:get, "#{Setting[:netbox_url]}/api/dcim/devices.json").with(
93
+ query: { limit: 50, name: host.netbox_facet.netbox_params.dig(:device, :name) }
94
+ ).to_return(
95
+ status: 200, headers: { 'Content-Type': 'application/json' },
96
+ body: { count: 0, results: [] }.to_json
97
+ )
98
+
99
+ assert_nil subject.site
100
+ assert_requested(stub_get_by_serial)
101
+ assert_requested(stub_get_by_mac_addres)
102
+ assert_requested(stub_get_by_name)
103
+ end
104
+ end
105
+ end