mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-25 01:48:38 -06:00
Service.protocol to slug (#3569)
This commit is contained in:
parent
213bd1555a
commit
4ecbfc4e5e
@ -9,8 +9,7 @@ from dcim.api.nested_serializers import NestedDeviceSerializer, NestedSiteSerial
|
|||||||
from dcim.models import Interface
|
from dcim.models import Interface
|
||||||
from extras.api.customfields import CustomFieldModelSerializer
|
from extras.api.customfields import CustomFieldModelSerializer
|
||||||
from ipam.choices import *
|
from ipam.choices import *
|
||||||
from ipam.constants import *
|
from ipam.models import AF_CHOICES, Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
||||||
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
|
||||||
from tenancy.api.nested_serializers import NestedTenantSerializer
|
from tenancy.api.nested_serializers import NestedTenantSerializer
|
||||||
from utilities.api import (
|
from utilities.api import (
|
||||||
ChoiceField, SerializedPKRelatedField, ValidatedModelSerializer, WritableNestedSerializer,
|
ChoiceField, SerializedPKRelatedField, ValidatedModelSerializer, WritableNestedSerializer,
|
||||||
@ -240,7 +239,7 @@ class AvailableIPSerializer(serializers.Serializer):
|
|||||||
class ServiceSerializer(CustomFieldModelSerializer):
|
class ServiceSerializer(CustomFieldModelSerializer):
|
||||||
device = NestedDeviceSerializer(required=False, allow_null=True)
|
device = NestedDeviceSerializer(required=False, allow_null=True)
|
||||||
virtual_machine = NestedVirtualMachineSerializer(required=False, allow_null=True)
|
virtual_machine = NestedVirtualMachineSerializer(required=False, allow_null=True)
|
||||||
protocol = ChoiceField(choices=IP_PROTOCOL_CHOICES)
|
protocol = ChoiceField(choices=ServiceProtocolChoices)
|
||||||
ipaddresses = SerializedPKRelatedField(
|
ipaddresses = SerializedPKRelatedField(
|
||||||
queryset=IPAddress.objects.all(),
|
queryset=IPAddress.objects.all(),
|
||||||
serializer=NestedIPAddressSerializer,
|
serializer=NestedIPAddressSerializer,
|
||||||
|
@ -108,3 +108,23 @@ class VLANStatusChoices(ChoiceSet):
|
|||||||
STATUS_RESERVED: 2,
|
STATUS_RESERVED: 2,
|
||||||
STATUS_DEPRECATED: 3,
|
STATUS_DEPRECATED: 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# VLANs
|
||||||
|
#
|
||||||
|
|
||||||
|
class ServiceProtocolChoices(ChoiceSet):
|
||||||
|
|
||||||
|
PROTOCOL_TCP = 'tcp'
|
||||||
|
PROTOCOL_UDP = 'udp'
|
||||||
|
|
||||||
|
CHOICES = (
|
||||||
|
(PROTOCOL_TCP, 'TCP'),
|
||||||
|
(PROTOCOL_UDP, 'UDP'),
|
||||||
|
)
|
||||||
|
|
||||||
|
LEGACY_MAP = {
|
||||||
|
PROTOCOL_TCP: 6,
|
||||||
|
PROTOCOL_UDP: 17,
|
||||||
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
# IP address families
|
|
||||||
AF_CHOICES = (
|
|
||||||
(4, 'IPv4'),
|
|
||||||
(6, 'IPv6'),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# IP protocols (for services)
|
|
||||||
IP_PROTOCOL_TCP = 6
|
|
||||||
IP_PROTOCOL_UDP = 17
|
|
||||||
IP_PROTOCOL_CHOICES = (
|
|
||||||
(IP_PROTOCOL_TCP, 'TCP'),
|
|
||||||
(IP_PROTOCOL_UDP, 'UDP'),
|
|
||||||
)
|
|
@ -10,7 +10,6 @@ from tenancy.filtersets import TenancyFilterSet
|
|||||||
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
|
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
|
||||||
from virtualization.models import VirtualMachine
|
from virtualization.models import VirtualMachine
|
||||||
from .choices import *
|
from .choices import *
|
||||||
from .constants import *
|
|
||||||
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ from utilities.forms import (
|
|||||||
)
|
)
|
||||||
from virtualization.models import VirtualMachine
|
from virtualization.models import VirtualMachine
|
||||||
from .choices import *
|
from .choices import *
|
||||||
from .constants import *
|
|
||||||
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
||||||
|
|
||||||
IP_FAMILY_CHOICES = [
|
IP_FAMILY_CHOICES = [
|
||||||
@ -1293,7 +1292,7 @@ class ServiceFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
label='Search'
|
label='Search'
|
||||||
)
|
)
|
||||||
protocol = forms.ChoiceField(
|
protocol = forms.ChoiceField(
|
||||||
choices=add_blank_choice(IP_PROTOCOL_CHOICES),
|
choices=add_blank_choice(ServiceProtocolChoices),
|
||||||
required=False,
|
required=False,
|
||||||
widget=StaticSelect2Multiple()
|
widget=StaticSelect2Multiple()
|
||||||
)
|
)
|
||||||
@ -1308,7 +1307,7 @@ class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
|||||||
widget=forms.MultipleHiddenInput()
|
widget=forms.MultipleHiddenInput()
|
||||||
)
|
)
|
||||||
protocol = forms.ChoiceField(
|
protocol = forms.ChoiceField(
|
||||||
choices=add_blank_choice(IP_PROTOCOL_CHOICES),
|
choices=add_blank_choice(ServiceProtocolChoices),
|
||||||
required=False,
|
required=False,
|
||||||
widget=StaticSelect2()
|
widget=StaticSelect2()
|
||||||
)
|
)
|
||||||
|
35
netbox/ipam/migrations/0031_3569_service_fields.py
Normal file
35
netbox/ipam/migrations/0031_3569_service_fields.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
SERVICE_PROTOCOL_CHOICES = (
|
||||||
|
(6, 'tcp'),
|
||||||
|
(17, 'udp'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def service_protocol_to_slug(apps, schema_editor):
|
||||||
|
Service = apps.get_model('ipam', 'Service')
|
||||||
|
for id, slug in SERVICE_PROTOCOL_CHOICES:
|
||||||
|
Service.objects.filter(protocol=str(id)).update(protocol=slug)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
atomic = False
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('ipam', '0030_3569_vlan_fields'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
|
||||||
|
# Service.protocol
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='service',
|
||||||
|
name='protocol',
|
||||||
|
field=models.CharField(max_length=50),
|
||||||
|
),
|
||||||
|
migrations.RunPython(
|
||||||
|
code=service_protocol_to_slug
|
||||||
|
),
|
||||||
|
|
||||||
|
]
|
@ -15,12 +15,17 @@ from utilities.models import ChangeLoggedModel
|
|||||||
from utilities.utils import serialize_object
|
from utilities.utils import serialize_object
|
||||||
from virtualization.models import VirtualMachine
|
from virtualization.models import VirtualMachine
|
||||||
from .choices import *
|
from .choices import *
|
||||||
from .constants import *
|
|
||||||
from .fields import IPNetworkField, IPAddressField
|
from .fields import IPNetworkField, IPAddressField
|
||||||
from .querysets import PrefixQuerySet
|
from .querysets import PrefixQuerySet
|
||||||
from .validators import DNSValidator
|
from .validators import DNSValidator
|
||||||
|
|
||||||
|
|
||||||
|
# IP address families
|
||||||
|
AF_CHOICES = (
|
||||||
|
(4, 'IPv4'),
|
||||||
|
(6, 'IPv6'),
|
||||||
|
)
|
||||||
|
|
||||||
IPADDRESS_ROLES_NONUNIQUE = (
|
IPADDRESS_ROLES_NONUNIQUE = (
|
||||||
# IPAddress roles which are exempt from unique address enforcement
|
# IPAddress roles which are exempt from unique address enforcement
|
||||||
IPAddressRoleChoices.ROLE_ANYCAST,
|
IPAddressRoleChoices.ROLE_ANYCAST,
|
||||||
@ -975,8 +980,9 @@ class Service(ChangeLoggedModel, CustomFieldModel):
|
|||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
max_length=30
|
max_length=30
|
||||||
)
|
)
|
||||||
protocol = models.PositiveSmallIntegerField(
|
protocol = models.CharField(
|
||||||
choices=IP_PROTOCOL_CHOICES
|
max_length=50,
|
||||||
|
choices=ServiceProtocolChoices
|
||||||
)
|
)
|
||||||
port = models.PositiveIntegerField(
|
port = models.PositiveIntegerField(
|
||||||
validators=[MinValueValidator(1), MaxValueValidator(65535)],
|
validators=[MinValueValidator(1), MaxValueValidator(65535)],
|
||||||
|
@ -5,7 +5,7 @@ from netaddr import IPNetwork
|
|||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
|
||||||
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
|
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
|
||||||
from ipam.constants import IP_PROTOCOL_TCP, IP_PROTOCOL_UDP
|
from ipam.choices import ServiceProtocolChoices
|
||||||
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
||||||
from utilities.testing import APITestCase
|
from utilities.testing import APITestCase
|
||||||
|
|
||||||
@ -996,13 +996,13 @@ class ServiceTest(APITestCase):
|
|||||||
name='Test Device 2', site=site, device_type=devicetype, device_role=devicerole
|
name='Test Device 2', site=site, device_type=devicetype, device_role=devicerole
|
||||||
)
|
)
|
||||||
self.service1 = Service.objects.create(
|
self.service1 = Service.objects.create(
|
||||||
device=self.device1, name='Test Service 1', protocol=IP_PROTOCOL_TCP, port=1
|
device=self.device1, name='Test Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=1
|
||||||
)
|
)
|
||||||
self.service1 = Service.objects.create(
|
self.service1 = Service.objects.create(
|
||||||
device=self.device1, name='Test Service 2', protocol=IP_PROTOCOL_TCP, port=2
|
device=self.device1, name='Test Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=2
|
||||||
)
|
)
|
||||||
self.service1 = Service.objects.create(
|
self.service1 = Service.objects.create(
|
||||||
device=self.device1, name='Test Service 3', protocol=IP_PROTOCOL_TCP, port=3
|
device=self.device1, name='Test Service 3', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=3
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_service(self):
|
def test_get_service(self):
|
||||||
@ -1024,7 +1024,7 @@ class ServiceTest(APITestCase):
|
|||||||
data = {
|
data = {
|
||||||
'device': self.device1.pk,
|
'device': self.device1.pk,
|
||||||
'name': 'Test Service 4',
|
'name': 'Test Service 4',
|
||||||
'protocol': IP_PROTOCOL_TCP,
|
'protocol': ServiceProtocolChoices.PROTOCOL_TCP,
|
||||||
'port': 4,
|
'port': 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1045,19 +1045,19 @@ class ServiceTest(APITestCase):
|
|||||||
{
|
{
|
||||||
'device': self.device1.pk,
|
'device': self.device1.pk,
|
||||||
'name': 'Test Service 4',
|
'name': 'Test Service 4',
|
||||||
'protocol': IP_PROTOCOL_TCP,
|
'protocol': ServiceProtocolChoices.PROTOCOL_TCP,
|
||||||
'port': 4,
|
'port': 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'device': self.device1.pk,
|
'device': self.device1.pk,
|
||||||
'name': 'Test Service 5',
|
'name': 'Test Service 5',
|
||||||
'protocol': IP_PROTOCOL_TCP,
|
'protocol': ServiceProtocolChoices.PROTOCOL_TCP,
|
||||||
'port': 5,
|
'port': 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'device': self.device1.pk,
|
'device': self.device1.pk,
|
||||||
'name': 'Test Service 6',
|
'name': 'Test Service 6',
|
||||||
'protocol': IP_PROTOCOL_TCP,
|
'protocol': ServiceProtocolChoices.PROTOCOL_TCP,
|
||||||
'port': 6,
|
'port': 6,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -1076,7 +1076,7 @@ class ServiceTest(APITestCase):
|
|||||||
data = {
|
data = {
|
||||||
'device': self.device2.pk,
|
'device': self.device2.pk,
|
||||||
'name': 'Test Service X',
|
'name': 'Test Service X',
|
||||||
'protocol': IP_PROTOCOL_UDP,
|
'protocol': ServiceProtocolChoices.PROTOCOL_UDP,
|
||||||
'port': 99,
|
'port': 99,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ from django.test import Client, TestCase
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
|
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
|
||||||
from ipam.constants import IP_PROTOCOL_TCP
|
from ipam.choices import ServiceProtocolChoices
|
||||||
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
||||||
from utilities.testing import create_test_user
|
from utilities.testing import create_test_user
|
||||||
|
|
||||||
@ -264,9 +264,9 @@ class ServiceTestCase(TestCase):
|
|||||||
device.save()
|
device.save()
|
||||||
|
|
||||||
Service.objects.bulk_create([
|
Service.objects.bulk_create([
|
||||||
Service(device=device, name='Service 1', protocol=IP_PROTOCOL_TCP, port=101),
|
Service(device=device, name='Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=101),
|
||||||
Service(device=device, name='Service 2', protocol=IP_PROTOCOL_TCP, port=102),
|
Service(device=device, name='Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=102),
|
||||||
Service(device=device, name='Service 3', protocol=IP_PROTOCOL_TCP, port=103),
|
Service(device=device, name='Service 3', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=103),
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_service_list(self):
|
def test_service_list(self):
|
||||||
|
@ -15,7 +15,6 @@ from utilities.views import (
|
|||||||
from virtualization.models import VirtualMachine
|
from virtualization.models import VirtualMachine
|
||||||
from . import filters, forms, tables
|
from . import filters, forms, tables
|
||||||
from .choices import *
|
from .choices import *
|
||||||
from .constants import *
|
|
||||||
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user