foreman_netbox 1.0.2 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -0
- data/app/contracts/foreman_netbox/device_contract.rb +3 -3
- data/app/contracts/foreman_netbox/params/interface_params.rb +6 -8
- data/app/contracts/foreman_netbox/params/ip_address_params.rb +5 -7
- data/app/contracts/foreman_netbox/params/tenant_params.rb +4 -6
- data/app/contracts/foreman_netbox/virtual_machine_contract.rb +3 -3
- data/app/interactors/foreman_netbox/concerns/assign_tags.rb +21 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/create.rb +3 -1
- data/app/interactors/foreman_netbox/sync_host/sync_device/organizer.rb +1 -0
- data/app/interactors/foreman_netbox/sync_host/sync_device/save_netbox_url.rb +1 -1
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/create.rb +2 -1
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/update.rb +2 -2
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/create.rb +3 -1
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/create.rb +6 -1
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/delete.rb +1 -1
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/update.rb +2 -14
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/update.rb +2 -3
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_site/create.rb +4 -1
- data/app/interactors/foreman_netbox/sync_host/sync_device/sync_site/update.rb +3 -9
- data/app/interactors/foreman_netbox/sync_host/sync_device/update.rb +5 -7
- data/app/interactors/foreman_netbox/sync_host/sync_tags/create.rb +30 -0
- data/app/interactors/foreman_netbox/sync_host/sync_tags/find.rb +26 -0
- data/app/interactors/foreman_netbox/sync_host/sync_tags/organizer.rb +22 -0
- data/app/interactors/foreman_netbox/sync_host/sync_tenant/create.rb +4 -1
- data/app/interactors/foreman_netbox/sync_host/sync_tenant/update.rb +3 -9
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/create.rb +3 -1
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/organizer.rb +1 -0
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/save_netbox_url.rb +1 -1
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/create.rb +3 -1
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/update.rb +3 -9
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/create.rb +6 -1
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/create.rb +7 -2
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/delete.rb +1 -1
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/update.rb +2 -14
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/update.rb +2 -3
- data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/update.rb +3 -7
- data/app/lib/foreman_netbox/api.rb +2 -2
- data/app/models/concerns/foreman_netbox/user_usergroup_common_extensions.rb +1 -1
- data/app/models/orchestration/netbox.rb +4 -1
- data/app/services/foreman_netbox/cached_netbox_parameters.rb +8 -8
- data/app/services/foreman_netbox/netbox_parameters.rb +8 -17
- data/app/services/foreman_netbox/netbox_parameters_comparator.rb +2 -2
- data/db/migrate/20230303095650_fix_netbox_settings_category_to_dsl.rb +9 -0
- data/lib/foreman_netbox/engine.rb +28 -11
- data/lib/foreman_netbox/version.rb +1 -1
- data/test/integration/foreman_netbox/sync_k8s_physical_host_test.rb +12 -8
- data/test/integration/foreman_netbox/sync_rhel_physical_host_test.rb +12 -8
- data/test/integration/foreman_netbox/sync_rhel_virtual_host_test.rb +12 -8
- data/test/interactors/foreman_netbox/sync_host/organizer_test.rb +22 -6
- data/test/interactors/foreman_netbox/sync_host/sync_device/create_test.rb +5 -3
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/create_test.rb +4 -3
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_device_type/update_test.rb +8 -3
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/create_test.rb +8 -4
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/create_test.rb +10 -5
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/delete_test.rb +2 -2
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/sync_ip_addresses/update_test.rb +5 -3
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_interfaces/update_test.rb +7 -5
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_site/create_test.rb +2 -2
- data/test/interactors/foreman_netbox/sync_host/sync_device/sync_site/update_test.rb +4 -3
- data/test/interactors/foreman_netbox/sync_host/sync_device/update_test.rb +49 -5
- data/test/interactors/foreman_netbox/sync_host/sync_tenant/create_test.rb +2 -2
- data/test/interactors/foreman_netbox/sync_host/sync_tenant/update_test.rb +5 -3
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/create_test.rb +4 -3
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/create_test.rb +7 -3
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_cluster/update_test.rb +5 -3
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/create_test.rb +5 -4
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/create_test.rb +9 -7
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/delete_test.rb +2 -2
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/sync_ip_addresses/update_test.rb +13 -4
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/update_test.rb +9 -4
- data/test/interactors/foreman_netbox/sync_host/sync_virtual_machine/update_test.rb +7 -4
- data/test/models/foreman_netbox/usergroup_test.rb +4 -4
- data/test/services/foreman_netbox/netbox_attributes_test.rb +10 -19
- data/test/services/foreman_netbox/netbox_parameters_comparator_test.rb +6 -16
- data/test/test_plugin_helper.rb +10 -3
- metadata +122 -12
- data/app/models/setting/netbox.rb +0 -32
@@ -7,6 +7,7 @@ module ForemanNetbox
|
|
7
7
|
module SyncIpAddresses
|
8
8
|
class Create
|
9
9
|
include ::Interactor
|
10
|
+
include ForemanNetbox::Concerns::AssignTags
|
10
11
|
|
11
12
|
def call
|
12
13
|
netbox_params.fetch(:ip_addresses, []).map do |ip_address|
|
@@ -16,12 +17,16 @@ module ForemanNetbox
|
|
16
17
|
next unless ForemanNetbox::API.client
|
17
18
|
.ipam
|
18
19
|
.ip_addresses
|
19
|
-
.filter(
|
20
|
+
.filter(vminterface_id: interface_id, address: ip_address[:address])
|
20
21
|
.total
|
21
22
|
.zero?
|
22
23
|
|
23
24
|
ForemanNetbox::API.client::IPAM::IpAddress.new(
|
24
|
-
ip_address.slice(:address
|
25
|
+
ip_address.slice(:address)
|
26
|
+
.merge(
|
27
|
+
assigned_object_type: 'virtualization.vminterface', assigned_object_id: interface_id,
|
28
|
+
tags: default_tag_ids
|
29
|
+
)
|
25
30
|
).save
|
26
31
|
end
|
27
32
|
rescue NetboxClientRuby::LocalError, NetboxClientRuby::ClientError, NetboxClientRuby::RemoteError => e
|
@@ -25,7 +25,7 @@ module ForemanNetbox
|
|
25
25
|
.map { |ip| ip.fetch(:address) }
|
26
26
|
|
27
27
|
context.ip_addresses
|
28
|
-
.select { |ip| ip['
|
28
|
+
.select { |ip| ip['assigned_object_type'] == 'virtualization.vminterface' && ip['assigned_object_id'] == netbox_interface.id }
|
29
29
|
.reject { |ip| host_interface_ips.include?(ip['address']) }
|
30
30
|
.each(&:delete)
|
31
31
|
end
|
@@ -7,12 +7,11 @@ module ForemanNetbox
|
|
7
7
|
module SyncIpAddresses
|
8
8
|
class Update
|
9
9
|
include ::Interactor
|
10
|
+
include ForemanNetbox::Concerns::AssignTags
|
10
11
|
|
11
12
|
def call
|
12
13
|
context.ip_addresses.each do |ip_address|
|
13
|
-
|
14
|
-
|
15
|
-
ip_address.tags = (ip_address.tags | new_tags) if new_tags.any?
|
14
|
+
assign_tags_to(ip_address)
|
16
15
|
|
17
16
|
ip_address.save
|
18
17
|
end
|
@@ -20,17 +19,6 @@ module ForemanNetbox
|
|
20
19
|
::Foreman::Logging.logger('foreman_netbox/import').error("#{self.class} error #{e}: #{e.backtrace}")
|
21
20
|
context.fail!(error: "#{self.class}: #{e}")
|
22
21
|
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
delegate :netbox_params, to: :context
|
27
|
-
|
28
|
-
def tags_map
|
29
|
-
netbox_params.fetch(:ip_addresses, [])
|
30
|
-
.each_with_object({}) do |item, memo|
|
31
|
-
memo[item[:address]] = item.fetch(:tags, [])
|
32
|
-
end
|
33
|
-
end
|
34
22
|
end
|
35
23
|
end
|
36
24
|
end
|
data/app/interactors/foreman_netbox/sync_host/sync_virtual_machine/sync_interfaces/update.rb
CHANGED
@@ -6,6 +6,7 @@ module ForemanNetbox
|
|
6
6
|
module SyncInterfaces
|
7
7
|
class Update
|
8
8
|
include ::Interactor
|
9
|
+
include ForemanNetbox::Concerns::AssignTags
|
9
10
|
|
10
11
|
def call
|
11
12
|
context.interfaces.each { |netbox_interface| update(netbox_interface) }
|
@@ -22,9 +23,7 @@ module ForemanNetbox
|
|
22
23
|
return unless new_params
|
23
24
|
|
24
25
|
netbox_interface.mac_address = new_params[:mac_address] if netbox_interface.mac_address != new_params[:mac_address]
|
25
|
-
|
26
|
-
new_tags = new_params.fetch(:tags, []) - netbox_interface.tags
|
27
|
-
netbox_interface.tags = (netbox_interface.tags | new_tags) if new_tags.any?
|
26
|
+
assign_tags_to(netbox_interface)
|
28
27
|
|
29
28
|
netbox_interface.save
|
30
29
|
rescue NetboxClientRuby::LocalError, NetboxClientRuby::ClientError, NetboxClientRuby::RemoteError => e
|
@@ -6,8 +6,9 @@ module ForemanNetbox
|
|
6
6
|
class Update
|
7
7
|
include ::Interactor
|
8
8
|
include ForemanNetbox::Concerns::PrimaryIps
|
9
|
+
include ForemanNetbox::Concerns::AssignTags
|
9
10
|
|
10
|
-
ATTRIBUTES = %i[name cluster disk memory primary_ip4 primary_ip6 tenant vcpus
|
11
|
+
ATTRIBUTES = %i[name cluster disk memory primary_ip4 primary_ip6 tenant vcpus].freeze
|
11
12
|
|
12
13
|
around do |interactor|
|
13
14
|
interactor.call if context.virtual_machine
|
@@ -19,6 +20,7 @@ module ForemanNetbox
|
|
19
20
|
|
20
21
|
def call
|
21
22
|
assign_new_attributes
|
23
|
+
assign_tags_to(virtual_machine)
|
22
24
|
|
23
25
|
virtual_machine.save
|
24
26
|
rescue NetboxClientRuby::LocalError, NetboxClientRuby::ClientError, NetboxClientRuby::RemoteError => e
|
@@ -70,12 +72,6 @@ module ForemanNetbox
|
|
70
72
|
vcpus = netbox_params.dig(:virtual_machine, :vcpus)
|
71
73
|
virtual_machine.vcpus = vcpus if virtual_machine.vcpus != vcpus
|
72
74
|
end
|
73
|
-
|
74
|
-
def assign_tags
|
75
|
-
new_tags = (netbox_params.dig(:virtual_machine, :tags) || []) - virtual_machine.tags
|
76
|
-
|
77
|
-
virtual_machine.tags = (virtual_machine.tags | new_tags) if new_tags.any?
|
78
|
-
end
|
79
75
|
end
|
80
76
|
end
|
81
77
|
end
|
@@ -4,8 +4,8 @@ module ForemanNetbox
|
|
4
4
|
class API
|
5
5
|
def self.client
|
6
6
|
NetboxClientRuby.configure do |config|
|
7
|
-
config.netbox.api_base_url = "#{Setting
|
8
|
-
config.netbox.auth.token = Setting
|
7
|
+
config.netbox.api_base_url = "#{Setting['netbox_url']}/api"
|
8
|
+
config.netbox.auth.token = Setting['netbox_api_token']
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -14,7 +14,7 @@ module Orchestration
|
|
14
14
|
protected
|
15
15
|
|
16
16
|
def netbox_orchestration_allowed?
|
17
|
-
Setting
|
17
|
+
Setting[:netbox_orchestration_enabled] && netbox_will_change?
|
18
18
|
end
|
19
19
|
|
20
20
|
def queue_netbox_push
|
@@ -30,6 +30,9 @@ module Orchestration
|
|
30
30
|
def queue_netbox_destroy
|
31
31
|
return unless errors.empty? && managed?
|
32
32
|
|
33
|
+
::Foreman::Logging.logger('foreman_netbox/import')
|
34
|
+
.info("Queued delete of #{name} from Netbox.")
|
35
|
+
|
33
36
|
queue.create(name: _('Delete host %s from Netbox') % self, priority: 60,
|
34
37
|
action: [self, :del_netbox])
|
35
38
|
end
|
@@ -28,7 +28,7 @@ module ForemanNetbox
|
|
28
28
|
return unless data.keys.include?(:interfaces)
|
29
29
|
|
30
30
|
result[:interfaces] = data.fetch(:interfaces, {}).fetch(:results, []).map do |interface|
|
31
|
-
interface.slice(:name, :mac_address
|
31
|
+
interface.slice(:name, :mac_address)
|
32
32
|
.merge(type: interface.fetch(:type, {}).slice(:value))
|
33
33
|
.compact
|
34
34
|
end
|
@@ -38,7 +38,7 @@ module ForemanNetbox
|
|
38
38
|
return unless data.keys.include?(:ip_addresses)
|
39
39
|
|
40
40
|
result[:ip_addresses] = data.fetch(:ip_addresses, {}).fetch(:results, []).map do |ip_address|
|
41
|
-
ip_address.slice(:address
|
41
|
+
ip_address.slice(:address)
|
42
42
|
.merge(interface: ip_address.fetch(:interface, {}).slice(:name))
|
43
43
|
end
|
44
44
|
end
|
@@ -46,19 +46,19 @@ module ForemanNetbox
|
|
46
46
|
def read_virtual_machine
|
47
47
|
return unless data.keys.include?(:virtual_machine)
|
48
48
|
|
49
|
-
result[:virtual_machine] = data.fetch(:virtual_machine, {}).slice(:name, :vcpus, :memory, :disk
|
49
|
+
result[:virtual_machine] = data.fetch(:virtual_machine, {}).slice(:name, :vcpus, :memory, :disk)
|
50
50
|
end
|
51
51
|
|
52
52
|
def read_tenant
|
53
53
|
return unless data.keys.include?(:tenant)
|
54
54
|
|
55
|
-
result[:tenant] = data.fetch(:tenant, {}).slice(:name, :slug
|
55
|
+
result[:tenant] = data.fetch(:tenant, {}).slice(:name, :slug)
|
56
56
|
end
|
57
57
|
|
58
58
|
def read_cluster
|
59
59
|
return unless data.keys.include?(:cluster)
|
60
60
|
|
61
|
-
result[:cluster] = data.fetch(:cluster, {}).slice(:name
|
61
|
+
result[:cluster] = data.fetch(:cluster, {}).slice(:name)
|
62
62
|
end
|
63
63
|
|
64
64
|
def read_cluster_type
|
@@ -71,7 +71,7 @@ module ForemanNetbox
|
|
71
71
|
return unless data.keys.include?(:device)
|
72
72
|
|
73
73
|
result[:device] = data.fetch(:device, {})
|
74
|
-
.slice(:name, :serial
|
74
|
+
.slice(:name, :serial)
|
75
75
|
.compact
|
76
76
|
.reject { |k, v| k == :serial && v.blank? }
|
77
77
|
end
|
@@ -85,7 +85,7 @@ module ForemanNetbox
|
|
85
85
|
def read_device_type
|
86
86
|
return unless data.keys.include?(:device_type)
|
87
87
|
|
88
|
-
result[:device_type] = data.fetch(:device_type, {}).slice(:model, :slug
|
88
|
+
result[:device_type] = data.fetch(:device_type, {}).slice(:model, :slug)
|
89
89
|
end
|
90
90
|
|
91
91
|
def read_manufacturer
|
@@ -97,7 +97,7 @@ module ForemanNetbox
|
|
97
97
|
def read_site
|
98
98
|
return unless data.keys.include?(:site)
|
99
99
|
|
100
|
-
result[:site] = data.fetch(:site, {}).slice(:name, :slug
|
100
|
+
result[:site] = data.fetch(:site, {}).slice(:name, :slug)
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
@@ -4,7 +4,6 @@ module ForemanNetbox
|
|
4
4
|
# rubocop:disable Metrics/ClassLength
|
5
5
|
class NetboxParameters
|
6
6
|
UNKNOWN = 'Unknown'
|
7
|
-
DEFAULT_TAGS = ['foreman'].freeze
|
8
7
|
DEFAULT_INTERFACE_TYPE = 'virtual'
|
9
8
|
CLUSTER_TYPES = {
|
10
9
|
:'Foreman::Model::Vmware' => {
|
@@ -56,8 +55,7 @@ module ForemanNetbox
|
|
56
55
|
{
|
57
56
|
tenant: {
|
58
57
|
name: host.owner&.netbox_tenant_name,
|
59
|
-
slug: host.owner&.netbox_tenant_slug
|
60
|
-
tags: DEFAULT_TAGS
|
58
|
+
slug: host.owner&.netbox_tenant_slug
|
61
59
|
}
|
62
60
|
}
|
63
61
|
end
|
@@ -66,8 +64,7 @@ module ForemanNetbox
|
|
66
64
|
{
|
67
65
|
device: {
|
68
66
|
name: host.name,
|
69
|
-
serial: host.facts.deep_symbolize_keys[:serialnumber]
|
70
|
-
tags: DEFAULT_TAGS
|
67
|
+
serial: host.facts.deep_symbolize_keys[:serialnumber]
|
71
68
|
}
|
72
69
|
}
|
73
70
|
end
|
@@ -84,8 +81,7 @@ module ForemanNetbox
|
|
84
81
|
{
|
85
82
|
device_type: {
|
86
83
|
model: model,
|
87
|
-
slug: model.parameterize
|
88
|
-
tags: DEFAULT_TAGS
|
84
|
+
slug: model.parameterize
|
89
85
|
}
|
90
86
|
}
|
91
87
|
end
|
@@ -105,8 +101,7 @@ module ForemanNetbox
|
|
105
101
|
{
|
106
102
|
site: {
|
107
103
|
name: host.location&.netbox_site_name,
|
108
|
-
slug: host.location&.netbox_site_slug
|
109
|
-
tags: DEFAULT_TAGS
|
104
|
+
slug: host.location&.netbox_site_slug
|
110
105
|
}
|
111
106
|
}
|
112
107
|
end
|
@@ -122,8 +117,7 @@ module ForemanNetbox
|
|
122
117
|
mac_address: mac_address,
|
123
118
|
type: {
|
124
119
|
value: DEFAULT_INTERFACE_TYPE
|
125
|
-
}
|
126
|
-
tags: DEFAULT_TAGS
|
120
|
+
}
|
127
121
|
}
|
128
122
|
end
|
129
123
|
}
|
@@ -144,8 +138,7 @@ module ForemanNetbox
|
|
144
138
|
address: ip_address,
|
145
139
|
interface: {
|
146
140
|
name: identifier || (mac_address && "Interface #{mac_address}")
|
147
|
-
}
|
148
|
-
tags: DEFAULT_TAGS
|
141
|
+
}
|
149
142
|
}
|
150
143
|
end
|
151
144
|
end.flatten
|
@@ -158,8 +151,7 @@ module ForemanNetbox
|
|
158
151
|
virtual_machine: netbox_compute_attributes.slice(
|
159
152
|
:vcpus, :memory, :disk
|
160
153
|
).merge(
|
161
|
-
name: host.name
|
162
|
-
tags: DEFAULT_TAGS
|
154
|
+
name: host.name
|
163
155
|
)
|
164
156
|
}
|
165
157
|
end
|
@@ -167,8 +159,7 @@ module ForemanNetbox
|
|
167
159
|
def cluster
|
168
160
|
{
|
169
161
|
cluster: {
|
170
|
-
name: netbox_compute_attributes[:cluster]
|
171
|
-
tags: DEFAULT_TAGS
|
162
|
+
name: netbox_compute_attributes[:cluster]
|
172
163
|
}.compact
|
173
164
|
}
|
174
165
|
end
|
@@ -48,7 +48,7 @@ module ForemanNetbox
|
|
48
48
|
|
49
49
|
memo[key] = diff
|
50
50
|
elsif old_value.is_a?(Array)
|
51
|
-
next
|
51
|
+
next if new_hash[key]
|
52
52
|
|
53
53
|
memo[key] = { added: [], removed: old_value }
|
54
54
|
else
|
@@ -77,7 +77,7 @@ module ForemanNetbox
|
|
77
77
|
elsif new_value.is_a?(Array)
|
78
78
|
old_value = old_hash.fetch(key, [])
|
79
79
|
added = new_value.reject { |item| old_value.find { |x| x == item } }
|
80
|
-
removed =
|
80
|
+
removed = old_value.reject { |item| new_value.find { |x| x == item } }
|
81
81
|
|
82
82
|
next unless added.any? || removed.any?
|
83
83
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class FixNetboxSettingsCategoryToDsl < ActiveRecord::Migration[6.0]
|
4
|
+
def up
|
5
|
+
# rubocop:disable Rails/SkipsModelValidations
|
6
|
+
Setting.where(category: 'Setting::Netbox').update_all(category: 'Setting') if column_exists?(:settings, :category)
|
7
|
+
# rubocop:enable Rails/SkipsModelValidations
|
8
|
+
end
|
9
|
+
end
|
@@ -10,14 +10,6 @@ module ForemanNetbox
|
|
10
10
|
|
11
11
|
config.autoload_paths += Dir["#{config.root}/app/interactors"]
|
12
12
|
|
13
|
-
initializer 'foreman_netbox.load_default_settings', before: :load_config_initializers do
|
14
|
-
require_dependency File.expand_path('../../app/models/setting/netbox.rb', __dir__) if begin
|
15
|
-
Setting.table_exists?
|
16
|
-
rescue StandardError
|
17
|
-
(false)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
13
|
# Add any db migrations
|
22
14
|
initializer 'foreman_netbox.load_app_instance_data' do |app|
|
23
15
|
ForemanNetbox::Engine.paths['db/migrate'].existent.each do |path|
|
@@ -27,7 +19,7 @@ module ForemanNetbox
|
|
27
19
|
|
28
20
|
initializer 'foreman_netbox.register_plugin', :before => :finisher_hook do |_app|
|
29
21
|
Foreman::Plugin.register :foreman_netbox do
|
30
|
-
requires_foreman '>= 1
|
22
|
+
requires_foreman '>= 3.1'
|
31
23
|
|
32
24
|
# Netbox Facet
|
33
25
|
register_facet(ForemanNetbox::NetboxFacet, :netbox_facet) do
|
@@ -42,6 +34,31 @@ module ForemanNetbox
|
|
42
34
|
onlyif: proc { |host| host.netbox_facet.synchronized_at }
|
43
35
|
end
|
44
36
|
|
37
|
+
settings do
|
38
|
+
category(:netbox, N_('Netbox')) do
|
39
|
+
setting 'netbox_url',
|
40
|
+
type: :string,
|
41
|
+
default: '-',
|
42
|
+
full_name: N_('Netbox URL'),
|
43
|
+
description: N_('URL where Netbox is reachable')
|
44
|
+
setting 'netbox_api_token',
|
45
|
+
type: :string,
|
46
|
+
default: '-',
|
47
|
+
full_name: N_('Netbox API token'),
|
48
|
+
description: N_('API token to Netbox')
|
49
|
+
setting 'netbox_orchestration_enabled',
|
50
|
+
type: :boolean,
|
51
|
+
default: false,
|
52
|
+
full_name: N_('Netbox Orchestration'),
|
53
|
+
description: N_('Enable Netbox Orchestration')
|
54
|
+
setting 'netbox_skip_site_update',
|
55
|
+
type: :boolean,
|
56
|
+
default: false,
|
57
|
+
full_name: N_('Skip Site Update'),
|
58
|
+
description: N_('Skip updating Site attribute for Devices')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
45
62
|
logger :import, enabled: true
|
46
63
|
end
|
47
64
|
end
|
@@ -54,8 +71,8 @@ module ForemanNetbox
|
|
54
71
|
::Usergroup.include(ForemanNetbox::UserUsergroupCommonExtensions)
|
55
72
|
|
56
73
|
NetboxClientRuby.configure do |config|
|
57
|
-
config.netbox.api_base_url = Setting
|
58
|
-
config.netbox.auth.token = Setting
|
74
|
+
config.netbox.api_base_url = Setting['netbox_url']
|
75
|
+
config.netbox.auth.token = Setting['netbox_api_token']
|
59
76
|
end
|
60
77
|
rescue StandardError => e
|
61
78
|
Rails.logger.warn "ForemanNetbox: skipping engine hook (#{e})\n#{e.backtrace.join("\n")}"
|
@@ -62,20 +62,24 @@ class SyncK8sPhysicalHostTest < ActiveSupport::TestCase
|
|
62
62
|
assert nx_interface.present?
|
63
63
|
|
64
64
|
h_interface.netbox_ips.each do |h_ip|
|
65
|
-
assert subject.ip_addresses.find
|
65
|
+
assert subject.ip_addresses.find do |nx_ip|
|
66
|
+
nx_ip.interface.assigned_object_type == 'dcim.interface' &&
|
67
|
+
nx_ip.interface.assigned_object_id == nx_interface.id &&
|
68
|
+
nx_ip.address == IPAddress.parse(h_ip)
|
69
|
+
end.present?
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
73
|
+
expected_tag_ids = subject.tags.pluck('id')
|
74
|
+
assert (expected_tag_ids - subject.device.tags.pluck('id')).empty?
|
75
|
+
assert (expected_tag_ids - subject.device_type.tags.pluck('id')).empty?
|
76
|
+
assert (expected_tag_ids - subject.site.tags.pluck('id')).empty?
|
77
|
+
assert (expected_tag_ids - subject.tenant.tags.pluck('id')).empty?
|
74
78
|
subject.interfaces.reload.each do |interface|
|
75
|
-
|
79
|
+
assert (expected_tag_ids - interface.tags.pluck('id')).empty?
|
76
80
|
end
|
77
81
|
subject.ip_addresses.reload.each do |interface|
|
78
|
-
|
82
|
+
assert (expected_tag_ids - interface.tags.pluck('id')).empty?
|
79
83
|
end
|
80
84
|
end
|
81
85
|
end
|
@@ -62,20 +62,24 @@ class SyncRhelPhysicalHostTest < ActiveSupport::TestCase
|
|
62
62
|
assert nx_interface.present?
|
63
63
|
|
64
64
|
h_interface.netbox_ips.each do |h_ip|
|
65
|
-
assert subject.ip_addresses.find
|
65
|
+
assert subject.ip_addresses.find do |nx_ip|
|
66
|
+
nx_ip.interface.assigned_object_type == 'dcim.interface' &&
|
67
|
+
nx_ip.interface.assigned_object_id == nx_interface.id &&
|
68
|
+
nx_ip.address == IPAddress.parse(h_ip)
|
69
|
+
end.present?
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
73
|
+
expected_tag_ids = subject.tags.pluck('id')
|
74
|
+
assert (expected_tag_ids - subject.device.tags.pluck('id')).empty?
|
75
|
+
assert (expected_tag_ids - subject.device_type.tags.pluck('id')).empty?
|
76
|
+
assert (expected_tag_ids - subject.site.tags.pluck('id')).empty?
|
77
|
+
assert (expected_tag_ids - subject.tenant.tags.pluck('id')).empty?
|
74
78
|
subject.interfaces.reload.each do |interface|
|
75
|
-
|
79
|
+
assert (expected_tag_ids - interface.tags.pluck('id')).empty?
|
76
80
|
end
|
77
81
|
subject.ip_addresses.reload.each do |interface|
|
78
|
-
|
82
|
+
assert (expected_tag_ids - interface.tags.pluck('id')).empty?
|
79
83
|
end
|
80
84
|
end
|
81
85
|
end
|
@@ -61,7 +61,7 @@ class SyncRhelVirtualHostTest < ActiveSupport::TestCase
|
|
61
61
|
|
62
62
|
assert_equal host.name, subject.virtual_machine.name
|
63
63
|
assert_equal host.owner.netbox_tenant_name, subject.virtual_machine.tenant.name
|
64
|
-
assert_equal host.compute_object.cpus,
|
64
|
+
assert_equal host.compute_object.cpus.to_f, subject.virtual_machine.vcpus
|
65
65
|
assert_equal host.compute_object.memory_mb, subject.virtual_machine.memory
|
66
66
|
assert_equal host.compute_object.volumes.first.size_gb, subject.virtual_machine.disk
|
67
67
|
assert_equal host.compute_object.cluster, subject.virtual_machine.cluster.name
|
@@ -75,19 +75,23 @@ class SyncRhelVirtualHostTest < ActiveSupport::TestCase
|
|
75
75
|
assert nx_interface.present?
|
76
76
|
|
77
77
|
h_interface.netbox_ips.each do |h_ip|
|
78
|
-
assert subject.ip_addresses.find
|
78
|
+
assert subject.ip_addresses.find do |nx_ip|
|
79
|
+
nx_ip.interface.assigned_object_type == 'virtualization.vminterface' &&
|
80
|
+
nx_ip.interface.assigned_object_id == nx_interface.id &&
|
81
|
+
nx_ip.address == IPAddress.parse(h_ip)
|
82
|
+
end.present?
|
79
83
|
end
|
80
84
|
end
|
81
85
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
+
expected_tag_ids = subject.tags.pluck('id')
|
87
|
+
assert (expected_tag_ids - subject.virtual_machine.tags.pluck('id')).empty?
|
88
|
+
assert (expected_tag_ids - subject.tenant.tags.pluck('id')).empty?
|
89
|
+
assert (expected_tag_ids - subject.cluster.tags.pluck('id')).empty?
|
86
90
|
subject.interfaces.reload.each do |interface|
|
87
|
-
|
91
|
+
assert (expected_tag_ids - interface.tags.pluck('id')).empty?
|
88
92
|
end
|
89
93
|
subject.ip_addresses.reload.each do |interface|
|
90
|
-
|
94
|
+
assert (expected_tag_ids - interface.tags.pluck('id')).empty?
|
91
95
|
end
|
92
96
|
end
|
93
97
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'test_plugin_helper'
|
4
4
|
|
5
5
|
class SyncHostOrganizerTest < ActiveSupport::TestCase
|
6
|
-
subject { ForemanNetbox::SyncHost::Organizer.call(host: host) }
|
6
|
+
subject { ForemanNetbox::SyncHost::Organizer.call(host: host, tags: default_tags) }
|
7
7
|
|
8
8
|
let(:host) do
|
9
9
|
FactoryBot.create(:host).tap do |host|
|
@@ -11,11 +11,27 @@ class SyncHostOrganizerTest < ActiveSupport::TestCase
|
|
11
11
|
host.stubs(:facts).returns({ serialnumber: 'abc123' })
|
12
12
|
end
|
13
13
|
end
|
14
|
-
let(:tags)
|
14
|
+
let(:tags) do
|
15
|
+
default_tags.map { |t| { 'id' => t.id, 'name' => t.name, 'slug' => t.slug } }
|
16
|
+
end
|
15
17
|
|
16
18
|
setup do
|
17
19
|
setup_default_netbox_settings
|
18
20
|
# rubocop:disable Layout/FirstArrayElementIndentation
|
21
|
+
default_tags.each do |tag|
|
22
|
+
stub_get_netbox_request("extras/tags.json?limit=50&slug=#{tag.slug}", results: [
|
23
|
+
{ id: tag.id, name: tag.name, slug: tag.slug }
|
24
|
+
])
|
25
|
+
stub_request(:get, "#{Setting[:netbox_url]}/api/extras/tags/#{tag.id}.json")
|
26
|
+
.to_return(
|
27
|
+
status: 200, headers: { 'Content-Type': 'application/json' },
|
28
|
+
body: {
|
29
|
+
id: tag.id,
|
30
|
+
name: tag.name,
|
31
|
+
slug: tag.slug
|
32
|
+
}.to_json
|
33
|
+
)
|
34
|
+
end
|
19
35
|
stub_get_netbox_request('tenancy/tenants.json?limit=50&slug=admin-user', results: [
|
20
36
|
{ id: 1, name: host.owner.name, slug: host.owner.name.parameterize, tags: tags }
|
21
37
|
])
|
@@ -40,7 +56,7 @@ class SyncHostOrganizerTest < ActiveSupport::TestCase
|
|
40
56
|
end
|
41
57
|
|
42
58
|
test 'save synchronization status when it succeeds' do
|
43
|
-
stub_request(:patch, "#{Setting
|
59
|
+
stub_request(:patch, "#{Setting[:netbox_url]}/api/dcim/devices/1.json").to_return(
|
44
60
|
status: 200, headers: { 'Content-Type': 'application/json' },
|
45
61
|
body: { id: 1 }.to_json
|
46
62
|
)
|
@@ -48,12 +64,12 @@ class SyncHostOrganizerTest < ActiveSupport::TestCase
|
|
48
64
|
host.reload
|
49
65
|
|
50
66
|
assert_not_nil host.netbox_facet.synchronized_at
|
51
|
-
assert_equal "#{Setting
|
67
|
+
assert_equal "#{Setting[:netbox_url]}/dcim/devices/1", host.netbox_facet.url
|
52
68
|
assert_nil host.netbox_facet.synchronization_error
|
53
69
|
end
|
54
70
|
|
55
71
|
test 'save synchronization status when it fails' do
|
56
|
-
stub_request(:patch, "#{Setting
|
72
|
+
stub_request(:patch, "#{Setting[:netbox_url]}/api/dcim/devices/1.json").to_return(
|
57
73
|
status: 500, headers: { 'Content-Type': 'application/json' }
|
58
74
|
)
|
59
75
|
subject
|
@@ -67,7 +83,7 @@ class SyncHostOrganizerTest < ActiveSupport::TestCase
|
|
67
83
|
private
|
68
84
|
|
69
85
|
def stub_get_netbox_request(path, results:)
|
70
|
-
stub_request(:get, "#{Setting
|
86
|
+
stub_request(:get, "#{Setting[:netbox_url]}/api/#{path}").to_return(
|
71
87
|
status: 200, headers: { 'Content-Type': 'application/json' },
|
72
88
|
body: {
|
73
89
|
count: 1,
|
@@ -11,7 +11,8 @@ class CreateDeviceTest < ActiveSupport::TestCase
|
|
11
11
|
device_role: device_role,
|
12
12
|
site: site,
|
13
13
|
tenant: tenant,
|
14
|
-
device: device
|
14
|
+
device: device,
|
15
|
+
tags: tags
|
15
16
|
)
|
16
17
|
end
|
17
18
|
|
@@ -26,6 +27,7 @@ class CreateDeviceTest < ActiveSupport::TestCase
|
|
26
27
|
let(:site) { OpenStruct.new(id: 1) }
|
27
28
|
let(:tenant) { OpenStruct.new(id: 1) }
|
28
29
|
let(:netbox_device_params) { host.netbox_facet.netbox_params.fetch(:device) }
|
30
|
+
let(:tags) { [ForemanNetbox::API.client::Extras::Tag.new(id: 1, name: 'foreman', slug: 'foreman')] }
|
29
31
|
|
30
32
|
setup do
|
31
33
|
setup_default_netbox_settings
|
@@ -39,11 +41,11 @@ class CreateDeviceTest < ActiveSupport::TestCase
|
|
39
41
|
body: {
|
40
42
|
name: netbox_device_params[:name],
|
41
43
|
serial: netbox_device_params[:serial],
|
42
|
-
tags: netbox_device_params[:tags],
|
43
44
|
device_type: device_type.id,
|
44
45
|
device_role: device_role.id,
|
45
46
|
site: site.id,
|
46
|
-
tenant: tenant.id
|
47
|
+
tenant: tenant.id,
|
48
|
+
tags: tags.map(&:id)
|
47
49
|
}.to_json
|
48
50
|
).to_return(
|
49
51
|
status: 201, headers: { 'Content-Type': 'application/json' },
|
@@ -8,7 +8,8 @@ class CreateDeviceTypeTest < ActiveSupport::TestCase
|
|
8
8
|
netbox_params: host.netbox_facet.netbox_params,
|
9
9
|
device_type: device_type,
|
10
10
|
manufacturer: manufacturer,
|
11
|
-
host: host
|
11
|
+
host: host,
|
12
|
+
tags: default_tags
|
12
13
|
)
|
13
14
|
end
|
14
15
|
|
@@ -32,8 +33,8 @@ class CreateDeviceTypeTest < ActiveSupport::TestCase
|
|
32
33
|
body: {
|
33
34
|
model: host.netbox_facet.netbox_params.dig(:device_type, :model),
|
34
35
|
slug: host.netbox_facet.netbox_params.dig(:device_type, :slug),
|
35
|
-
|
36
|
-
|
36
|
+
manufacturer: manufacturer.id,
|
37
|
+
tags: default_tags.map(&:id)
|
37
38
|
}.to_json
|
38
39
|
).to_return(
|
39
40
|
status: 201, headers: { 'Content-Type': 'application/json' },
|