Closes #6582: Allow available-ips to specify network bits

Allow the POST /ipam/prefixes/{id}/available-ips to specify prefix length (for example when I need to create /32's)
This commit is contained in:
Cédric Paillet 2022-02-23 17:51:41 +01:00
parent 90f91eeea4
commit 7b47c92c54
3 changed files with 19 additions and 4 deletions

View File

@ -352,15 +352,17 @@ class AvailableIPSerializer(serializers.Serializer):
family = serializers.IntegerField(read_only=True)
address = serializers.CharField(read_only=True)
vrf = NestedVRFSerializer(read_only=True)
mask_length = serializers.IntegerField(read_only=True, allow_null=True)
def to_representation(self, instance):
if self.context.get('vrf'):
vrf = NestedVRFSerializer(self.context['vrf'], context={'request': self.context['request']}).data
else:
vrf = None
mask_length = self.context.get('mask_length') or self.context['parent'].mask_length
return OrderedDict([
('family', self.context['parent'].family),
('address', f"{instance}/{self.context['parent'].mask_length}"),
('address', f"{instance}/{mask_length}"),
('vrf', vrf),
])

View File

@ -294,7 +294,8 @@ class AvailableIPAddressesView(ObjectValidationMixin, APIView):
# Assign addresses from the list of available IPs and copy VRF assignment from the parent
available_ips = iter(available_ips)
for requested_ip in requested_ips:
requested_ip['address'] = f'{next(available_ips)}/{parent.mask_length}'
mask_length = requested_ip.get('mask_length') or parent.mask_length
requested_ip['address'] = f'{next(available_ips)}/{mask_length}'
requested_ip['vrf'] = parent.vrf.pk if parent.vrf else None
# Initialize the serializer with a list or a single object depending on what was requested

View File

@ -379,8 +379,8 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
url = reverse('ipam-api:prefix-available-ips', kwargs={'pk': prefix.pk})
self.add_permissions('ipam.view_prefix', 'ipam.add_ipaddress')
# Create all four available IPs with individual requests
for i in range(1, 5):
# Create three available IPs with individual requests
for i in range(1, 4):
data = {
'description': 'Test IP {}'.format(i)
}
@ -388,6 +388,18 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
self.assertHttpStatus(response, status.HTTP_201_CREATED)
self.assertEqual(response.data['vrf']['id'], vrf.pk)
self.assertEqual(response.data['description'], data['description'])
self.assertEqual(IPNetwork(response.data['address']).prefixlen, 30)
# Create one more IP with a specified mask length
data = {
'description': 'Test IP 4',
'mask_length': 32
}
response = self.client.post(url, data, format='json', **self.header)
self.assertHttpStatus(response, status.HTTP_201_CREATED)
self.assertEqual(response.data['vrf']['id'], vrf.pk)
self.assertEqual(response.data['description'], data['description'])
self.assertEqual(IPNetwork(response.data['address']).prefixlen, 32)
# Try to create one more IP
response = self.client.post(url, {}, **self.header)