Skip to content

Commit d92b161

Browse files
Bugfix: Add required_one_of to netbox_service to allow device or virtual_machine (#326)
1 parent 20c7406 commit d92b161

File tree

3 files changed

+92
-4
lines changed

3 files changed

+92
-4
lines changed

plugins/module_utils/netbox_utils.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ def __init__(
979979
no_log=False,
980980
mutually_exclusive=None,
981981
required_together=None,
982-
required_one_of=None,
982+
required_one_of=required_one_of,
983983
add_file_common_args=False,
984984
supports_check_mode=supports_check_mode,
985985
required_if=required_if,
@@ -1047,6 +1047,47 @@ def check_required_if(self, requirements, module_parameters):
10471047

10481048
return results
10491049

1050+
def _check_required_one_of(self, spec, param=None):
1051+
if spec is None:
1052+
return
1053+
1054+
if param is None:
1055+
param = self.params
1056+
1057+
try:
1058+
self.check_required_one_of(spec, param)
1059+
except TypeError as e:
1060+
msg = to_native(e)
1061+
if self._options_context:
1062+
msg += " found in %s" % " -> ".join(self._options_context)
1063+
self.fail_json(msg=msg)
1064+
1065+
def check_required_one_of(self, terms, module_parameters):
1066+
"""Check each list of terms to ensure at least one exists in the given module
1067+
parameters
1068+
Accepts a list of lists or tuples
1069+
:arg terms: List of lists of terms to check. For each list of terms, at
1070+
least one is required.
1071+
:arg module_parameters: Dictionary of module parameters
1072+
:returns: Empty list or raises TypeError if the check fails.
1073+
"""
1074+
1075+
results = []
1076+
if terms is None:
1077+
return results
1078+
1079+
for term in terms:
1080+
count = self.count_terms(term, module_parameters["data"])
1081+
if count == 0:
1082+
results.append(term)
1083+
1084+
if results:
1085+
for term in results:
1086+
msg = "one of the following is required: %s" % ", ".join(term)
1087+
raise TypeError(to_native(msg))
1088+
1089+
return results
1090+
10501091
def count_terms(self, terms, module_parameters):
10511092
"""Count the number of occurrences of a key in a given dictionary
10521093
:arg terms: String or iterable of values to check

plugins/modules/netbox_service.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
device:
4646
description:
4747
- Specifies on which device the service is running
48-
required: true
48+
required: false
4949
type: raw
5050
virtual_machine:
5151
description:
@@ -170,7 +170,7 @@ def main():
170170
type="dict",
171171
required=True,
172172
options=dict(
173-
device=dict(required=True, type="raw"),
173+
device=dict(required=False, type="raw"),
174174
virtual_machine=dict(required=False, type="raw"),
175175
name=dict(required=True, type="str"),
176176
port=dict(required=True, type="int"),
@@ -185,9 +185,13 @@ def main():
185185
)
186186

187187
required_if = [("state", "present", ["name"]), ("state", "absent", ["name"])]
188+
required_one_of = [["device", "virtual_machine"]]
188189

189190
module = NetboxAnsibleModule(
190-
argument_spec=argument_spec, supports_check_mode=True, required_if=required_if
191+
argument_spec=argument_spec,
192+
supports_check_mode=True,
193+
required_if=required_if,
194+
required_one_of=required_one_of,
191195
)
192196

193197
netbox_service = NetboxIpamModule(module, NB_SERVICES)

tests/integration/targets/latest/tasks/netbox_service.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,46 @@
148148
- test_service_ip_addresses['services']['protocol'] == "udp"
149149
- test_service_ip_addresses['services']['ipaddresses'] is defined
150150
- test_service_ip_addresses['msg'] == "services node-exporter created"
151+
152+
- name: "NETBOX_SERVICE: Missing both device & virtual_machine options - Tests required_one_of"
153+
netbox.netbox.netbox_service:
154+
netbox_url: "http://localhost:32768"
155+
netbox_token: "0123456789abcdef0123456789abcdef01234567"
156+
data:
157+
name: "node-exporter"
158+
port: 9100
159+
protocol: UDP
160+
ipaddresses:
161+
- address: "172.16.180.1/24"
162+
state: present
163+
ignore_errors: yes
164+
register: test_service_required_one_of
165+
166+
- name: "NETBOX_SERVICE ASSERT - Failed due to missing arguments"
167+
assert:
168+
that:
169+
- test_service_required_one_of is failed
170+
- 'test_service_required_one_of["msg"] == "one of the following is required: device, virtual_machine"'
171+
172+
- name: "NETBOX_SERVICE: Create new service on virtual_machine"
173+
netbox.netbox.netbox_service:
174+
netbox_url: "http://localhost:32768"
175+
netbox_token: "0123456789abcdef0123456789abcdef01234567"
176+
data:
177+
virtual_machine: "test100-vm"
178+
name: "node-exporter"
179+
port: 9100
180+
protocol: TCP
181+
state: present
182+
register: test_service_create_vm
183+
184+
- name: "NETBOX_SERVICE ASSERT - Create"
185+
assert:
186+
that:
187+
- test_service_create_vm is changed
188+
- test_service_create_vm['services']['name'] == "node-exporter"
189+
- test_service_create_vm['services']['port'] == 9100
190+
- test_service_create_vm['services']['protocol'] == "tcp"
191+
- test_service_create_vm['diff']['after']['state'] == "present"
192+
- test_service_create_vm['diff']['before']['state'] == "absent"
193+
- test_service_create_vm['msg'] == "services node-exporter created"

0 commit comments

Comments
 (0)