Skip to content

Commit eddb708

Browse files
authored
Inventory source misc bug fixes (#917)
* DeviceModel: fix port type to 'int' Signed-off-by: LucaNicosia <[email protected]> * native source: do not set up default port The default port must be set up depending on the device data, which is not accessible within the source. The default port assignment will be performed in the function `set_device` of base_source Signed-off-by: LucaNicosia <[email protected]> * base_source: default port + inventory keys fix Sometimes sources doesn't return the device port: - netbox: never return the port - native: if not specified on the host If the port is not specified, the inventory key (which is computed using namespace, address and port) will be incomplete. In order to fix this issue, we correctly set the port to these items and recreate the keys with the correct port Signed-off-by: LucaNicosia <[email protected]> * new tests + test fixes Signed-off-by: LucaNicosia <[email protected]> * unrelated test fix this test passes locally, but somehow it doesn't on github. setting the env-var to an empty value should fix this issue Signed-off-by: LucaNicosia <[email protected]> --------- Signed-off-by: LucaNicosia <[email protected]>
1 parent 091d784 commit eddb708

File tree

9 files changed

+146
-33
lines changed

9 files changed

+146
-33
lines changed

suzieq/poller/controller/source/base_source.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ def set_device(self, inventory: Dict[str, Dict]):
210210
slow_host = False
211211
per_cmd_auth = True
212212
retries_on_auth_fail = 0
213-
port = None
213+
dev_port = None
214214
devtype = None
215215

216216
if self._device:
@@ -231,21 +231,25 @@ def set_device(self, inventory: Dict[str, Dict]):
231231
slow_host = self._device.get('slow-host', False)
232232
per_cmd_auth = self._device.get('per-cmd-auth', True)
233233
retries_on_auth_fail = self._device.get('retries-on-auth-fail', 0)
234-
port = self._device.get('port')
234+
dev_port = self._device.get('port')
235235
devtype = self._device.get('devtype')
236236

237-
for node in inventory.values():
237+
node_keys_to_remove = []
238+
nodes_to_add = {}
239+
for node_name, node in inventory.items():
238240
transport_tmp = node.get('transport') or transport or 'ssh'
239241
ignore_known_hosts_tmp = node.get('ignore_known_hosts')
242+
missing_node_port = not (node_port := node.get('port'))
243+
if missing_node_port:
244+
node_port = dev_port or _DEFAULT_PORTS.get(transport_tmp)
240245
node.update({
241246
'jump_host': node.get('jump_host') or jump_host,
242247
'jump_host_key_file': node.get('jump_host_key_file')
243248
or jump_host_key_file,
244249
'ignore_known_hosts': ignore_known_hosts_tmp if
245250
ignore_known_hosts_tmp is not None else ignore_known_hosts,
246251
'transport': transport_tmp,
247-
'port': node.get('port') or port or
248-
_DEFAULT_PORTS.get(transport_tmp),
252+
'port': node_port,
249253
'devtype': node.get('devtype') or devtype,
250254
'slow_host': node.get('slow_host', '') or slow_host,
251255
'per_cmd_auth': ((node.get('per_cmd_auth', '') != '')
@@ -254,6 +258,25 @@ def set_device(self, inventory: Dict[str, Dict]):
254258
-1) != -1) or
255259
retries_on_auth_fail)
256260
})
261+
if missing_node_port:
262+
# An inventory key is composed by
263+
# '{namespace}.{address}.{port}'. If the node port is missing,
264+
# the key generated is not complete.
265+
# We need to assign the node to a correct key. Since we are
266+
# looping on the items in the inventory, we cannot update it
267+
# here. We need to do it after the loop is completed, so we are
268+
# storing in "node_keys_to_remove" the invalid key and in
269+
# "nodes_to_add" the current node assigned to the correct key
270+
node_keys_to_remove.append(node_name)
271+
new_key = f"{node['namespace']}.{node['address']}.{node_port}"
272+
nodes_to_add[new_key] = node
273+
274+
if node_keys_to_remove:
275+
for k in node_keys_to_remove:
276+
del inventory[k]
277+
278+
if nodes_to_add:
279+
inventory.update(nodes_to_add)
257280

258281
def _validate_device(self):
259282
if self._device:

suzieq/poller/controller/source/native.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212

1313
logger = logging.getLogger(__name__)
1414

15-
_DEFAULT_PORTS = {'http': 80, 'https': 443, 'ssh': 22}
16-
1715

1816
class HostModel(BaseModel):
1917
"""Model used to validate the hosts of a native inventory
@@ -22,7 +20,7 @@ class HostModel(BaseModel):
2220
password: Optional[str] = Field(default=None)
2321
keyfile: Optional[str] = Field(default=None)
2422
devtype: Optional[str] = Field(default=None)
25-
port: str = Field(default=None)
23+
port: Optional[str] = Field(default=None)
2624
address: str = Field(default=None)
2725
transport: str = Field(default=None)
2826
url: str
@@ -47,7 +45,7 @@ def validate_and_set(cls, url: str, values):
4745
except KeyError:
4846
raise ValueError(
4947
f"Transport '{transport}' not supported for host {address}")
50-
port = decoded_url.port or _DEFAULT_PORTS.get(transport)
48+
port = decoded_url.port
5149
devtype = None
5250
keyfile = None
5351

suzieq/poller/controller/utils/inventory_models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class DeviceModel(BaseModel):
3434
retries_on_auth_fail: Optional[int] = Field(alias='retries-on-auth-fail',
3535
default=1)
3636
transport: Optional[PollerTransport]
37-
port: Optional[str]
37+
port: Optional[int]
3838
devtype: Optional[str]
3939

4040
# pylint: disable=no-self-argument

tests/unit/poller/controller/data/exp-inventory.yaml

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ auths:
66
password: strong-passoword
77
key-passphrase: null
88
type: null
9-
username: null
9+
username: user
1010
devices:
1111
dev0:
1212
devtype: null
1313
ignore-known-hosts: false
1414
jump-host: [email protected]
1515
jump-host-key-file: null
1616
name: dev0
17-
port: null
17+
port: 333
1818
slow-host: False
1919
per-cmd-auth: False
2020
retries-on-auth-fail: 0
@@ -24,28 +24,52 @@ namespaces:
2424
device: dev0
2525
name: native-ns
2626
source: native0
27+
- auth: auth0
28+
device: null
29+
name: native-default
30+
source: native-default
2731
- auth: auth0
2832
device: null
2933
name: netbox-ns
3034
source: netbox0
3135
sources:
36+
native-default:
37+
hosts:
38+
- address: 192.168.1.2
39+
devtype: eos
40+
keyfile: null
41+
password: null
42+
port: null
43+
transport: https
44+
url: https://192.168.1.2 devtype=eos
45+
username: null
46+
- address: 192.168.1.3
47+
devtype: null
48+
keyfile: null
49+
password: null
50+
port: null
51+
transport: ssh
52+
url: ssh://192.168.1.3
53+
username: null
54+
name: native-default
55+
type: null
3256
native0:
3357
hosts:
3458
- address: 192.168.123.164
3559
devtype: eos
3660
keyfile: null
3761
password: null
38-
port: 443
62+
port: null
3963
transport: https
4064
url: https://[email protected] devtype=eos
4165
username: vagrant
4266
- address: 192.168.123.70
4367
devtype: null
4468
keyfile: null
4569
password: null
46-
port: 22
70+
port: 123
4771
transport: ssh
48-
url: ssh://192.168.123.70 username=admin
72+
url: ssh://192.168.123.70:123 username=admin
4973
username: admin
5074
name: native0
5175
type: null

tests/unit/poller/controller/data/inventory.yaml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,38 @@ sources:
22
- name: native0
33
hosts:
44
- url: https://[email protected] devtype=eos
5-
- url: ssh://192.168.123.70 username=admin
5+
- url: ssh://192.168.123.70:123 username=admin
66
- name: netbox0
77
type: netbox
88
token: MY-TOKEN
99
url: http://localhost:8000
1010
tag: suzieq
11+
- name: native-default
12+
hosts:
13+
- url: https://192.168.1.2 devtype=eos
14+
- url: ssh://192.168.1.3
1115

1216
auths:
1317
- name: auth0
1418
password: plain:strong-passoword
19+
username: user
1520

1621
devices:
1722
- name: dev0
1823
transport: ssh
1924
jump-host: [email protected]
2025
per-cmd-auth: False
2126
retries-on-auth-fail: 0
27+
port: 333
2228

2329
namespaces:
2430
- name: native-ns
2531
device: dev0
2632
auth: auth0
2733
source: native0
34+
- name: native-default
35+
auth: auth0
36+
source: native-default
2837
- name: netbox-ns
2938
auth: auth0
3039
source: netbox0

tests/unit/poller/controller/sources/netbox/netbox_faker.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ def generate_data(self) -> Tuple[Dict, Dict]:
274274
namespace = dev_site
275275
else:
276276
namespace = self._namespace
277-
dev_key = f'{namespace}.{ip}'
277+
port = 22
278+
dev_key = f'{namespace}.{ip}.{port}'
278279
exp_inventory[dev_key] = _BASE_INVENTORY_DEVICE.copy()
279280

280281
exp_inventory[dev_key].update({

tests/unit/poller/controller/sources/test_devices.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
'transport': 'http',
5050
'port': 443
5151
},
52-
'native-ns.192.168.123.171.22':
52+
'native-ns.192.168.123.171':
5353
{
5454
'address': '192.168.123.171',
5555
'hostname': None,
@@ -101,7 +101,7 @@
101101
'transport': 'http',
102102
'port': 443
103103
},
104-
'native-ns.192.168.123.171.22':
104+
'native-ns.192.168.123.171.80':
105105
{
106106
'address': '192.168.123.171',
107107
'hostname': None,

0 commit comments

Comments
 (0)