Skip to content

Commit 15a91eb

Browse files
BugFix: Fix connection error handling to Netbox (#80)
1 parent 6331847 commit 15a91eb

File tree

11 files changed

+82
-47
lines changed

11 files changed

+82
-47
lines changed

.travis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ matrix:
2626
- cd ..
2727
- pip install -U pip
2828
- pip install pytest==4.6.5 pytest-mock pytest-xdist jinja2 PyYAML black==19.10b0
29-
- pip install pynetbox==4.0.6 cryptography codecov jmespath ansible
29+
- pip install pynetbox cryptography codecov jmespath ansible
3030

3131
- name: "Python 3.6 - Netbox Latest - Ansible Devel"
3232
python: 3.6
@@ -41,7 +41,7 @@ matrix:
4141
- cd ..
4242
- pip install -U pip
4343
- pip install pytest==4.6.5 pytest-mock pytest-xdist jinja2 PyYAML black==19.10b0
44-
- pip install pynetbox==4.0.6 cryptography jmespath
44+
- pip install pynetbox cryptography jmespath
4545
# This is due to ansible-test only being available within devel branch
4646
- git clone https://github.com/ansible/ansible.git
4747
- cd ansible
@@ -60,4 +60,5 @@ script:
6060
- black . --check
6161
- timeout 300 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:32768)" != "200" ]]; do echo "waiting for Netbox"; sleep 5; done' || false
6262
- python tests/integration/netbox-deploy.py
63+
- ansible-playbook tests/integration/regression-tests.yml -vvvv
6364
- ansible-playbook tests/integration/integration-tests.yml -vvvv

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
## Requirements
77

88
- Netbox 2.5+
9-
- pynetbox 4.0.6+
9+
- **pynetbox 4.1.0+**
1010
- Python 3.6+
1111
- Ansible 2.9+
1212

plugins/module_utils/netbox_circuits.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,7 @@ def run(self):
6868
data["slug"] = self._to_slug(name)
6969

7070
object_query_params = self._build_query_params(endpoint_name, data)
71-
try:
72-
self.nb_object = nb_endpoint.get(**object_query_params)
73-
except ValueError:
74-
self._handle_errors(msg="More than one result returned for %s" % (name))
71+
self.nb_object = self._nb_endpoint_get(nb_endpoint, object_query_params, name)
7572

7673
if self.state == "present":
7774
self._ensure_object_exists(nb_endpoint, endpoint_name, name, data)

plugins/module_utils/netbox_dcim.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,7 @@ def run(self):
8888
data["color"] = data["color"].lower()
8989

9090
object_query_params = self._build_query_params(endpoint_name, data)
91-
try:
92-
self.nb_object = nb_endpoint.get(**object_query_params)
93-
except ValueError:
94-
self._handle_errors(msg="More than one result returned for %s" % (name))
91+
self.nb_object = self._nb_endpoint_get(nb_endpoint, object_query_params, name)
9592

9693
if self.state == "present":
9794
self._ensure_object_exists(nb_endpoint, endpoint_name, name, data)

plugins/module_utils/netbox_extras.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,7 @@ def run(self):
4545
data["slug"] = self._to_slug(name)
4646

4747
object_query_params = self._build_query_params(endpoint_name, data)
48-
try:
49-
self.nb_object = nb_endpoint.get(**object_query_params)
50-
except ValueError:
51-
self._handle_errors(msg="More than one result returned for %s" % (name))
48+
self.nb_object = self._nb_endpoint_get(nb_endpoint, object_query_params, name)
5249

5350
if self.state == "present":
5451
self._ensure_object_exists(nb_endpoint, endpoint_name, name, data)

plugins/module_utils/netbox_ipam.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def _ensure_ip_in_prefix_present_on_netif(
8181

8282
def _get_new_available_ip_address(self, nb_app, data, endpoint_name):
8383
prefix_query = self._build_query_params("prefix", data)
84-
prefix = nb_app.prefixes.get(**prefix_query)
84+
prefix = self._nb_endpoint_get(nb_app.prefixes, prefix_query, data["prefix"])
8585
if not prefix:
8686
self.result["changed"] = False
8787
self.result["msg"] = "%s does not exist - please create first" % (
@@ -170,15 +170,13 @@ def run(self):
170170
object_query_params = self._build_query_params(endpoint_name, data)
171171
if data.get("prefix") and self.endpoint == "ip_addresses":
172172
object_query_params = self._build_query_params("prefix", data)
173-
try:
174-
self.nb_object = nb_app.prefixes.get(**object_query_params)
175-
except ValueError:
176-
self._handle_errors(msg="More than one result returned for %s" % (name))
173+
self.nb_object = self._nb_endpoint_get(
174+
nb_app.prefixes, object_query_params, name
175+
)
177176
else:
178-
try:
179-
self.nb_object = nb_endpoint.get(**object_query_params)
180-
except ValueError:
181-
self._handle_errors(msg="More than one result returned for %s" % (name))
177+
self.nb_object = self._nb_endpoint_get(
178+
nb_endpoint, object_query_params, name
179+
)
182180

183181
if self.state in ("new", "present") and endpoint_name == "ip_address":
184182
self._handle_state_new_present(

plugins/module_utils/netbox_secrets.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,7 @@ def run(self):
4545
data["slug"] = self._to_slug(name)
4646

4747
object_query_params = self._build_query_params(endpoint_name, data)
48-
try:
49-
self.nb_object = nb_endpoint.get(**object_query_params)
50-
except ValueError:
51-
self._handle_errors(msg="More than one result returned for %s" % (name))
48+
self.nb_object = self._nb_endpoint_get(nb_endpoint, object_query_params, name)
5249

5350
if self.state == "present":
5451
self._ensure_object_exists(nb_endpoint, endpoint_name, name, data)

plugins/module_utils/netbox_tenancy.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,7 @@ def run(self):
5151
data["slug"] = self._to_slug(name)
5252

5353
object_query_params = self._build_query_params(endpoint_name, data)
54-
try:
55-
self.nb_object = nb_endpoint.get(**object_query_params)
56-
except ValueError:
57-
self._handle_errors(msg="More than one result returned for %s" % (name))
54+
self.nb_object = self._nb_endpoint_get(nb_endpoint, object_query_params, name)
5855

5956
if self.state == "present":
6057
self._ensure_object_exists(nb_endpoint, endpoint_name, name, data)

plugins/module_utils/netbox_utils.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -442,10 +442,31 @@ def __init__(self, module, endpoint, nb_client=None):
442442

443443
def _connect_netbox_api(self, url, token, ssl_verify):
444444
try:
445-
return pynetbox.api(url, token=token, ssl_verify=ssl_verify)
445+
nb = pynetbox.api(url, token=token, ssl_verify=ssl_verify)
446+
try:
447+
self.version = nb.version
448+
except AttributeError:
449+
self.module.fail_json(msg="Must have pynetbox >=4.1.0")
450+
except Exception:
451+
self.module.fail_json(
452+
msg="Failed to establish connection to Netbox API"
453+
)
454+
return nb
446455
except Exception:
447456
self.module.fail_json(msg="Failed to establish connection to Netbox API")
448457

458+
def _nb_endpoint_get(self, nb_endpoint, query_params, search_item):
459+
try:
460+
response = nb_endpoint.get(**query_params)
461+
except pynetbox.RequestError as e:
462+
self._handle_errors(msg=e.error)
463+
except ValueError:
464+
self._handle_errors(
465+
msg="More than one result returned for %s" % (search_item)
466+
)
467+
468+
return response
469+
449470
def _handle_errors(self, msg):
450471
"""
451472
Returns message and changed = False
@@ -498,7 +519,10 @@ def _get_query_param_id(self, match, data):
498519
app = self._find_app(endpoint)
499520
nb_app = getattr(self.nb, app)
500521
nb_endpoint = getattr(nb_app, endpoint)
501-
result = nb_endpoint.get(**{QUERY_TYPES.get(match): data[match]})
522+
523+
query_params = {QUERY_TYPES.get(match): data[match]}
524+
result = self._nb_endpoint_get(nb_endpoint, query_params, match)
525+
502526
if result:
503527
return result.id
504528
else:
@@ -607,27 +631,22 @@ def _find_ids(self, data):
607631
nb_app = getattr(self.nb, "virtualization")
608632
nb_endpoint = getattr(nb_app, endpoint)
609633
query_params = self._build_query_params(k, data, v)
610-
query_id = nb_endpoint.get(**query_params)
634+
query_id = self._nb_endpoint_get(nb_endpoint, query_params, k)
611635

612636
elif isinstance(v, list):
613637
id_list = list()
614638
for list_item in v:
615639
norm_data = self._normalize_data(list_item)
616640
temp_dict = self._build_query_params(k, data, norm_data)
617-
query_id = nb_endpoint.get(**temp_dict)
641+
query_id = self._nb_endpoint_get(nb_endpoint, temp_dict, k)
618642
if query_id:
619643
id_list.append(query_id.id)
620644
else:
621645
self._handle_errors(msg="%s not found" % (list_item))
622646

623647
else:
624-
try:
625-
query_id = nb_endpoint.get(**{QUERY_TYPES.get(k, "q"): search})
626-
except ValueError:
627-
self._handle_errors(
628-
msg="Multiple results found while searching for key: %s"
629-
% (k)
630-
)
648+
query_params = {QUERY_TYPES.get(k, "q"): search}
649+
query_id = self._nb_endpoint_get(nb_endpoint, query_params, k)
631650

632651
if isinstance(v, list):
633652
data[k] = id_list

plugins/module_utils/netbox_virtualization.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,7 @@ def run(self):
6767
data["slug"] = self._to_slug(name)
6868

6969
object_query_params = self._build_query_params(endpoint_name, data)
70-
try:
71-
self.nb_object = nb_endpoint.get(**object_query_params)
72-
except ValueError:
73-
self._handle_errors(msg="More than one result returned for %s" % (name))
70+
self.nb_object = self._nb_endpoint_get(nb_endpoint, object_query_params, name)
7471

7572
if self.state == "present":
7673
self._ensure_object_exists(nb_endpoint, endpoint_name, name, data)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
##
3+
##
4+
### TEST NETBOX CONNECTION FAILURE
5+
##
6+
##
7+
- name: "TEST NETBOX CONNECTION FAILURE"
8+
hosts: localhost
9+
connection: local
10+
gather_facts: no
11+
collections:
12+
- netbox_community.ansible_modules
13+
vars:
14+
netbox_url: "http://localhost:32768"
15+
16+
tasks:
17+
- name: "1 - Device with required information"
18+
netbox_device:
19+
netbox_url: netbox_url
20+
netbox_token: "0123456789abcdef0123456789abcdef01234567"
21+
data:
22+
name: "R1"
23+
device_type: "Cisco Test"
24+
device_role: "Core Switch"
25+
site: "Test Site"
26+
status: "Staged"
27+
state: present
28+
register: test_one
29+
ignore_errors: yes
30+
31+
- name: "1 - ASSERT"
32+
assert:
33+
that:
34+
- test_one is failed
35+
- test_one['msg'] == "Failed to establish connection to Netbox API"

0 commit comments

Comments
 (0)