Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iterables Feature Request - Expanded #302

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions nsot/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,9 @@ class InterfaceAdmin(GuardedModelAdmin):


admin.site.register(models.Interface, InterfaceAdmin)

class IterableAdmin(admin.ModelAdmin):
list_display = ('name', 'description', 'min_val', 'max_val', 'increment', 'site')
fields = list_display

admin.site.register(models.Iterable, IterableAdmin)
5 changes: 5 additions & 0 deletions nsot/api/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,8 @@ class CircuitFilter(ResourceFilter):
class Meta:
model = models.Circuit
fields = ['endpoint_a', 'endpoint_z', 'name', 'attributes']

class IterableFilter(ResourceFilter):
class Meta:
model = models.Iterable
fields = ['name', 'attributes']
55 changes: 55 additions & 0 deletions nsot/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,3 +612,58 @@ def validate(self, attrs):
else:
msg = 'Must include "email" and "secret_key"'
raise exc.ValidationError(msg)

###########
# Iterables
###########

class IterableSerializer(ResourceSerializer):
"""Used for GET, DELETE on Iterables."""
class Meta:
model = models.Iterable
fields = '__all__'


class IterableCreateSerializer(IterableSerializer):
"""Used for POST on Iterables."""
site_id = fields.IntegerField(
label = get_field_attr(models.Iterable, 'site', 'verbose_name'),
help_text = get_field_attr(models.Iterable, 'site', 'help_text')
)
#parent = fields.IntegerField(
#label = get_field_attr(models.Iterable, 'parent', 'name'),
#help_text = get_field_attr(models.Iterable, 'parent', 'help_text')
#)

class Meta:
model = models.Iterable
fields = ( 'name', 'description', 'value', 'parent',
'min_val', 'max_val', 'increment', 'site_id', 'attributes')
#fields = '__all__'


class IterableUpdateSerializer(BulkSerializerMixin,
IterableCreateSerializer):
""" Used for PUT on Iterables. """
attributes = JSONDictField(
required=True,
help_text='Dictionary of attributes to set.'
)

class Meta:
model = models.Iterable
list_serializer_class = BulkListSerializer
fields = ('id', 'name', 'description', 'value',
'min_val', 'max_val', 'increment', 'attributes')
#fields = '__all__'


class IterablePartialUpdateSerializer(BulkSerializerMixin,
IterableCreateSerializer):
""" Used for PATCH, on Iterables. """
class Meta:
model = models.Iterable
list_serializer_class = BulkListSerializer
fields = ('id', 'name', 'description', 'value',
'min_val', 'max_val', 'increment', 'attributes')
#fields = '__all__'
3 changes: 3 additions & 0 deletions nsot/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
router.register(r'interfaces', views.InterfaceViewSet)
router.register(r'networks', views.NetworkViewSet)
router.register(r'users', views.UserViewSet)
router.register(r'iterables', views.IterableViewSet)
router.register(r'values', views.ValueViewSet)


# Nested router for resources under /sites
sites_router = routers.BulkNestedRouter(
router, r'sites', lookup='site', trailing_slash=settings.APPEND_SLASH
Expand All @@ -34,6 +36,7 @@
sites_router.register(r'interfaces', views.InterfaceViewSet)
sites_router.register(r'networks', views.NetworkViewSet)
sites_router.register(r'values', views.ValueViewSet)
sites_router.register(r'iterables', views.IterableViewSet)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
Expand Down
29 changes: 29 additions & 0 deletions nsot/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -970,3 +970,32 @@ def post(self, request, *args, **kwargs):
('data', True),
])
)
class IterableViewSet(ResourceViewSet):
"""
API endpoint that allows Iterables to be viewed or edited.
"""
queryset = models.Iterable.objects.all()
serializer_class = serializers.IterableSerializer
#filter_fields = ('name', 'description', 'min_val', 'max_val', 'increment', 'attributes')
filter_class = filters.IterableFilter
natural_key = 'name'

def get_serializer_class(self):
if self.request.method == 'POST':
return serializers.IterableCreateSerializer
if self.request.method in ('PUT'):
return serializers.IterableUpdateSerializer
if self.request.method in ('PATCH'):
return serializers.IterablePartialUpdateSerializer
return self.serializer_class

def get_natural_key_kwargs(self, filter_value):
"""Return a dict of kwargs for natural_key lookup."""
return {self.natural_key: filter_value}

@detail_route(methods=['get'])
def next_value(self, request, pk=None, site_pk=None, *args, **kwargs):
"""Return next available value from this Iterable"""
dynamicresource = self.get_resource_object(pk, site_pk)
value = dynamicresource.get_next_value()
return self.success(value)
50 changes: 50 additions & 0 deletions nsot/migrations/0036_auto_20171006_0118.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion
import django_extensions.db.fields.json


class Migration(migrations.Migration):

dependencies = [
('nsot', '0035_fix_interface_name_slug'),
]

operations = [
migrations.CreateModel(
name='Iterable',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('_attributes_cache', django_extensions.db.fields.json.JSONField(help_text='Local cache of attributes. (Internal use only)', blank=True)),
('name', models.CharField(help_text='The name of the Iterable.', max_length=255, db_index=True)),
('description', models.TextField(default='', help_text='A helpful description for the Iterable.', blank=True)),
('min_val', models.PositiveIntegerField(default=1, help_text='The minimum value of the Iterable.')),
('max_val', models.PositiveIntegerField(default=100, help_text='The maximum value of the Iterable.')),
('increment', models.PositiveIntegerField(default=1, help_text='Value to increment the Iterable.')),
('is_resource', models.BooleanField(default=False, help_text='Will this resource have children', db_index=True)),
('value', models.IntegerField(help_text='Current Value of Iterable', null=True)),
('parent', models.ForeignKey(related_name='children', on_delete=django.db.models.deletion.PROTECT, default=None, blank=True, to='nsot.Iterable', help_text='The parent DynamicResouce', null=True)),
('site', models.ForeignKey(related_name='iterable', on_delete=django.db.models.deletion.PROTECT, verbose_name='Site', to='nsot.Site', help_text='Unique ID of the Site assigned to this Iterable')),
],
),
migrations.AlterField(
model_name='attribute',
name='resource_name',
field=models.CharField(help_text='The name of the Resource to which this Attribute is bound.', max_length=20, verbose_name='Resource Name', db_index=True, choices=[('Device', 'Device'), ('Interface', 'Interface'), ('Iterable', 'Iterable'), ('Network', 'Network'), ('Circuit', 'Circuit')]),
),
migrations.AlterField(
model_name='network',
name='is_ip',
field=models.BooleanField(default=False, help_text='Whether the Network is a host address or not.', db_index=True, editable=False),
),
migrations.AlterUniqueTogether(
name='iterable',
unique_together=set([('site', 'name', 'value', 'parent')]),
),
migrations.AlterIndexTogether(
name='iterable',
index_together=set([('site', 'name', 'value', 'parent')]),
),
]
24 changes: 24 additions & 0 deletions nsot/migrations/0037_auto_20171006_0914.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('nsot', '0036_auto_20171006_0118'),
]

operations = [
migrations.AlterField(
model_name='change',
name='resource_name',
field=models.CharField(help_text='The name of the Resource for this Change.', max_length=20, verbose_name='Resource Type', db_index=True, choices=[('Network', 'Network'), ('Attribute', 'Attribute'), ('Site', 'Site'), ('Interface', 'Interface'), ('Circuit', 'Circuit'), ('Device', 'Device'), ('Iterable', 'Iterable')]),
),
migrations.AlterField(
model_name='value',
name='resource_name',
field=models.CharField(help_text='The name of the Resource type to which the Value is bound.', max_length=20, verbose_name='Resource Type', db_index=True, choices=[('Network', 'Network'), ('Attribute', 'Attribute'), ('Site', 'Site'), ('Interface', 'Interface'), ('Circuit', 'Circuit'), ('Device', 'Device'), ('Iterable', 'Iterable')]),
),
]
18 changes: 18 additions & 0 deletions nsot/migrations/0038_remove_iterable_is_resource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('nsot', '0037_auto_20171006_0914'),
]

operations = [
migrations.RemoveField(
model_name='iterable',
name='is_resource',
),
]
20 changes: 20 additions & 0 deletions nsot/migrations/0039_auto_20171006_1021.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('nsot', '0038_remove_iterable_is_resource'),
]

operations = [
migrations.AlterField(
model_name='iterable',
name='parent',
field=models.ForeignKey(related_name='children', on_delete=django.db.models.deletion.PROTECT, default=None, blank=True, to='nsot.Iterable', help_text='The parent Iterable', null=True),
),
]
Loading