Skip to content

Commit 4ceb283

Browse files
authored
feat: Add custom_field choice-set support (#1203)
1 parent 2481548 commit 4ceb283

File tree

6 files changed

+301
-5
lines changed

6 files changed

+301
-5
lines changed

plugins/module_utils/netbox_extras.py

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
NB_CONFIG_CONTEXTS = "config_contexts"
1515
NB_TAGS = "tags"
1616
NB_CUSTOM_FIELDS = "custom_fields"
17+
NB_CUSTOM_FIELD_CHOICE_SETS = "custom_field_choice_sets"
1718
NB_CUSTOM_LINKS = "custom_links"
1819
NB_EXPORT_TEMPLATES = "export_templates"
1920
NB_JOURNAL_ENTRIES = "journal_entries"

plugins/module_utils/netbox_utils.py

+6
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
"config_templates": {},
8383
"tags": {},
8484
"custom_fields": {},
85+
"custom_field_choice_sets": {},
8586
"custom_links": {},
8687
"export_templates": {},
8788
"journal_entries": {},
@@ -145,6 +146,7 @@
145146
contact_group="name",
146147
contact_role="name",
147148
custom_field="name",
149+
choice_set="name",
148150
custom_link="name",
149151
device="name",
150152
device_role="slug",
@@ -226,6 +228,7 @@
226228
"config_context": "config_contexts",
227229
"config_template": "config_templates",
228230
"contact_groups": "contact_groups",
231+
"choice_set": "custom_field_choice_sets",
229232
"dcim.consoleport": "console_ports",
230233
"dcim.consoleserverport": "console_server_ports",
231234
"dcim.frontport": "front_ports",
@@ -338,6 +341,7 @@
338341
"contact_groups": "contact_group",
339342
"contact_roles": "contact_role",
340343
"custom_fields": "custom_field",
344+
"custom_field_choice_sets": "choice_set",
341345
"custom_links": "custom_link",
342346
"device_bays": "device_bay",
343347
"device_bay_templates": "device_bay_template",
@@ -438,6 +442,8 @@
438442
"contact_group": set(["name"]),
439443
"contact_role": set(["name"]),
440444
"custom_field": set(["name"]),
445+
"custom_field_choice_set": set(["name"]),
446+
"choice_set": set(["name"]),
441447
"custom_link": set(["name"]),
442448
"dcim.consoleport": set(["name", "device"]),
443449
"dcim.consoleserverport": set(["name", "device"]),

plugins/modules/netbox_custom_field.py

+19-5
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,11 @@
132132
- The regular expression to enforce on text fields
133133
required: false
134134
type: str
135-
choices:
135+
choice_set:
136136
description:
137-
- List of available choices (for selection fields)
137+
- The name of the choice set to use (for selection fields)
138138
required: false
139-
type: list
140-
elements: str
139+
type: str
141140
required: true
142141
"""
143142

@@ -157,6 +156,18 @@
157156
name: A Custom Field
158157
type: text
159158
159+
- name: Create a custom field of type selection
160+
netbox.netbox.netbox_custom_field:
161+
netbox_url: http://netbox.local
162+
netbox_token: thisIsMyToken
163+
data:
164+
name: "Custom_Field"
165+
content_types:
166+
- dcim.device
167+
- virtualization.virtualmachine
168+
type: select
169+
choice_set: A Choice Set name
170+
160171
- name: Update the custom field to make it required
161172
netbox.netbox.netbox_custom_field:
162173
netbox_url: http://netbox.local
@@ -258,7 +269,10 @@ def main():
258269
validation_minimum=dict(required=False, type="int"),
259270
validation_maximum=dict(required=False, type="int"),
260271
validation_regex=dict(required=False, type="str"),
261-
choices=dict(required=False, type="list", elements="str"),
272+
choice_set=dict(
273+
required=False,
274+
type="str",
275+
),
262276
),
263277
)
264278
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#!/usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
# Copyright: (c) 2024, Philipp Rintz (@p-rintz) <[email protected]>
4+
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5+
6+
from __future__ import absolute_import, division, print_function
7+
8+
__metaclass__ = type
9+
10+
DOCUMENTATION = r"""
11+
---
12+
module: netbox_custom_field_choice_set
13+
short_description: Creates, updates or deletes custom field choice sets within Netbox
14+
description:
15+
- Creates, updates or removes custom fields choice sets from Netbox
16+
notes:
17+
- This should be run with connection C(local) and hosts C(localhost)
18+
author:
19+
- Philipp Rintz (@p-rintz)
20+
requirements:
21+
- pynetbox
22+
version_added: "3.6.0"
23+
extends_documentation_fragment:
24+
- netbox.netbox.common
25+
options:
26+
data:
27+
type: dict
28+
description:
29+
- Defines the choice set
30+
suboptions:
31+
name:
32+
description:
33+
- Name of the choice set
34+
required: true
35+
type: str
36+
description:
37+
description:
38+
- Description of the choice set
39+
required: false
40+
type: str
41+
extra_choices:
42+
description:
43+
- List of available choices in the choice set
44+
required: false
45+
default: []
46+
type: list
47+
elements: list
48+
base_choices:
49+
description:
50+
- Selection of base choice to use in the choice set
51+
required: false
52+
type: str
53+
choices:
54+
- IATA
55+
- ISO_3166
56+
- UN_LOCODE
57+
order_alphabetically:
58+
description:
59+
- Order the choices alphabetically
60+
required: false
61+
type: bool
62+
required: true
63+
"""
64+
65+
EXAMPLES = r"""
66+
- name: "Test Netbox custom_field_choice_set module"
67+
connection: local
68+
hosts: localhost
69+
tasks:
70+
- name: Create a choice set with choices
71+
netbox.netbox.netbox_custom_field_choice_set:
72+
netbox_url: http://netbox.local
73+
netbox_token: thisIsMyToken
74+
data:
75+
name: "ChoiceSetName"
76+
description: "Choice Set Description"
77+
extra_choices:
78+
- ['choice1', 'label1']
79+
- ['choice2', 'label2']
80+
81+
- name: Create a choice set with a base choice
82+
netbox.netbox.netbox_custom_field_choice_set:
83+
netbox_url: http://netbox.local
84+
netbox_token: thisIsMyToken
85+
data:
86+
name: "ChoiceSetName"
87+
description: "Choice Set Description"
88+
order_alphabetically: true
89+
base_choices: "IATA"
90+
"""
91+
92+
RETURN = r"""
93+
custom_field_choice_set:
94+
description: Serialized object as created/existent/updated/deleted within NetBox
95+
returned: always
96+
type: dict
97+
msg:
98+
description: Message indicating failure or info about what has been achieved
99+
returned: always
100+
type: str
101+
"""
102+
103+
from ansible_collections.netbox.netbox.plugins.module_utils.netbox_utils import (
104+
NetboxAnsibleModule,
105+
NETBOX_ARG_SPEC,
106+
)
107+
from ansible_collections.netbox.netbox.plugins.module_utils.netbox_extras import (
108+
NetboxExtrasModule,
109+
NB_CUSTOM_FIELD_CHOICE_SETS,
110+
)
111+
from copy import deepcopy
112+
113+
114+
def main():
115+
"""
116+
Main entry point for module execution
117+
"""
118+
argument_spec = deepcopy(NETBOX_ARG_SPEC)
119+
argument_spec.update(
120+
dict(
121+
data=dict(
122+
type="dict",
123+
required=True,
124+
options=dict(
125+
name=dict(required=True, type="str"),
126+
description=dict(required=False, type="str"),
127+
base_choices=dict(
128+
required=False,
129+
type="str",
130+
choices=[
131+
"IATA",
132+
"ISO_3166",
133+
"UN_LOCODE",
134+
],
135+
),
136+
extra_choices=dict(
137+
required=False,
138+
default=[],
139+
type="list",
140+
elements="list",
141+
),
142+
order_alphabetically=dict(required=False, type="bool"),
143+
),
144+
)
145+
)
146+
)
147+
148+
required_if = [
149+
("state", "present", ["name"]),
150+
("state", "absent", ["name"]),
151+
]
152+
153+
module = NetboxAnsibleModule(
154+
argument_spec=argument_spec, supports_check_mode=True, required_if=required_if
155+
)
156+
157+
netbox_custom_field_choice_set = NetboxExtrasModule(
158+
module, NB_CUSTOM_FIELD_CHOICE_SETS
159+
)
160+
netbox_custom_field_choice_set.run()
161+
162+
163+
if __name__ == "__main__": # pragma: no cover
164+
main()

tests/integration/targets/v3.6/tasks/main.yml

+5
Original file line numberDiff line numberDiff line change
@@ -310,3 +310,8 @@
310310
include_tasks: "netbox_config_template.yml"
311311
tags:
312312
- netbox_config_template
313+
314+
- name: "NETBOX_CUSTOM_FIELD_CHOICE_SET"
315+
include_tasks: "netbox_custom_field_choice_set.yml"
316+
tags:
317+
- netbox_custom_field_choice_set
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
---
2+
##
3+
##
4+
### NETBOX_CUSTOM_FIELD_CHOICE_SET
5+
##
6+
##
7+
- name: "CUSTOM_FIELD_CHOICE_SET 1: Base Choice set creation"
8+
netbox.netbox.netbox_custom_field_choice_set:
9+
netbox_url: http://localhost:32768
10+
netbox_token: 0123456789abcdef0123456789abcdef01234567
11+
data:
12+
name: "A_ChoiceSet"
13+
description: "Added a description"
14+
base_choices: "IATA"
15+
state: present
16+
register: test_one
17+
18+
- name: "CUSTOM_FIELD_CHOICE_SET 1: ASSERT - Base Choice set creation"
19+
assert:
20+
that:
21+
- test_one is changed
22+
- test_one['diff']['before']['state'] == "absent"
23+
- test_one['diff']['after']['state'] == "present"
24+
- test_one['choice_set']['name'] == "A_ChoiceSet"
25+
- test_one['choice_set']['description'] == "Added a description"
26+
- test_one['choice_set']['display'] == "A_ChoiceSet"
27+
- test_one['choice_set']['order_alphabetically'] == false
28+
- test_one['choice_set']['extra_choices'] == []
29+
- test_one['msg'] == "choice_set A_ChoiceSet created"
30+
31+
- name: "CUSTOM_FIELD_CHOICE_SET 2: Create duplicate"
32+
netbox.netbox.netbox_custom_field_choice_set:
33+
netbox_url: http://localhost:32768
34+
netbox_token: 0123456789abcdef0123456789abcdef01234567
35+
data:
36+
name: "A_ChoiceSet"
37+
description: "Added a description"
38+
base_choices: "IATA"
39+
state: present
40+
register: test_two
41+
42+
- name: "CUSTOM_FIELD_CHOICE_SET 2: ASSERT - Create duplicate"
43+
assert:
44+
that:
45+
- not test_two['changed']
46+
- test_two['choice_set']['name'] == "A_ChoiceSet"
47+
- test_two['msg'] == "choice_set A_ChoiceSet already exists"
48+
49+
- name: "CUSTOM_FIELD_CHOICE_SET 3: Update data and change base_choice"
50+
netbox.netbox.netbox_custom_field_choice_set:
51+
netbox_url: http://localhost:32768
52+
netbox_token: 0123456789abcdef0123456789abcdef01234567
53+
data:
54+
name: "A_ChoiceSet"
55+
description: "Added a description"
56+
base_choices: "ISO_3166"
57+
state: present
58+
register: test_three
59+
60+
- name: "CUSTOM_FIELD_CHOICE_SET 3: ASSERT - Updated"
61+
assert:
62+
that:
63+
- test_three is changed
64+
- test_three['diff']['after']['base_choices'] == "ISO_3166"
65+
- test_three['choice_set']['name'] == "A_ChoiceSet"
66+
- test_three['msg'] == "choice_set A_ChoiceSet updated"
67+
68+
- name: "CUSTOM_FIELD_CHOICE_SET 4: Update extra choice and order alphabetically"
69+
netbox.netbox.netbox_custom_field_choice_set:
70+
netbox_url: http://localhost:32768
71+
netbox_token: 0123456789abcdef0123456789abcdef01234567
72+
data:
73+
name: "A_ChoiceSet"
74+
description: "Added a description"
75+
order_alphabetically: true
76+
extra_choices:
77+
- ['test', 'label']
78+
- ['test2', 'label2']
79+
state: present
80+
register: test_four
81+
82+
- name: "CUSTOM_FIELD_CHOICE_SET 4: ASSERT - Change extra choice and order alphabetically"
83+
assert:
84+
that:
85+
- test_four is changed
86+
- test_four['diff']['after']['extra_choices'] == [["test","label"],["test2","label2"]]
87+
- test_four['diff']['after']['order_alphabetically'] == true
88+
- test_four['choice_set']['name'] == "A_ChoiceSet"
89+
- test_four['msg'] == "choice_set A_ChoiceSet updated"
90+
91+
- name: "CUSTOM_FIELD_CHOICE_SET 5: Delete"
92+
netbox.netbox.netbox_custom_field_choice_set:
93+
netbox_url: http://localhost:32768
94+
netbox_token: 0123456789abcdef0123456789abcdef01234567
95+
data:
96+
name: "A_ChoiceSet"
97+
state: absent
98+
register: test_five
99+
100+
- name: "CUSTOM_FIELD_CHOICE_SET 5: ASSERT - Deleted"
101+
assert:
102+
that:
103+
- test_five is changed
104+
- test_five['diff']['after']['state'] == "absent"
105+
- test_five['choice_set']['name'] == "A_ChoiceSet"
106+
- test_five['msg'] == "choice_set A_ChoiceSet deleted"

0 commit comments

Comments
 (0)