Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Unable to query zones with a specific view name from the API. #171

Closed
jcollie opened this issue Apr 30, 2022 · 4 comments · Fixed by #164
Closed

Unable to query zones with a specific view name from the API. #171

jcollie opened this issue Apr 30, 2022 · 4 comments · Fixed by #164

Comments

@jcollie
Copy link

jcollie commented Apr 30, 2022

I am unable to query zones by view name using the API:

from pynetbox.core.api import Api

api = Api(
    "https://netbox.example.org/", token="*****************************************"
)
zones = api.plugins.netbox_dns.zones.filter(view="internal", name="ocjtech.us")
for zone in zones:
    print(f"{zone.id} {zone.name} {zone.view.id} {zone.view.name")

Gives me:

Traceback (most recent call last):
  File "/home/jeff/dev/netbox-dns/test.py", line 7, in <module>
    for zone in zones:
  File "/usr/lib/python3.10/site-packages/pynetbox/core/response.py", line 117, in __next__
    next(self.response), self.endpoint.api, self.endpoint
  File "/usr/lib/python3.10/site-packages/pynetbox/core/query.py", line 312, in get
    req = self._make_call(add_params=add_params)
  File "/usr/lib/python3.10/site-packages/pynetbox/core/query.py", line 282, in _make_call
    raise RequestError(req)
pynetbox.core.query.RequestError: The request failed with code 400 Bad Request: {'view': ['Select a valid choice. That choice is not one of the available choices.']}

But:

from pynetbox.core.api import Api

api = Api(
    "https://netbox.example.org/", token="*****************************************"
)
zones = api.plugins.netbox_dns.zones.filter(view=1, name="example.org")
for zone in zones:
    print(f"{zone.id} {zone.name} {zone.view.id} {zone.view.name}")

gives me:

1 example.org 1 internal

Using the view_id parameter works as well:

from pynetbox.core.api import Api

api = Api(
    "https://netbox.example.org/", token="*****************************************"
)
zones = api.plugins.netbox_dns.zones.filter(view_id=1, name="example.org")
for zone in zones:
    print(f"{zone.id} {zone.name} {zone.view.id} {zone.view.name}")

gives me:

1 example.org 1 internal
@peteeckel
Copy link
Contributor

Hi @jcollie, thanks for raising this issue.

The issue with addressing a view by its name in API queries is even a bit more tricky than you already found: Views are entirely optional for zones, so it's possible that there is not even a view that could be selected by a name. The main reasons for this are backward compatibiity, the fact that many users don't need views at all, and the fact that views are also optional in the configuration of BIND, which would otherwise be hard to map to NetBox DNS.

Currently the best solution is to do a two-step approach (as you already found out) and determine the ID of the view you want to query for, then in a second step get the zones for that view. Zones without a view are in this case addressed by view=null or view_id=null.

I'll look a bit deeper into this and try to find a way to enhance the Serializer code to accept view_name as well. Good point in any case, the two-step approach is a bit tedious indeed.

@peteeckel
Copy link
Contributor

OK, forget about the idea I outlined above, that wasn't the cause of the problem. I'm still trying to find out what happens.

@peteeckel
Copy link
Contributor

This was, after all, nothing but a stupid C&P error ... sorry for that. Fixed in the latest version of the PR.

@peteeckel
Copy link
Contributor

Short test with some similar code to yours:

#!/usr/bin/env python3

import sys
from pynetbox.core.api import Api

try:
    view = sys.argv[1]
except IndexError:
    view = "null"

api = Api(
    "https://192.168.106.105/", token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)
zones = api.plugins.netbox_dns.zones.filter(view=view)

for zone in zones:
    if zone.view is not None:
        print(f"{zone.id} {zone.name} {zone.view.id} {zone.view.name}")
    else:
        print(f"{zone.id} {zone.name} None None")

When using pynetbox it doesn't seem to be such a good idea to name a view "null" :-)

The results:

pete@lagavulin Desktop % python3 test_api_issues_171.py
30 zone1.example.com None None
pete@lagavulin Desktop % python3 test_api_issues_171.py internal
28 1.0.10.in-addr.arpa 1 internal
11 zone1.example.com 1 internal
4 zone4.example.com 1 internal
pete@lagavulin Desktop % python3 test_api_issues_171.py external
9 1.0.10.in-addr.arpa 2 external
10 2.0.10.in-addr.arpa 2 external
1 zone1.example.com 2 external
2 zone2.example.com 2 external
3 zone3.example.com 2 external
5 zone5.example.com 2 external
6 zone6.example.com 2 external
7 zone7.example.com 2 external
8 zone8.example.com 2 external
pete@lagavulin Desktop % python3 test_api_issues_171.py test    
29 test.example.com 3 test

Seems to do exactly what it should now, even with zones without views.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants