Skip to content

Commit bdcdf3a

Browse files
authored
Merge pull request #42 from k01ek/develop
Develop
2 parents 0db73d5 + 8377478 commit bdcdf3a

File tree

9 files changed

+181
-9
lines changed

9 files changed

+181
-9
lines changed

Makefile

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
PYTHON_VER?=3.7
2-
NETBOX_VER?=v2.11.2
2+
NETBOX_VER?=v2.11.6
33

44
NAME=netbox-bgp
55

@@ -71,3 +71,7 @@ endif
7171
git commit -am 'bump ver'
7272
git push origin release-$(NEWVER)
7373
git checkout develop
74+
75+
76+
test:
77+
docker-compose -f ${COMPOSE_FILE} -p ${BUILD_NAME} run netbox python manage.py test ${BUILD_NAME}

netbox_bgp/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class BGPConfig(PluginConfig):
1212
base_url = 'bgp'
1313
required_settings = []
1414
min_version = '2.10.1'
15-
max_version = '2.11.3'
15+
max_version = '2.11.6'
1616
default_settings = {
1717
'device_ext_page': 'right'
1818
}

netbox_bgp/api/serializers.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from rest_framework.serializers import Serializer, HyperlinkedIdentityField
22
from rest_framework.relations import PrimaryKeyRelatedField
33

4-
from netbox.api import ChoiceField, WritableNestedSerializer
4+
from netbox.api import ChoiceField, WritableNestedSerializer, ValidatedModelSerializer
55
from dcim.api.nested_serializers import NestedSiteSerializer, NestedDeviceSerializer
66
from tenancy.api.nested_serializers import NestedTenantSerializer
77
from extras.api.nested_serializers import NestedTagSerializer
@@ -14,7 +14,8 @@
1414
from netbox.api.serializers import CustomFieldModelSerializer
1515

1616
from netbox_bgp.models import (
17-
ASN, ASNStatusChoices, BGPSession, SessionStatusChoices, RoutingPolicy, BGPPeerGroup
17+
ASN, ASNStatusChoices, BGPSession, SessionStatusChoices, RoutingPolicy, BGPPeerGroup,
18+
Community
1819
)
1920

2021

@@ -161,3 +162,12 @@ def to_representation(self, instance):
161162
NestedRoutingPolicySerializer(pol, context={'request': self.context['request']}).data
162163
)
163164
return ret
165+
166+
167+
class CommunitySerializer(TaggedObjectSerializer, ValidatedModelSerializer):
168+
status = ChoiceField(choices=ASNStatusChoices, required=False)
169+
tenant = NestedTenantSerializer(required=False, allow_null=True)
170+
171+
class Meta:
172+
model = Community
173+
fields = ['id', 'value', 'status', 'description', 'tenant', 'tags']

netbox_bgp/api/urls.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
from rest_framework import routers
22

3-
from .views import ASNViewSet, BGPSessionViewSet, RoutingPolicyViewSet, BGPPeerGroupViewSet
3+
from .views import (
4+
ASNViewSet, BGPSessionViewSet, RoutingPolicyViewSet, BGPPeerGroupViewSet,
5+
CommunityViewSet
6+
)
47

58
router = routers.DefaultRouter()
69
router.register('asn', ASNViewSet)
710
router.register('session', BGPSessionViewSet)
811
router.register('routing-policy', RoutingPolicyViewSet)
912
router.register('peer-group', BGPPeerGroupViewSet)
13+
router.register('community', CommunityViewSet)
1014

1115

1216
urlpatterns = router.urls

netbox_bgp/api/views.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
from rest_framework.viewsets import ModelViewSet
22

3-
from .serializers import ASNSerializer, BGPSessionSerializer, RoutingPolicySerializer, BGPPeerGroupSerializer
4-
from netbox_bgp.models import ASN, BGPSession, RoutingPolicy, BGPPeerGroup
3+
from .serializers import (
4+
ASNSerializer, BGPSessionSerializer, RoutingPolicySerializer, BGPPeerGroupSerializer,
5+
CommunitySerializer
6+
)
7+
from netbox_bgp.models import ASN, BGPSession, RoutingPolicy, BGPPeerGroup, Community
58
from netbox_bgp.filters import (
6-
ASNFilterSet, BGPSessionFilterSet, RoutingPolicyFilterSet, BGPPeerGroupFilterSet
9+
ASNFilterSet, BGPSessionFilterSet, RoutingPolicyFilterSet, BGPPeerGroupFilterSet,
10+
CommunityFilterSet
711
)
812

913

@@ -29,3 +33,9 @@ class BGPPeerGroupViewSet(ModelViewSet):
2933
queryset = BGPPeerGroup.objects.all()
3034
serializer_class = BGPPeerGroupSerializer
3135
filterset_class = BGPPeerGroupFilterSet
36+
37+
38+
class CommunityViewSet(ModelViewSet):
39+
queryset = Community.objects.all()
40+
serializer_class = CommunitySerializer
41+
filterset_class = CommunityFilterSet

netbox_bgp/tests/__init__.py

Whitespace-only changes.

netbox_bgp/tests/test_api.py

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
from django.contrib.auth.models import User
2+
from django.test import TestCase
3+
from django.urls import reverse
4+
from rest_framework import status
5+
from rest_framework.test import APIClient, APITestCase
6+
7+
8+
from users.models import Token
9+
10+
from netbox_bgp.models import ASN, Community
11+
12+
13+
class BaseTestCase(TestCase):
14+
def setUp(self):
15+
self.user = User.objects.create(username='testuser', is_superuser=True)
16+
self.token = Token.objects.create(user=self.user)
17+
self.client = APIClient()
18+
self.client.credentials(HTTP_AUTHORIZATION=f'Token {self.token.key}')
19+
20+
21+
class ASNTestCase(BaseTestCase):
22+
def setUp(self):
23+
super().setUp()
24+
self.base_url_lookup = 'plugins-api:netbox_bgp-api:asn'
25+
self.asn1 = ASN.objects.create(number=65000, description='test_asn1')
26+
self.asn2 = ASN.objects.create(number=65001, description='test_asn2')
27+
28+
def test_list_asn(self):
29+
url = reverse(f'{self.base_url_lookup}-list')
30+
response = self.client.get(url)
31+
self.assertEqual(response.status_code, status.HTTP_200_OK)
32+
self.assertEqual(response.data['count'], 2)
33+
34+
def test_get_asn(self):
35+
url = reverse(f'{self.base_url_lookup}-detail', kwargs={'pk': self.asn1.pk})
36+
response = self.client.get(url)
37+
self.assertEqual(response.status_code, status.HTTP_200_OK)
38+
self.assertEqual(response.data['number'], self.asn1.number)
39+
self.assertEqual(response.data['description'], self.asn1.description)
40+
41+
def test_create_asn(self):
42+
url = reverse(f'{self.base_url_lookup}-list')
43+
data = {'number': 65002, 'description': 'test_asn3'}
44+
45+
response = self.client.post(url, data, format='json')
46+
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
47+
for key, value in data.items():
48+
self.assertEqual(response.data[key], value)
49+
50+
asn = ASN.objects.get(pk=response.data['id'])
51+
self.assertEqual(asn.number, data['number'])
52+
self.assertEqual(asn.description, data['description'])
53+
54+
def test_update_asn(self):
55+
url = reverse(f'{self.base_url_lookup}-detail', kwargs={'pk': self.asn1.pk})
56+
57+
response = self.client.patch(url, {'number': 65004}, format='json')
58+
self.assertEqual(response.status_code, status.HTTP_200_OK)
59+
asn = ASN.objects.get(pk=self.asn1.pk)
60+
self.assertEqual(asn.number, 65004)
61+
62+
response = self.client.patch(url, {'number': 65005}, format='json')
63+
self.assertEqual(response.status_code, status.HTTP_200_OK)
64+
asn = ASN.objects.get(pk=self.asn1.pk)
65+
self.assertEqual(asn.number, 65005)
66+
67+
def test_delete_task(self):
68+
url = reverse(f'{self.base_url_lookup}-detail', kwargs={'pk': self.asn1.pk})
69+
70+
response = self.client.delete(url)
71+
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
72+
with self.assertRaises(ASN.DoesNotExist):
73+
ASN.objects.get(pk=self.asn1.pk)
74+
75+
76+
class CommunityTestCase(BaseTestCase):
77+
def setUp(self):
78+
super().setUp()
79+
self.base_url_lookup = 'plugins-api:netbox_bgp-api:community'
80+
self.community1 = Community.objects.create(value='65000:65000', description='test_community')
81+
82+
def test_list_community(self):
83+
url = reverse(f'{self.base_url_lookup}-list')
84+
response = self.client.get(url)
85+
self.assertEqual(response.status_code, status.HTTP_200_OK)
86+
self.assertEqual(response.data['count'], 1)
87+
88+
def test_get_asn(self):
89+
url = reverse(f'{self.base_url_lookup}-detail', kwargs={'pk': self.community1.pk})
90+
response = self.client.get(url)
91+
self.assertEqual(response.status_code, status.HTTP_200_OK)
92+
self.assertEqual(response.data['value'], self.community1.value)
93+
self.assertEqual(response.data['description'], self.community1.description)
94+
95+
def test_create_community(self):
96+
url = reverse(f'{self.base_url_lookup}-list')
97+
data = {'value': '65001:65001', 'description': 'test_community1'}
98+
response = self.client.post(url, data, format='json')
99+
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
100+
self.assertEqual(Community.objects.get(pk=response.data['id']).value, '65001:65001')
101+
self.assertEqual(Community.objects.get(pk=response.data['id']).description, 'test_community1')
102+
103+
def test_update_community(self):
104+
pass
105+
106+
def test_delete_community(self):
107+
pass

netbox_bgp/tests/test_models.py

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from django.core.exceptions import ValidationError
2+
from django.db.utils import IntegrityError
3+
from django.test import TestCase
4+
5+
from tenancy.models import Tenant
6+
7+
from netbox_bgp.models import ASN, BGPSession, Community, RoutingPolicy, BGPPeerGroup
8+
9+
10+
class ASNTestCase(TestCase):
11+
def setUp(self):
12+
self.tenant = Tenant.objects.create(name='tenant')
13+
self.asn = ASN.objects.create(
14+
number=65001,
15+
description='test_asn'
16+
)
17+
18+
def test_create_asn(self):
19+
pass
20+
21+
def test_invalid_asn0(self):
22+
asn = ASN(number=0)
23+
self.assertRaises(ValidationError, asn.full_clean)
24+
25+
def test_invalid_asndohuya(self):
26+
asn = ASN(number=4294967295)
27+
self.assertRaises(ValidationError, asn.full_clean)
28+
29+
def test_uniqueconstraint_asn(self):
30+
asn = ASN(number=65001)
31+
with self.assertRaises(IntegrityError):
32+
asn.save()
33+
34+
def test_uniqueconstraint_asn2(self):
35+
asn = ASN.objects.create(number=65001, tenant=self.tenant)
36+
self.assertEqual(str(asn), '65001')
37+
# todo cre another 65001 tenant=self.tenant

netbox_bgp/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.3.4"
1+
__version__ = "0.3.5"

0 commit comments

Comments
 (0)