Skip to content

Commit fa92ddb

Browse files
committed
Inventory: Dynamically fetch openapi data
* Gets the API version, to allow working around netbox-community/netbox#3507 in tests * While I'm at it, it also allows fetching allowed_device_query_parameters dynamically instead of hard-coding the list.
1 parent b1b746c commit fa92ddb

File tree

3 files changed

+72
-285
lines changed

3 files changed

+72
-285
lines changed

hacking/get_inventory_query_parameters.py

Lines changed: 0 additions & 43 deletions
This file was deleted.

plugins/inventory/nb_inventory.py

Lines changed: 31 additions & 230 deletions
Original file line numberDiff line numberDiff line change
@@ -218,230 +218,6 @@
218218
ip_interface,
219219
)
220220

221-
# List of parameters fetched from /api/docs/?format=openapi
222-
# Use hacking/get_inventory_query_parameters.py to update this
223-
224-
ALLOWED_DEVICE_QUERY_PARAMETERS = (
225-
"asset_tag",
226-
"asset_tag__ic",
227-
"asset_tag__ie",
228-
"asset_tag__iew",
229-
"asset_tag__isw",
230-
"asset_tag__n",
231-
"asset_tag__nic",
232-
"asset_tag__nie",
233-
"asset_tag__niew",
234-
"asset_tag__nisw",
235-
"cluster_id",
236-
"cluster_id__n",
237-
"console_ports",
238-
"console_server_ports",
239-
"created",
240-
"created__gte",
241-
"created__lte",
242-
"device_bays",
243-
"device_type_id",
244-
"device_type_id__n",
245-
"face",
246-
"face__n",
247-
"has_primary_ip",
248-
"id",
249-
"id__gt",
250-
"id__gte",
251-
"id__lt",
252-
"id__lte",
253-
"id__n",
254-
"interfaces",
255-
"is_full_depth",
256-
"last_updated",
257-
"last_updated__gte",
258-
"last_updated__lte",
259-
"limit",
260-
"local_context_data",
261-
"mac_address",
262-
"mac_address__ic",
263-
"mac_address__ie",
264-
"mac_address__iew",
265-
"mac_address__isw",
266-
"mac_address__n",
267-
"mac_address__nic",
268-
"mac_address__nie",
269-
"mac_address__niew",
270-
"mac_address__nisw",
271-
"manufacturer",
272-
"manufacturer__n",
273-
"manufacturer_id",
274-
"manufacturer_id__n",
275-
"model",
276-
"model__n",
277-
"name",
278-
"name__ic",
279-
"name__ie",
280-
"name__iew",
281-
"name__isw",
282-
"name__n",
283-
"name__nic",
284-
"name__nie",
285-
"name__niew",
286-
"name__nisw",
287-
"offset",
288-
"pass_through_ports",
289-
"platform",
290-
"platform__n",
291-
"platform_id",
292-
"platform_id__n",
293-
"position",
294-
"position__gt",
295-
"position__gte",
296-
"position__lt",
297-
"position__lte",
298-
"position__n",
299-
"power_outlets",
300-
"power_ports",
301-
"q",
302-
"rack_group_id",
303-
"rack_group_id__n",
304-
"rack_id",
305-
"rack_id__n",
306-
"region",
307-
"region__n",
308-
"region_id",
309-
"region_id__n",
310-
"role",
311-
"role__n",
312-
"role_id",
313-
"role_id__n",
314-
"serial",
315-
"site",
316-
"site__n",
317-
"site_id",
318-
"site_id__n",
319-
"status",
320-
"status__n",
321-
"tag",
322-
"tag__n",
323-
"tenant",
324-
"tenant__n",
325-
"tenant_group",
326-
"tenant_group__n",
327-
"tenant_group_id",
328-
"tenant_group_id__n",
329-
"tenant_id",
330-
"tenant_id__n",
331-
"vc_position",
332-
"vc_position__gt",
333-
"vc_position__gte",
334-
"vc_position__lt",
335-
"vc_position__lte",
336-
"vc_position__n",
337-
"vc_priority",
338-
"vc_priority__gt",
339-
"vc_priority__gte",
340-
"vc_priority__lt",
341-
"vc_priority__lte",
342-
"vc_priority__n",
343-
"virtual_chassis_id",
344-
"virtual_chassis_id__n",
345-
"virtual_chassis_member",
346-
)
347-
348-
ALLOWED_VM_QUERY_PARAMETERS = (
349-
"cluster",
350-
"cluster__n",
351-
"cluster_group",
352-
"cluster_group__n",
353-
"cluster_group_id",
354-
"cluster_group_id__n",
355-
"cluster_id",
356-
"cluster_id__n",
357-
"cluster_type",
358-
"cluster_type__n",
359-
"cluster_type_id",
360-
"cluster_type_id__n",
361-
"created",
362-
"created__gte",
363-
"created__lte",
364-
"disk",
365-
"disk__gt",
366-
"disk__gte",
367-
"disk__lt",
368-
"disk__lte",
369-
"disk__n",
370-
"id",
371-
"id__gt",
372-
"id__gte",
373-
"id__lt",
374-
"id__lte",
375-
"id__n",
376-
"last_updated",
377-
"last_updated__gte",
378-
"last_updated__lte",
379-
"limit",
380-
"local_context_data",
381-
"mac_address",
382-
"mac_address__ic",
383-
"mac_address__ie",
384-
"mac_address__iew",
385-
"mac_address__isw",
386-
"mac_address__n",
387-
"mac_address__nic",
388-
"mac_address__nie",
389-
"mac_address__niew",
390-
"mac_address__nisw",
391-
"memory",
392-
"memory__gt",
393-
"memory__gte",
394-
"memory__lt",
395-
"memory__lte",
396-
"memory__n",
397-
"name",
398-
"name__ic",
399-
"name__ie",
400-
"name__iew",
401-
"name__isw",
402-
"name__n",
403-
"name__nic",
404-
"name__nie",
405-
"name__niew",
406-
"name__nisw",
407-
"offset",
408-
"platform",
409-
"platform__n",
410-
"platform_id",
411-
"platform_id__n",
412-
"q",
413-
"region",
414-
"region__n",
415-
"region_id",
416-
"region_id__n",
417-
"role",
418-
"role__n",
419-
"role_id",
420-
"role_id__n",
421-
"site",
422-
"site__n",
423-
"site_id",
424-
"site_id__n",
425-
"status",
426-
"status__n",
427-
"tag",
428-
"tag__n",
429-
"tenant",
430-
"tenant__n",
431-
"tenant_group",
432-
"tenant_group__n",
433-
"tenant_group_id",
434-
"tenant_group_id__n",
435-
"tenant_id",
436-
"tenant_id__n",
437-
"vcpus",
438-
"vcpus__gt",
439-
"vcpus__gte",
440-
"vcpus__lt",
441-
"vcpus__lte",
442-
"vcpus__n",
443-
)
444-
445221

446222
class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
447223
NAME = "netbox.netbox.nb_inventory"
@@ -465,12 +241,12 @@ def _fetch_information(self, url):
465241
# occurs if the cache_key is not in the cache or if the cache_key expired
466242
# we need to fetch the URL now
467243
need_to_fetch = True
468-
self.display.v("Not cached, opening url: " + url)
469244
else:
470245
# not reading from cache so do fetch
471246
need_to_fetch = True
472247

473248
if need_to_fetch:
249+
self.display.v("Fetching: " + url)
474250
response = open_url(
475251
url,
476252
headers=self.headers,
@@ -508,7 +284,6 @@ def get_resource_list(self, api_url):
508284

509285
# Handle pagination
510286
while api_url:
511-
self.display.v("Fetching: " + api_url)
512287
api_output = self._fetch_information(api_url)
513288
resources.extend(api_output["results"])
514289
api_url = api_output["next"]
@@ -535,6 +310,13 @@ def query_string(value, separator="&"):
535310
if chunk_size < 1:
536311
chunk_size = 1
537312

313+
if self.api_version == "2.6":
314+
# Issue netbox-community/netbox#3507 was fixed in v2.7.5
315+
# If using NetBox v2.7.0-v2.7.4 will have to manually set max_uri_length to 0,
316+
# but it's probably faster to keep fetch_all: True
317+
# (You should really just upgrade your Netbox install)
318+
chunk_size = 1
319+
538320
resources = []
539321

540322
for i in range(0, len(query_values), chunk_size):
@@ -1071,6 +853,22 @@ def wrapper():
1071853
# Avoid retain cycles
1072854
thread_exceptions = None
1073855

856+
def fetch_api_docs(self):
857+
openapi = self._fetch_information(
858+
self.api_endpoint + "/api/docs/?format=openapi"
859+
)
860+
861+
self.api_version = openapi["info"]["version"]
862+
self.allowed_device_query_parameters = [
863+
p["name"] for p in openapi["paths"]["/dcim/devices/"]["get"]["parameters"]
864+
]
865+
self.allowed_vm_query_parameters = [
866+
p["name"]
867+
for p in openapi["paths"]["/virtualization/virtual-machines/"]["get"][
868+
"parameters"
869+
]
870+
]
871+
1074872
def validate_query_parameter(self, parameter, allowed_query_parameters):
1075873
if not (isinstance(parameter, dict) and len(parameter) == 1):
1076874
self.display.warning(
@@ -1114,27 +912,27 @@ def refresh_url(self):
1114912
if isinstance(self.query_filters, Iterable):
1115913
device_query_parameters.extend(
1116914
self.filter_query_parameters(
1117-
self.query_filters, ALLOWED_DEVICE_QUERY_PARAMETERS
915+
self.query_filters, self.allowed_device_query_parameters
1118916
)
1119917
)
1120918

1121919
vm_query_parameters.extend(
1122920
self.filter_query_parameters(
1123-
self.query_filters, ALLOWED_VM_QUERY_PARAMETERS
921+
self.query_filters, self.allowed_vm_query_parameters
1124922
)
1125923
)
1126924

1127925
if isinstance(self.device_query_filters, Iterable):
1128926
device_query_parameters.extend(
1129927
self.filter_query_parameters(
1130-
self.device_query_filters, ALLOWED_DEVICE_QUERY_PARAMETERS
928+
self.device_query_filters, self.allowed_device_query_parameters
1131929
)
1132930
)
1133931

1134932
if isinstance(self.vm_query_filters, Iterable):
1135933
vm_query_parameters.extend(
1136934
self.filter_query_parameters(
1137-
self.vm_query_filters, ALLOWED_VM_QUERY_PARAMETERS
935+
self.vm_query_filters, self.allowed_vm_query_parameters
1138936
)
1139937
)
1140938

@@ -1354,6 +1152,9 @@ def _get_host_virtual_chassis_master(self, host):
13541152
return master.get("id", None)
13551153

13561154
def main(self):
1155+
# Get info about the API - version, allowed query parameters
1156+
self.fetch_api_docs()
1157+
13571158
self.fetch_hosts()
13581159

13591160
# Interface, and Service lookup will depend on hosts, if option fetch_all is false

0 commit comments

Comments
 (0)