-
Notifications
You must be signed in to change notification settings - Fork 66
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
Interface Tree traversal #271
Conversation
Oh awesome. Sorry I've been behind the curve. I'll check this out. Thank you!! |
I'm going to review this damn thing eventually. I need a clone. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great! Just have a couple minor adjustments.
nsot/api/views.py
Outdated
"""Return parent of interface""" | ||
interface = self.get_resource_object(pk, site_pk) | ||
parent = [] if interface.parent is None else [interface.parent] | ||
return self.list(request, queryset=parent, *args, **kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parent should return only a single object vs. a list. See NetworkViewSet.parent
for a good reference on how it's done for network objects.
nsot/models.py
Outdated
|
||
def get_siblings(self): | ||
"""Return the interfaces with same parent as an interface""" | ||
return list(Interface.objects.filter(parent=self.parent).exclude(id=self.id)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Siblings should be interfaces with both the same parent AND the same device, otherwise all interfaces with no parent are considered to be siblings, which I don't think is what we really want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jathanism Currently you can create a interface on a device and set its parent to an interface on another device. Should I create a validation check that prevents that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I guess that is a pretty sane constraint!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay I will work on this.
nsot/models.py
Outdated
root = self.parent | ||
while root is not None and root.parent is not None: | ||
root = root.parent | ||
return [] if root is None else [root] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to @jathanism's comment on parent
, this should have the same behavior and return a single object rather than a list.
Hi @jathanism and @nickpegg, I saw the feed back on #266 and #271. I will work on them soon. |
- used self.retrieve to return parent and root of interfaces - changed filter query on siblings to look for interfaces with same parent and device
Hi @jathanism and @nickpegg I worked on the changes you requested. Sorry it took so long. |
@rmhasan There's no need to apologize, you're a hero! |
- If someone calls the root view on an Interface object and its parent is None, then it should be returned as the root - Also added tests to check that if sibling is called on an Interface object, then Interface objects with same parent and device are returned
-Added validation check to prevent users from adding interfaces with different device than its parent or add a parent to an existing interface that has a different device than itself -Also added test to check that when a user calls siblings view on an interface object, then only interfaces with same parent and device are returned
Hi @jathanism and @nickpegg. I made the following changes.
EDIT: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything looks pretty good overall! I just have some minor asks to wrap this up and a few comments to think about.
nsot/models.py
Outdated
return parent | ||
if parent.device_hostname != self.device_hostname: | ||
raise exc.ValidationError({ | ||
'parent': 'Parent\'s device does not match device with host name \"%s\"'%(self.device_hostname) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry to nitpick but can you please change this string to be double-quoted so that we can eliminate the backslashes. It make for better readability. You can also use %r
vs. %s
to get the repr conversion of the object, which includes quotes.
e.g.
"Parent's device does not match device with host name %r" % self.device_hostname
results in
"Parent's device does not match device with host name 'foo'"
nsot/api/views.py
Outdated
return self.list(request, queryset=interface.networks, *args, **kwargs) | ||
|
||
@detail_route(methods=['get']) | ||
def parent(self, request, pk=None, site_pk=None, *args, **kwargs): | ||
"""Return parent of interface""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please update the docstring to be similar in style to the one at nsot.api.NetworkViewSet.parent()
?
And for the remaining methods you've added can you please make sure they all have docstrings?
This is important because the docstrings are used in the automated API documentation on nsot.readthedocs.io and in the browsable API.
nsot/models.py
Outdated
def get_ancestors(self): | ||
"""Recursively get all parents of an interface""" | ||
p = self.parent | ||
ancestors = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a comment: Returning a list instead of a queryset may be problematic if we attempt to implement any filtering (or filter chaining) for ancestors. This isn't currently a use-case but it will be something to keep in mind if the need arises in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @jathanism, how about I do the following. I get all the id's of the ancestors in a list like the following
ancestor_ids = [a.id for a in ancestors]
Then I return the Queryset
from the following query
Interface.objects.filter(id__in=ancestor_ids)
nsot/models.py
Outdated
def get_descendants(self): | ||
"""Recursively return all the children of an interface""" | ||
s = list(self.get_children()) | ||
children = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a comment: Similarly to ancestors, returning a list may be problematic if we ever need to filter (or chain filters) on descendant interfaces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use the same fix mentioned in the Interface.get_ancestors
comment.
nsot/models.py
Outdated
|
||
def get_siblings(self): | ||
"""Return the interfaces with same parent as an interface""" | ||
return list(Interface.objects.filter(parent=self.parent, device=self.device).exclude(id=self.id)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a comment: Last but not least, casting the queryset to a list may become problematic in the future in the event we need to implement filtering or desire to chain filters on these results.
- Updated docstrings for parent and added docstrings for other view functions - Changing ValidationError message for setting siblings to use a double quoted string - Also returning a queryset from get_siblings instead of a list
Hi @jathanism I made the following changes
|
- Update the docstring of some Interface model functions - Return queryset from get_descendants and get_ancestors in Interface model
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome. Thank you! I'm gonna ask @nickpegg to take a look, too!
Thanks for this contribution! :) I'm merging this and cutting a new version. I'll drop a note on this PR once that version's available on PyPI. |
v.1.1.4 released to PyPI: https://pypi.python.org/pypi/nsot/1.1.4 |
Added following methods in
InterfaceViewSet
which can be invoked by get requests to return view setsAlso implemented following methods in
Interface
model class inmodels.py
which get invoked in the view methodsAlso added tests in
tests/api_tests/test_interfaces.py
andtests/model_tests/test_interfaces.py