foreman_netbox 1.0.2

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 (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,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanNetbox
4
+ module SyncHost
5
+ module SyncVirtualMachine
6
+ class Validate
7
+ include ::Interactor
8
+
9
+ def call
10
+ validator = ForemanNetbox::VirtualMachineContract.new.call(netbox_params)
11
+
12
+ return if validator.success?
13
+
14
+ message = validator.errors
15
+ .messages
16
+ .map { |m| "#{m.path} #{m.text}" }
17
+ .to_sentence
18
+ context.fail!(error: _('Invalid Virtual Machine parameters: %s') % message)
19
+ end
20
+
21
+ delegate :netbox_params, to: :context
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanNetbox
4
+ class SyncHostJob < ::ApplicationJob
5
+ queue_as :netbox_queue
6
+
7
+ def perform(host_id)
8
+ Host::Managed.find(host_id)&.push_to_netbox
9
+ end
10
+
11
+ rescue_from(StandardError) do |error|
12
+ Foreman::Logging.logger('background').error("Netbox: Error #{error}: #{error.backtrace}")
13
+ end
14
+
15
+ def humanized_name
16
+ _('Push host to Netbox')
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanNetbox
4
+ class API
5
+ def self.client
6
+ NetboxClientRuby.configure do |config|
7
+ config.netbox.api_base_url = "#{Setting::Netbox['netbox_url']}/api"
8
+ config.netbox.auth.token = Setting::Netbox['netbox_api_token']
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanNetbox
4
+ module HostExtensions
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ include ::Orchestration::Netbox
9
+ end
10
+
11
+ def netbox_facet
12
+ @netbox_facet ||= super || ForemanNetbox::NetboxFacet.new(host: self)
13
+ end
14
+
15
+ def push_to_netbox_async
16
+ ForemanNetbox::SyncHostJob.perform_later(id)
17
+ end
18
+
19
+ def push_to_netbox
20
+ ForemanNetbox::SyncHost::Organizer.call(host: self)
21
+ end
22
+
23
+ def delete_from_netbox
24
+ ForemanNetbox::DeleteHost::Organizer.call(host: self)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanNetbox
4
+ module LocationExtensions
5
+ def netbox_site_name
6
+ parameters.fetch('netbox_site', name)
7
+ end
8
+
9
+ def netbox_site_slug
10
+ netbox_site_name&.parameterize
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanNetbox
4
+ module Nic
5
+ module BaseExtensions
6
+ def netbox_name
7
+ identifier || (mac && "Interface #{mac}")
8
+ end
9
+
10
+ def netbox_ips
11
+ [netbox_ip, netbox_ip6].compact
12
+ end
13
+
14
+ def netbox_ip
15
+ ip && subnet && "#{ip}/#{subnet.cidr}"
16
+ end
17
+
18
+ def netbox_ip6
19
+ ip6 && subnet6 && "#{ip6}/#{subnet6.cidr}"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanNetbox
4
+ module UserUsergroupCommonExtensions
5
+ NETBOX_TENANT_MAX_LENGTH = 30
6
+
7
+ def netbox_tenant_name
8
+ return name unless name.length > NETBOX_TENANT_MAX_LENGTH
9
+
10
+ name_length = NETBOX_TENANT_MAX_LENGTH - id.to_s.length - 1
11
+ "#{name.to_s.truncate(name_length, omission: '')}-#{id}"
12
+ end
13
+
14
+ def netbox_tenant_slug
15
+ netbox_tenant_name&.parameterize
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanNetbox
4
+ class NetboxFacet < ApplicationRecord
5
+ include Facets::Base
6
+
7
+ COMMON_PARAMS = %i[interfaces ip_addresses tenant].freeze
8
+ DEVICE_PARAMS = %i[device device_role device_type manufacturer site].freeze
9
+ VIRTUAL_MACHINE_PARAMS = %i[virtual_machine cluster cluster_type].freeze
10
+
11
+ validates :host, presence: true, allow_blank: false
12
+ validates :url, uniqueness: true
13
+
14
+ def synchronization_success?
15
+ !synchronization_error
16
+ end
17
+
18
+ def netbox_params
19
+ ForemanNetbox::NetboxParameters.call(host)
20
+ end
21
+
22
+ def cached_netbox_params
23
+ ForemanNetbox::CachedNetboxParameters.call(host)
24
+ end
25
+
26
+ def netbox_params_diff
27
+ ForemanNetbox::NetboxParametersComparator.call(cached_netbox_params, netbox_params)
28
+ end
29
+
30
+ def netbox_will_change?
31
+ netbox_params_diff.keys.any?
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orchestration
4
+ module Netbox
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ after_validation :queue_netbox_push, if: :netbox_orchestration_allowed?
9
+ before_destroy :queue_netbox_destroy
10
+ end
11
+
12
+ delegate :netbox_will_change?, :netbox_params_diff, to: :netbox_facet
13
+
14
+ protected
15
+
16
+ def netbox_orchestration_allowed?
17
+ Setting::Netbox[:netbox_orchestration_enabled] && netbox_will_change?
18
+ end
19
+
20
+ def queue_netbox_push
21
+ return unless errors.empty? && managed?
22
+
23
+ ::Foreman::Logging.logger('foreman_netbox/import')
24
+ .info("Queued import of #{name} to Netbox. Changes that will be sent: #{netbox_params_diff}")
25
+
26
+ post_queue.create(name: _('Push host %s to Netbox') % self, priority: 100,
27
+ action: [self, :set_netbox])
28
+ end
29
+
30
+ def queue_netbox_destroy
31
+ return unless errors.empty? && managed?
32
+
33
+ queue.create(name: _('Delete host %s from Netbox') % self, priority: 60,
34
+ action: [self, :del_netbox])
35
+ end
36
+
37
+ def set_netbox
38
+ ::Foreman::Logging.logger('foreman_netbox/import')
39
+ .info("Pushing #{name} to Netbox")
40
+
41
+ push_to_netbox_async
42
+ rescue StandardError => e
43
+ ::Foreman::Logging.logger('foreman_netbox/import')
44
+ .error("Failed to push #{name} to Netbox. Error #{e}: #{e.backtrace}")
45
+
46
+ failure format(_('Failed to push %{name} to Netbox: %{message}\n '), name: name, message: e.message), e
47
+ end
48
+
49
+ def del_netbox
50
+ ::Foreman::Logging.logger('foreman_netbox/import')
51
+ .info("Deleting #{name} from Netbox")
52
+
53
+ result = delete_from_netbox
54
+ return true if result.success?
55
+
56
+ raise Foreman::Exception, result.error
57
+ rescue StandardError => e
58
+ ::Foreman::Logging.logger('foreman_netbox/import')
59
+ .error("Failed to delete #{name} from Netbox. Error #{e}: #{e.backtrace}")
60
+
61
+ failure format(_('Failed to delete %{name} from Netbox: %{message}\n '), name: name, message: e.message), e
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Setting
4
+ class Netbox < ::Setting
5
+ BLANK_ATTRS << 'netbox_url'
6
+ BLANK_ATTRS << 'netbox_api_token'
7
+ URI_BLANK_ATTRS << 'netbox_url'
8
+
9
+ def self.default_settings
10
+ [
11
+ set('netbox_url', N_('URL where Netbox is reachable'), nil, N_('Netbox URL')),
12
+ set('netbox_api_token', N_('API token to Netbox'), nil, N_('Netbox API token'), nil, encrypted: true),
13
+ set('netbox_orchestration_enabled', N_('Enable Netbox Orchestration'), false, N_('Netbox Orchestration'))
14
+ ]
15
+ end
16
+
17
+ def self.load_defaults
18
+ # Check the table exists
19
+ return unless super
20
+
21
+ transaction do
22
+ default_settings.each { |s| create! s.update(category: 'Setting::Netbox') }
23
+ end
24
+
25
+ true
26
+ end
27
+
28
+ def self.humanized_category
29
+ N_('Netbox')
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanNetbox
4
+ class CachedNetboxParameters
5
+ def self.call(host)
6
+ new(host).call
7
+ end
8
+
9
+ def initialize(host)
10
+ @is_compute = host.compute?
11
+ @data = host.netbox_facet.raw_data&.deep_symbolize_keys || {}
12
+ @result = {}
13
+ end
14
+
15
+ def call
16
+ additional_params = is_compute ? ForemanNetbox::NetboxFacet::VIRTUAL_MACHINE_PARAMS : ForemanNetbox::NetboxFacet::DEVICE_PARAMS
17
+ (ForemanNetbox::NetboxFacet::COMMON_PARAMS + additional_params).map { |key| send("read_#{key}") }
18
+
19
+ result
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :data, :is_compute
25
+ attr_accessor :result
26
+
27
+ def read_interfaces
28
+ return unless data.keys.include?(:interfaces)
29
+
30
+ result[:interfaces] = data.fetch(:interfaces, {}).fetch(:results, []).map do |interface|
31
+ interface.slice(:name, :mac_address, :tags)
32
+ .merge(type: interface.fetch(:type, {}).slice(:value))
33
+ .compact
34
+ end
35
+ end
36
+
37
+ def read_ip_addresses
38
+ return unless data.keys.include?(:ip_addresses)
39
+
40
+ result[:ip_addresses] = data.fetch(:ip_addresses, {}).fetch(:results, []).map do |ip_address|
41
+ ip_address.slice(:address, :tags)
42
+ .merge(interface: ip_address.fetch(:interface, {}).slice(:name))
43
+ end
44
+ end
45
+
46
+ def read_virtual_machine
47
+ return unless data.keys.include?(:virtual_machine)
48
+
49
+ result[:virtual_machine] = data.fetch(:virtual_machine, {}).slice(:name, :vcpus, :memory, :disk, :tags)
50
+ end
51
+
52
+ def read_tenant
53
+ return unless data.keys.include?(:tenant)
54
+
55
+ result[:tenant] = data.fetch(:tenant, {}).slice(:name, :slug, :tags)
56
+ end
57
+
58
+ def read_cluster
59
+ return unless data.keys.include?(:cluster)
60
+
61
+ result[:cluster] = data.fetch(:cluster, {}).slice(:name, :tags)
62
+ end
63
+
64
+ def read_cluster_type
65
+ return unless data.keys.include?(:cluster_type)
66
+
67
+ result[:cluster_type] = data.fetch(:cluster_type, {}).slice(:name, :slug)
68
+ end
69
+
70
+ def read_device
71
+ return unless data.keys.include?(:device)
72
+
73
+ result[:device] = data.fetch(:device, {})
74
+ .slice(:name, :serial, :tags)
75
+ .compact
76
+ .reject { |k, v| k == :serial && v.blank? }
77
+ end
78
+
79
+ def read_device_role
80
+ return unless data.keys.include?(:device_role)
81
+
82
+ result[:device_role] = data.fetch(:device_role, {}).slice(:name, :color, :slug)
83
+ end
84
+
85
+ def read_device_type
86
+ return unless data.keys.include?(:device_type)
87
+
88
+ result[:device_type] = data.fetch(:device_type, {}).slice(:model, :slug, :tags)
89
+ end
90
+
91
+ def read_manufacturer
92
+ return unless data.keys.include?(:manufacturer)
93
+
94
+ result[:manufacturer] = data.fetch(:manufacturer, {}).slice(:name, :slug)
95
+ end
96
+
97
+ def read_site
98
+ return unless data.keys.include?(:site)
99
+
100
+ result[:site] = data.fetch(:site, {}).slice(:name, :slug, :tags)
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,185 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanNetbox
4
+ # rubocop:disable Metrics/ClassLength
5
+ class NetboxParameters
6
+ UNKNOWN = 'Unknown'
7
+ DEFAULT_TAGS = ['foreman'].freeze
8
+ DEFAULT_INTERFACE_TYPE = 'virtual'
9
+ CLUSTER_TYPES = {
10
+ :'Foreman::Model::Vmware' => {
11
+ name: 'VMware ESXi',
12
+ slug: 'vmware-esxi'
13
+ }
14
+ }.freeze
15
+ DEVICE_ROLE = {
16
+ name: 'SERVER',
17
+ color: '9e9e9e',
18
+ slug: 'server'
19
+ }.freeze
20
+
21
+ def self.call(host)
22
+ new(host).call
23
+ end
24
+
25
+ def initialize(host)
26
+ @host = host
27
+ end
28
+
29
+ def call
30
+ additional_params = host.compute? ? ForemanNetbox::NetboxFacet::VIRTUAL_MACHINE_PARAMS : ForemanNetbox::NetboxFacet::DEVICE_PARAMS
31
+
32
+ (ForemanNetbox::NetboxFacet::COMMON_PARAMS + additional_params).map do |param|
33
+ send(param)
34
+ end.reduce({}, :merge)
35
+ end
36
+
37
+ private
38
+
39
+ attr_accessor :host
40
+
41
+ delegate :netbox_facet, to: :host
42
+ delegate :cached_netbox_params, to: :netbox_facet
43
+
44
+ def netbox_compute_attributes
45
+ @netbox_compute_attributes ||= host.compute_object.yield_self do |compute_object|
46
+ {
47
+ vcpus: compute_object&.cpus,
48
+ memory: compute_object&.memory_mb,
49
+ disk: compute_object&.volumes&.map(&:size_gb)&.reduce(&:+),
50
+ cluster: compute_object&.cluster
51
+ }.compact
52
+ end
53
+ end
54
+
55
+ def tenant
56
+ {
57
+ tenant: {
58
+ name: host.owner&.netbox_tenant_name,
59
+ slug: host.owner&.netbox_tenant_slug,
60
+ tags: DEFAULT_TAGS
61
+ }
62
+ }
63
+ end
64
+
65
+ def device
66
+ {
67
+ device: {
68
+ name: host.name,
69
+ serial: host.facts.deep_symbolize_keys[:serialnumber],
70
+ tags: DEFAULT_TAGS
71
+ }
72
+ }
73
+ end
74
+
75
+ def device_role
76
+ {
77
+ device_role: DEVICE_ROLE
78
+ }
79
+ end
80
+
81
+ def device_type
82
+ model = host.facts.deep_symbolize_keys[:productname] || host.facts.deep_symbolize_keys[:'dmi::product::name'] || UNKNOWN
83
+
84
+ {
85
+ device_type: {
86
+ model: model,
87
+ slug: model.parameterize,
88
+ tags: DEFAULT_TAGS
89
+ }
90
+ }
91
+ end
92
+
93
+ def manufacturer
94
+ name = host.facts.deep_symbolize_keys[:manufacturer] || host.facts.deep_symbolize_keys[:'dmi::manufacturer'] || UNKNOWN
95
+
96
+ {
97
+ manufacturer: {
98
+ name: name,
99
+ slug: cached_netbox_params.dig(:manufacturer, :slug) || name.parameterize
100
+ }
101
+ }
102
+ end
103
+
104
+ def site
105
+ {
106
+ site: {
107
+ name: host.location&.netbox_site_name,
108
+ slug: host.location&.netbox_site_slug,
109
+ tags: DEFAULT_TAGS
110
+ }
111
+ }
112
+ end
113
+
114
+ def interfaces
115
+ {
116
+ interfaces: host.interfaces.map do |interface|
117
+ identifier = interface.identifier.present? && interface.identifier
118
+ mac_address = interface.mac&.upcase
119
+
120
+ {
121
+ name: identifier || (mac_address && "Interface #{mac_address}"),
122
+ mac_address: mac_address,
123
+ type: {
124
+ value: DEFAULT_INTERFACE_TYPE
125
+ },
126
+ tags: DEFAULT_TAGS
127
+ }
128
+ end
129
+ }
130
+ end
131
+
132
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
133
+ def ip_addresses
134
+ {
135
+ ip_addresses: host.interfaces.map do |interface|
136
+ [
137
+ interface.ip && interface.subnet && "#{interface.ip}/#{interface.subnet.cidr}",
138
+ interface.ip6 && interface.subnet6 && "#{interface.ip6}/#{interface.subnet6.cidr}"
139
+ ].compact.map do |ip_address|
140
+ identifier = interface.identifier.present? && interface.identifier
141
+ mac_address = interface.mac&.upcase
142
+
143
+ {
144
+ address: ip_address,
145
+ interface: {
146
+ name: identifier || (mac_address && "Interface #{mac_address}")
147
+ },
148
+ tags: DEFAULT_TAGS
149
+ }
150
+ end
151
+ end.flatten
152
+ }
153
+ end
154
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
155
+
156
+ def virtual_machine
157
+ {
158
+ virtual_machine: netbox_compute_attributes.slice(
159
+ :vcpus, :memory, :disk
160
+ ).merge(
161
+ name: host.name,
162
+ tags: DEFAULT_TAGS
163
+ )
164
+ }
165
+ end
166
+
167
+ def cluster
168
+ {
169
+ cluster: {
170
+ name: netbox_compute_attributes[:cluster],
171
+ tags: DEFAULT_TAGS
172
+ }.compact
173
+ }
174
+ end
175
+
176
+ def cluster_type
177
+ type = host.compute_resource&.type&.to_sym
178
+
179
+ {
180
+ cluster_type: CLUSTER_TYPES.fetch(type, nil)
181
+ }
182
+ end
183
+ end
184
+ # rubocop:enable Metrics/ClassLength
185
+ end