Skip to content

Commit 5c9bea8

Browse files
committed
Update Custom Field logic for Netbox v2.10.x
1 parent 036f94a commit 5c9bea8

24 files changed

+160
-260
lines changed

initializers/custom_fields.yml

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
# weight: 10
3838
# on_objects:
3939
# - tenancy.models.Tenant
40-
# select_field:
40+
# legacy_select_field:
4141
# type: select
4242
# label: Choose between items
4343
# required: false
@@ -56,6 +56,21 @@
5656
# weight: 50
5757
# - value: Fourth Item
5858
# weight: 40
59+
# select_field:
60+
# type: select
61+
# label: Choose between items
62+
# required: false
63+
# filter_logic: exact
64+
# weight: 30
65+
# default: First Item
66+
# on_objects:
67+
# - dcim.models.Device
68+
# choices:
69+
# - First Item
70+
# - Second Item
71+
# - Third Item
72+
# - Fifth Item
73+
# - Fourth Item
5974
# select_field_auto_weight:
6075
# type: select
6176
# label: Choose between items
@@ -65,18 +80,17 @@
6580
# on_objects:
6681
# - dcim.models.Device
6782
# choices:
68-
# - value: A
69-
# - value: B
70-
# - value: C
71-
# - value: "D like deprecated"
72-
# weight: 999
73-
# - value: E
83+
# - A
84+
# - B
85+
# - C
86+
# - E
87+
# - D like deprecated
7488
# boolean_field:
7589
# type: boolean
7690
# label: Yes Or No?
7791
# required: true
7892
# filter_logic: loose
79-
# default: "false" # important: but "false" in quotes!
93+
# default: "false" # important: put "false" in quotes!
8094
# weight: 90
8195
# on_objects:
8296
# - dcim.models.Device

initializers/device_types.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
# manufacturer: Manufacturer 1
33
# slug: model-1
44
# u_height: 2
5-
# custom_fields:
5+
# custom_field_data:
66
# text_field: Description
77
# - model: Model 2
88
# manufacturer: Manufacturer 1
99
# slug: model-2
10-
# custom_fields:
10+
# custom_field_data:
1111
# text_field: Description
1212
# - model: Model 3
1313
# manufacturer: Manufacturer 1
1414
# slug: model-3
1515
# is_full_depth: false
1616
# u_height: 0
17-
# custom_fields:
17+
# custom_field_data:
1818
# text_field: Description
1919
# - model: Other
2020
# manufacturer: No Name
2121
# slug: other
22-
# custom_fields:
22+
# custom_field_data:
2323
# text_field: Description

initializers/devices.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# rack: rack-01
2121
# face: front
2222
# position: 1
23-
# custom_fields:
23+
# custom_field_data:
2424
# text_field: Description
2525
# - name: server02
2626
# device_role: server
@@ -31,7 +31,7 @@
3131
# position: 2
3232
# primary_ip4: 10.1.1.2/24
3333
# primary_ip6: 2001:db8:a000:1::2/64
34-
# custom_fields:
34+
# custom_field_data:
3535
# text_field: Description
3636
# - name: server03
3737
# device_role: server
@@ -40,5 +40,5 @@
4040
# rack: rack-03
4141
# face: front
4242
# position: 3
43-
# custom_fields:
43+
# custom_field_data:
4444
# text_field: Description

initializers/racks.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@
2020
# type: 4-post-cabinet
2121
# width: 19
2222
# u_height: 47
23-
# custom_fields:
23+
# custom_field_data:
2424
# text_field: Description
2525
# - site: AMS 2
2626
# name: rack-02
2727
# role: Role 2
2828
# type: 4-post-cabinet
2929
# width: 19
3030
# u_height: 47
31-
# custom_fields:
31+
# custom_field_data:
3232
# text_field: Description
3333
# - site: SING 1
3434
# name: rack-03
@@ -37,5 +37,5 @@
3737
# type: 4-post-cabinet
3838
# width: 19
3939
# u_height: 47
40-
# custom_fields:
40+
# custom_field_data:
4141
# text_field: Description

initializers/sites.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,29 @@
44
# status: active
55
# facility: Amsterdam 1
66
# asn: 12345
7-
# custom_fields:
8-
# text_field: Description
7+
# custom_field_data:
8+
# text_field: Description for AMS1
99
# - name: AMS 2
1010
# slug: ams2
1111
# region: Downtown
1212
# status: active
1313
# facility: Amsterdam 2
1414
# asn: 54321
15-
# custom_fields:
16-
# text_field: Description
15+
# custom_field_data:
16+
# text_field: Description for AMS2
1717
# - name: AMS 3
1818
# slug: ams3
1919
# region: Suburbs
2020
# status: active
2121
# facility: Amsterdam 3
2222
# asn: 67890
23-
# custom_fields:
24-
# text_field: Description
23+
# custom_field_data:
24+
# text_field: Description for AMS3
2525
# - name: SING 1
2626
# slug: sing1
2727
# region: Singapore
2828
# status: active
2929
# facility: Singapore 1
3030
# asn: 09876
31-
# custom_fields:
32-
# text_field: Description
31+
# custom_field_data:
32+
# text_field: Description for SING1

startup_scripts/020_custom_fields.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from extras.models import CustomField, CustomFieldChoice
1+
import sys
22

3+
from extras.models import CustomField
34
from startup_script_utils import load_yaml
4-
import sys
55

66
def get_class_for_class_path(class_path):
77
import importlib
@@ -21,34 +21,37 @@ def get_class_for_class_path(class_path):
2121
custom_field, created = CustomField.objects.get_or_create(name = cf_name)
2222

2323
if created:
24-
if cf_details.get('default', 0):
24+
if cf_details.get('default', False):
2525
custom_field.default = cf_details['default']
2626

27-
if cf_details.get('description', 0):
27+
if cf_details.get('description', False):
2828
custom_field.description = cf_details['description']
2929

30-
if cf_details.get('label', 0):
30+
if cf_details.get('label', False):
3131
custom_field.label = cf_details['label']
3232

3333
for object_type in cf_details.get('on_objects', []):
34-
custom_field.obj_type.add(get_class_for_class_path(object_type))
34+
custom_field.content_types.add(get_class_for_class_path(object_type))
3535

36-
if cf_details.get('required', 0):
36+
if cf_details.get('required', False):
3737
custom_field.required = cf_details['required']
3838

39-
if cf_details.get('type', 0):
39+
if cf_details.get('type', False):
4040
custom_field.type = cf_details['type']
4141

42-
if cf_details.get('weight', 0):
42+
if cf_details.get('weight', -1) >= 0:
4343
custom_field.weight = cf_details['weight']
4444

45-
custom_field.save()
45+
if cf_details.get('choices', False):
46+
custom_field.choices = []
4647

47-
for idx, choice_details in enumerate(cf_details.get('choices', [])):
48-
choice, _ = CustomFieldChoice.objects.get_or_create(
49-
field=custom_field,
50-
value=choice_details['value'],
51-
defaults={'weight': idx * 10}
52-
)
48+
for _, choice_detail in enumerate(cf_details.get('choices', [])):
49+
if isinstance(choice_detail, str):
50+
custom_field.choices.append(choice_detail)
51+
else: # legacy mode
52+
print(f"⚠️ Please migrate the 'choices' of '{cf_name}' to the new format, as 'weight' is no longer supported!")
53+
custom_field.choices.append(choice_detail['value'])
54+
55+
custom_field.save()
5356

5457
print("🔧 Created custom field", cf_name)

startup_scripts/040_sites.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import sys
2+
13
from dcim.models import Region, Site
2-
from extras.models import CustomField, CustomFieldValue
4+
from startup_script_utils import *
35
from tenancy.models import Tenant
4-
from startup_script_utils import load_yaml
5-
import sys
66

77
sites = load_yaml('/opt/netbox/initializers/sites.yml')
88

@@ -15,7 +15,7 @@
1515
}
1616

1717
for params in sites:
18-
custom_fields = params.pop('custom_fields', None)
18+
custom_field_data = pop_custom_fields(params)
1919

2020
for assoc, details in optional_assocs.items():
2121
if assoc in params:
@@ -27,15 +27,6 @@
2727
site, created = Site.objects.get_or_create(**params)
2828

2929
if created:
30-
if custom_fields is not None:
31-
for cf_name, cf_value in custom_fields.items():
32-
custom_field = CustomField.objects.get(name=cf_name)
33-
custom_field_value = CustomFieldValue.objects.create(
34-
field=custom_field,
35-
obj=site,
36-
value=cf_value
37-
)
38-
39-
site.custom_field_values.add(custom_field_value)
30+
set_custom_fields_values(site, custom_field_data)
4031

4132
print("📍 Created site", site.name)

startup_scripts/060_device_types.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import sys
2+
13
from dcim.models import DeviceType, Manufacturer, Region
4+
from startup_script_utils import *
25
from tenancy.models import Tenant
3-
from extras.models import CustomField, CustomFieldValue
4-
from startup_script_utils import load_yaml
5-
import sys
66

77
device_types = load_yaml('/opt/netbox/initializers/device_types.yml')
88

@@ -19,7 +19,7 @@
1919
}
2020

2121
for params in device_types:
22-
custom_fields = params.pop('custom_fields', None)
22+
custom_field_data = pop_custom_fields(params)
2323

2424
for assoc, details in required_assocs.items():
2525
model, field = details
@@ -37,15 +37,6 @@
3737
device_type, created = DeviceType.objects.get_or_create(**params)
3838

3939
if created:
40-
if custom_fields is not None:
41-
for cf_name, cf_value in custom_fields.items():
42-
custom_field = CustomField.objects.get(name=cf_name)
43-
custom_field_value = CustomFieldValue.objects.create(
44-
field=custom_field,
45-
obj=device_type,
46-
value=cf_value
47-
)
48-
49-
device_type.custom_field_values.add(custom_field_value)
40+
set_custom_fields_values(device_type, custom_field_data)
5041

5142
print("🔡 Created device type", device_type.manufacturer, device_type.model)

startup_scripts/080_racks.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import sys
2+
13
from dcim.models import Site, RackRole, Rack, RackGroup
4+
from startup_script_utils import *
25
from tenancy.models import Tenant
3-
from extras.models import CustomField, CustomFieldValue
4-
from startup_script_utils import load_yaml
5-
import sys
66

77
racks = load_yaml('/opt/netbox/initializers/racks.yml')
88

@@ -20,7 +20,7 @@
2020
}
2121

2222
for params in racks:
23-
custom_fields = params.pop('custom_fields', None)
23+
custom_field_data = pop_custom_fields(params)
2424

2525
for assoc, details in required_assocs.items():
2626
model, field = details
@@ -38,15 +38,6 @@
3838
rack, created = Rack.objects.get_or_create(**params)
3939

4040
if created:
41-
if custom_fields is not None:
42-
for cf_name, cf_value in custom_fields.items():
43-
custom_field = CustomField.objects.get(name=cf_name)
44-
custom_field_value = CustomFieldValue.objects.create(
45-
field=custom_field,
46-
obj=rack,
47-
value=cf_value
48-
)
49-
50-
rack.custom_field_values.add(custom_field_value)
41+
set_custom_fields_values(rack, custom_field_data)
5142

5243
print("🔳 Created rack", rack.site, rack.name)

startup_scripts/120_tenants.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from tenancy.models import Tenant, TenantGroup
2-
from extras.models import CustomField, CustomFieldValue
3-
from startup_script_utils import load_yaml
41
import sys
52

3+
from startup_script_utils import *
4+
from tenancy.models import Tenant, TenantGroup
5+
66
tenants = load_yaml('/opt/netbox/initializers/tenants.yml')
77

88
if tenants is None:
@@ -13,7 +13,7 @@
1313
}
1414

1515
for params in tenants:
16-
custom_fields = params.pop('custom_fields', None)
16+
custom_field_data = pop_custom_fields(params)
1717

1818
for assoc, details in optional_assocs.items():
1919
if assoc in params:
@@ -25,15 +25,6 @@
2525
tenant, created = Tenant.objects.get_or_create(**params)
2626

2727
if created:
28-
if custom_fields is not None:
29-
for cf_name, cf_value in custom_fields.items():
30-
custom_field = CustomField.objects.get(name=cf_name)
31-
custom_field_value = CustomFieldValue.objects.create(
32-
field=custom_field,
33-
obj=tenant,
34-
value=cf_value
35-
)
36-
37-
tenant.custom_field_values.add(custom_field_value)
28+
set_custom_fields_values(tenant, custom_field_data)
3829

3930
print("👩‍💻 Created Tenant", tenant.name)

0 commit comments

Comments
 (0)