Skip to content

Commit 01b3be5

Browse files
authored
Netbox: handle different host url in 'next' section of the response (#850)
* netbox: handle next page url with different host The next url might contain a different url if netbox is behind a reverse proxy. This commit sets the protocol, the host and the port of the next page request to the same parameters of the previous request which was successful Signed-off-by: LucaNicosia <[email protected]> * controller: add debug log Signed-off-by: LucaNicosia <[email protected]> * controller test fixes Signed-off-by: LucaNicosia <[email protected]> --------- Signed-off-by: LucaNicosia <[email protected]>
1 parent d40b8a6 commit 01b3be5

File tree

3 files changed

+60
-1
lines changed

3 files changed

+60
-1
lines changed

suzieq/poller/controller/controller.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ async def _inventory_sync(self):
318318
'too much time'
319319
)
320320

321+
logger.debug(f'Received inventory from {inv_src.name}')
321322
if cur_inv:
322323
cur_inv_count = len(cur_inv)
323324
duplicated_devices = [x for x in cur_inv

suzieq/poller/controller/source/netbox.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,60 @@ async def _get_devices(self, url: str) -> Tuple[List, str]:
242242
async with self._session.get(url) as response:
243243
if int(response.status) == 200:
244244
res = await response.json()
245-
return res.get('results', []), res.get('next')
245+
next_url = res.get('next')
246+
if next_url:
247+
# The next url might contain a different url if netbox is
248+
# behind a reverse proxy.
249+
# The code below sets the protocol, the host and the port
250+
# of the next request to the same parameters of the
251+
# previous request which was successful
252+
253+
logger.debug(f'Parsing next page url {next_url}')
254+
255+
# parse urls
256+
url_data = urlparse(url)
257+
next_url_data = urlparse(next_url)
258+
259+
# retrieve protocol, host and port from the urls
260+
host = url_data.hostname
261+
protocol = url_data.scheme or 'http'
262+
port = url_data.port or _DEFAULT_PORTS.get(protocol)
263+
264+
next_host = next_url_data.hostname
265+
next_protocol = next_url_data.scheme or 'http'
266+
next_port = (next_url_data.port or
267+
_DEFAULT_PORTS.get(next_protocol))
268+
269+
# verify if the two elements are different. If so, log
270+
# what's different and set the value to content of the
271+
# previous url
272+
if host != next_host:
273+
logger.debug(
274+
'Detected a different host in response: original '
275+
f'host "{host}", received host "{next_host}". '
276+
f'Setting the request host to "{host}"'
277+
)
278+
next_host = host
279+
if protocol != next_protocol:
280+
logger.debug(
281+
'Detected a different protocol in response: '
282+
f'original protocol "{protocol}", received '
283+
f'protocol "{next_protocol}". Setting the request '
284+
f'protocol to "{protocol}"'
285+
)
286+
next_protocol = protocol
287+
if port != next_port:
288+
logger.debug(
289+
'Detected a different port in response: original '
290+
f'port "{port}", received port "{next_port}". '
291+
f'Setting the request port to "{port}"'
292+
)
293+
next_port = port
294+
295+
# build the next_url
296+
next_url = (f'{next_protocol}://{next_host}:{next_port}'
297+
f'{next_url_data.path}?{next_url_data.query}')
298+
return res.get('results', []), next_url
246299
else:
247300
raise InventorySourceError(
248301
f'{self.name}: error in inventory get '

tests/unit/poller/controller/test_controller.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@ def mock_src_init(self, inv, validate=False):
256256
self.set_device()
257257
self._load(inv)
258258

259+
def mock_get_name(self):
260+
return self._name
261+
259262
def mock_set_inventory(self, inv):
260263
self._inventory = inv.copy()
261264
if not self._inv_is_set:
@@ -284,12 +287,14 @@ def mock_chunk(self, inv, n):
284287
native_mock = patch.multiple(SqNativeFile, __init__=mock_src_init,
285288
set_inventory=mock_set_inventory,
286289
get_inventory=mock_get_inventory,
290+
name=mock_get_name,
287291
_load=mock_native_load,
288292
set_device=MagicMock())
289293

290294
netbox_mock = patch.multiple(Netbox, __init__=mock_src_init,
291295
set_inventory=mock_set_inventory,
292296
get_inventory=mock_get_inventory,
297+
name=mock_get_name,
293298
_load=MagicMock(), run=mock_netbox_run,
294299
set_device=MagicMock())
295300

0 commit comments

Comments
 (0)