Skip to content

Commit 1f15f7e

Browse files
authored
Fix two idempotency issues when updating VMs. (#859)
* fix: make _version_check_greater return type consistent values * fix: typo in form_factor error message * fix: make netbox_virtual_machine updates idempotent on netbox v2.10+
1 parent 4b606fd commit 1f15f7e

File tree

4 files changed

+150
-47
lines changed

4 files changed

+150
-47
lines changed

plugins/module_utils/netbox_utils.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,8 @@ def _version_check_greater(self, greater, lesser, greater_or_equal=False):
676676
elif g_major == l_major and g_minor > l_minor:
677677
return True
678678

679+
return False
680+
679681
def _connect_netbox_api(self, url, token, ssl_verify, cert):
680682
try:
681683
session = requests.Session()
@@ -1255,12 +1257,28 @@ def _update_netbox_object(self, data):
12551257
"""
12561258
serialized_nb_obj = self.nb_object.serialize()
12571259
updated_obj = serialized_nb_obj.copy()
1260+
1261+
if serialized_nb_obj.get("custom_fields"):
1262+
serialized_nb_obj["custom_fields"] = {
1263+
key: value
1264+
for key, value in serialized_nb_obj["custom_fields"].items()
1265+
if value is not None
1266+
}
1267+
1268+
if updated_obj.get("custom_fields"):
1269+
updated_obj["custom_fields"] = {
1270+
key: value
1271+
for key, value in updated_obj["custom_fields"].items()
1272+
if value is not None
1273+
}
1274+
12581275
updated_obj.update(data)
1276+
12591277
if serialized_nb_obj.get("tags") and data.get("tags"):
12601278
serialized_nb_obj["tags"] = set(serialized_nb_obj["tags"])
12611279
updated_obj["tags"] = set(data["tags"])
12621280

1263-
# Ensure idempotency for site and virtual machine on version pre-3.0
1281+
# Ensure idempotency for site on older netbox versions
12641282
version_pre_30 = self._version_check_greater("3.0", self.version)
12651283
if (
12661284
serialized_nb_obj.get("latitude")
@@ -1275,15 +1293,13 @@ def _update_netbox_object(self, data):
12751293
):
12761294
updated_obj["longitude"] = str(data["longitude"])
12771295

1278-
if serialized_nb_obj.get("vcpus") and data.get("vcpus") and version_pre_30:
1279-
updated_obj["vcpus"] = "{0:.2f}".format(data["vcpus"])
1280-
1281-
if serialized_nb_obj.get("custom_fields"):
1282-
serialized_nb_obj["custom_fields"] = {
1283-
key: value
1284-
for key, value in serialized_nb_obj["custom_fields"].items()
1285-
if value is not None
1286-
}
1296+
# Ensure idempotency for virtual machine on older netbox versions
1297+
version_pre_211 = self._version_check_greater("2.11", self.version)
1298+
if serialized_nb_obj.get("vcpus") and data.get("vcpus"):
1299+
if version_pre_211:
1300+
updated_obj["vcpus"] = int(data["vcpus"])
1301+
else:
1302+
updated_obj["vcpus"] = float(data["vcpus"])
12871303

12881304
if serialized_nb_obj == updated_obj:
12891305
return serialized_nb_obj, None
@@ -1296,7 +1312,7 @@ def _update_netbox_object(self, data):
12961312
data_after[key] = updated_obj[key]
12971313
except KeyError:
12981314
if key == "form_factor":
1299-
msg = "form_factor is not valid for NetBox 2.7 onword. Please use the type key instead."
1315+
msg = "form_factor is not valid for NetBox 2.7 onward. Please use the type key instead."
13001316
else:
13011317
msg = (
13021318
"%s does not exist on existing object. Check to make sure valid field."

tests/integration/targets/v3.1/tasks/netbox_virtual_machine.yml

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,24 +76,53 @@
7676
- test_three['virtual_machine']['tags'][0] == 4
7777
- test_three['msg'] == "virtual_machine Test VM One updated"
7878

79-
- name: "VIRTUAL_MACHINE 4: Delete"
79+
- name: "VIRTUAL_MACHINE 4: Test idempotence"
80+
netbox.netbox.netbox_virtual_machine:
81+
netbox_url: http://localhost:32768
82+
netbox_token: 0123456789abcdef0123456789abcdef01234567
83+
data:
84+
name: "Test VM One"
85+
cluster: "Test Cluster"
86+
vcpus: 8.5
87+
memory: 8
88+
status: "Planned"
89+
virtual_machine_role: "Test VM Role"
90+
tags:
91+
- "Schnozzberry"
92+
state: present
93+
register: test_four_idempotence
94+
95+
- name: "VIRTUAL_MACHINE 4: ASSERT - Not changed"
96+
assert:
97+
that:
98+
- test_four_idempotence is not changed
99+
- test_four_idempotence['virtual_machine']['name'] == "Test VM One"
100+
- test_four_idempotence['virtual_machine']['cluster'] == 1
101+
- test_four_idempotence['virtual_machine']['vcpus'] == 8.5
102+
- test_four_idempotence['virtual_machine']['memory'] == 8
103+
- test_four_idempotence['virtual_machine']['status'] == "planned"
104+
- test_four_idempotence['virtual_machine']['role'] == 2
105+
- test_four_idempotence['virtual_machine']['tags'][0] == 4
106+
- test_four_idempotence['msg'] == "virtual_machine Test VM One already exists"
107+
108+
- name: "VIRTUAL_MACHINE 5: Delete"
80109
netbox.netbox.netbox_virtual_machine:
81110
netbox_url: http://localhost:32768
82111
netbox_token: 0123456789abcdef0123456789abcdef01234567
83112
data:
84113
name: "Test VM One"
85114
state: absent
86-
register: test_four
115+
register: test_five
87116

88-
- name: "VIRTUAL_MACHINE 4: ASSERT - Delete"
117+
- name: "VIRTUAL_MACHINE 5: ASSERT - Delete"
89118
assert:
90119
that:
91-
- test_four is changed
92-
- test_four['virtual_machine']['name'] == "Test VM One"
93-
- test_four['virtual_machine']['cluster'] == 1
94-
- test_four['virtual_machine']['vcpus'] == 8.5
95-
- test_four['virtual_machine']['memory'] == 8
96-
- test_four['virtual_machine']['status'] == "planned"
97-
- test_four['virtual_machine']['role'] == 2
98-
- test_four['virtual_machine']['tags'][0] == 4
99-
- test_four['msg'] == "virtual_machine Test VM One deleted"
120+
- test_five is changed
121+
- test_five['virtual_machine']['name'] == "Test VM One"
122+
- test_five['virtual_machine']['cluster'] == 1
123+
- test_five['virtual_machine']['vcpus'] == 8.5
124+
- test_five['virtual_machine']['memory'] == 8
125+
- test_five['virtual_machine']['status'] == "planned"
126+
- test_five['virtual_machine']['role'] == 2
127+
- test_five['virtual_machine']['tags'][0] == 4
128+
- test_five['msg'] == "virtual_machine Test VM One deleted"

tests/integration/targets/v3.2/tasks/netbox_virtual_machine.yml

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,24 +76,53 @@
7676
- test_three['virtual_machine']['tags'][0] == 4
7777
- test_three['msg'] == "virtual_machine Test VM One updated"
7878

79-
- name: "VIRTUAL_MACHINE 4: Delete"
79+
- name: "VIRTUAL_MACHINE 4: Test idempotence"
80+
netbox.netbox.netbox_virtual_machine:
81+
netbox_url: http://localhost:32768
82+
netbox_token: 0123456789abcdef0123456789abcdef01234567
83+
data:
84+
name: "Test VM One"
85+
cluster: "Test Cluster"
86+
vcpus: 8.5
87+
memory: 8
88+
status: "Planned"
89+
virtual_machine_role: "Test VM Role"
90+
tags:
91+
- "Schnozzberry"
92+
state: present
93+
register: test_four_idempotence
94+
95+
- name: "VIRTUAL_MACHINE 4: ASSERT - Not changed"
96+
assert:
97+
that:
98+
- test_four_idempotence is not changed
99+
- test_four_idempotence['virtual_machine']['name'] == "Test VM One"
100+
- test_four_idempotence['virtual_machine']['cluster'] == 1
101+
- test_four_idempotence['virtual_machine']['vcpus'] == 8.5
102+
- test_four_idempotence['virtual_machine']['memory'] == 8
103+
- test_four_idempotence['virtual_machine']['status'] == "planned"
104+
- test_four_idempotence['virtual_machine']['role'] == 2
105+
- test_four_idempotence['virtual_machine']['tags'][0] == 4
106+
- test_four_idempotence['msg'] == "virtual_machine Test VM One already exists"
107+
108+
- name: "VIRTUAL_MACHINE 5: Delete"
80109
netbox.netbox.netbox_virtual_machine:
81110
netbox_url: http://localhost:32768
82111
netbox_token: 0123456789abcdef0123456789abcdef01234567
83112
data:
84113
name: "Test VM One"
85114
state: absent
86-
register: test_four
115+
register: test_five
87116

88-
- name: "VIRTUAL_MACHINE 4: ASSERT - Delete"
117+
- name: "VIRTUAL_MACHINE 5: ASSERT - Delete"
89118
assert:
90119
that:
91-
- test_four is changed
92-
- test_four['virtual_machine']['name'] == "Test VM One"
93-
- test_four['virtual_machine']['cluster'] == 1
94-
- test_four['virtual_machine']['vcpus'] == 8.5
95-
- test_four['virtual_machine']['memory'] == 8
96-
- test_four['virtual_machine']['status'] == "planned"
97-
- test_four['virtual_machine']['role'] == 2
98-
- test_four['virtual_machine']['tags'][0] == 4
99-
- test_four['msg'] == "virtual_machine Test VM One deleted"
120+
- test_five is changed
121+
- test_five['virtual_machine']['name'] == "Test VM One"
122+
- test_five['virtual_machine']['cluster'] == 1
123+
- test_five['virtual_machine']['vcpus'] == 8.5
124+
- test_five['virtual_machine']['memory'] == 8
125+
- test_five['virtual_machine']['status'] == "planned"
126+
- test_five['virtual_machine']['role'] == 2
127+
- test_five['virtual_machine']['tags'][0] == 4
128+
- test_five['msg'] == "virtual_machine Test VM One deleted"

tests/integration/targets/v3.3/tasks/netbox_virtual_machine.yml

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,24 +76,53 @@
7676
- test_three['virtual_machine']['tags'][0] == 4
7777
- test_three['msg'] == "virtual_machine Test VM One updated"
7878

79-
- name: "VIRTUAL_MACHINE 4: Delete"
79+
- name: "VIRTUAL_MACHINE 4: Test idempotence"
80+
netbox.netbox.netbox_virtual_machine:
81+
netbox_url: http://localhost:32768
82+
netbox_token: 0123456789abcdef0123456789abcdef01234567
83+
data:
84+
name: "Test VM One"
85+
cluster: "Test Cluster"
86+
vcpus: 8.5
87+
memory: 8
88+
status: "Planned"
89+
virtual_machine_role: "Test VM Role"
90+
tags:
91+
- "Schnozzberry"
92+
state: present
93+
register: test_four_idempotence
94+
95+
- name: "VIRTUAL_MACHINE 4: ASSERT - Not changed"
96+
assert:
97+
that:
98+
- test_four_idempotence is not changed
99+
- test_four_idempotence['virtual_machine']['name'] == "Test VM One"
100+
- test_four_idempotence['virtual_machine']['cluster'] == 1
101+
- test_four_idempotence['virtual_machine']['vcpus'] == 8.5
102+
- test_four_idempotence['virtual_machine']['memory'] == 8
103+
- test_four_idempotence['virtual_machine']['status'] == "planned"
104+
- test_four_idempotence['virtual_machine']['role'] == 2
105+
- test_four_idempotence['virtual_machine']['tags'][0] == 4
106+
- test_four_idempotence['msg'] == "virtual_machine Test VM One already exists"
107+
108+
- name: "VIRTUAL_MACHINE 5: Delete"
80109
netbox.netbox.netbox_virtual_machine:
81110
netbox_url: http://localhost:32768
82111
netbox_token: 0123456789abcdef0123456789abcdef01234567
83112
data:
84113
name: "Test VM One"
85114
state: absent
86-
register: test_four
115+
register: test_five
87116

88-
- name: "VIRTUAL_MACHINE 4: ASSERT - Delete"
117+
- name: "VIRTUAL_MACHINE 5: ASSERT - Delete"
89118
assert:
90119
that:
91-
- test_four is changed
92-
- test_four['virtual_machine']['name'] == "Test VM One"
93-
- test_four['virtual_machine']['cluster'] == 1
94-
- test_four['virtual_machine']['vcpus'] == 8.5
95-
- test_four['virtual_machine']['memory'] == 8
96-
- test_four['virtual_machine']['status'] == "planned"
97-
- test_four['virtual_machine']['role'] == 2
98-
- test_four['virtual_machine']['tags'][0] == 4
99-
- test_four['msg'] == "virtual_machine Test VM One deleted"
120+
- test_five is changed
121+
- test_five['virtual_machine']['name'] == "Test VM One"
122+
- test_five['virtual_machine']['cluster'] == 1
123+
- test_five['virtual_machine']['vcpus'] == 8.5
124+
- test_five['virtual_machine']['memory'] == 8
125+
- test_five['virtual_machine']['status'] == "planned"
126+
- test_five['virtual_machine']['role'] == 2
127+
- test_five['virtual_machine']['tags'][0] == 4
128+
- test_five['msg'] == "virtual_machine Test VM One deleted"

0 commit comments

Comments
 (0)