Giter VIP home page Giter VIP logo

netbox-plugin-tutorial's People

Contributors

brunosardinepi avatar dreng avatar jeffgdotorg avatar jeremystretch avatar ns1pelle avatar rixx avatar zorlin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

netbox-plugin-tutorial's Issues

Problem with webhooks

Thank you Jeremy for a great tutorial. I have built a plugin following the plugin tutorial everything works fine however upon trying to put the models so that it could initiate the webhook because i need to use changes to the models to make some changes outside netbox its not working.

I went on to install the plugin (netbox-access-lists) on my server and i tried to get a webhook response from the plugin to no avail. I am getting a repsonse though using built in models like 'dcim.devices' as shown in the image below

Screenshot from 2022-07-20 12-48-00

What aspects should i change in order to get a response from the webhook using the tutorial as the case study

Unable to import plugin netbox_access_lists: Module not found.

After following the instructions about 45 times. Each time resulting with the same issue. After restarting netbox, I'm seeing the error in the logs. "Unable to import plugin netbox_access_lists" and it fails to start.

  1. I am running the virtual environment. Using: source /opt/netbox/venv/bin/activate
  2. I am installing the plugin. I have tried the following installation methods. (pip install --editable .) from the plugin directory as well as (python3 setup.py develop)
  3. I have checked out step 001 to make sure I didn't have a typo.
  4. I have the latest vanilla netbox.
  5. The configuratioon.py does have the correct named plugin in it.
  6. I have the most recent versions of everything Python3, Postgres, Redis, Nginx, available to Ubuntu 22 and I can confirm the vanilla version runs fine before adding any plugins.

Somethings not installing or adding correctly. etc.

Add note about url name rule

Hello, everyone

I'm trying to develop netbox plugin while refering to this tutorial.

However, when step 5, I stucked because netbox rule.
Therefore, I would like to add comment for this netbox rule explicitly.

problem

Add button is not shown in model list view if URL name with `_'.
when refering Test the Views

ex) when model name is VLANGroupSet
good: vlangroupset_add
bad: vlan_group_set_add

Maybe this rule is related in /netbox/utilities/utils.py

(I cloud not find truth information, sorry)

Feature Suggestion: Plugin Configuration Options

It would be useful as a new plugin author to include tutorial steps on adding and utilising configuration options. (It took me a little while to reverse engineer how to access plugin config options within my code).

Confused about how to move from step 1 to step 2

I just started with the tutorial as described in Step 1 and have successfully installed "my" plugin.

Step 2 starts with the following note:

Note: If you skipped the previous step, run git checkout step01-initial-setup.

Step 1 ends with the following tip

Tip: You can check your work at the end of each step in the tutorial by running a git diff against the corresponding branch. For example, at the end of step one, run git diff step01-initial-setup to compare your work with the completed step. This will help identify any tasks you might have missed.

Executing this last command in the location where I ended up after installing the pug, I get

fatal: ambiguous argument 'step01-initial-setup': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

Executing the git command from the beginning of step 2 I get

error: The following untracked working tree files would be overwritten by checkout:
	README.md
	netbox_access_lists/__init__.py
	setup.py
Please move or remove them before you switch branches.
Aborting

My git-foo is pretty poor, so I am lost on what to do next. Step 2 suggests that there should have been a git command executed at the end of step 1, but I am sure that a diff is not the one.

What did I miss?

Thanks!

Issue loading model form in AccessListEditView and AccessListRuleEditView

In the guide the EditView forms are defined as:

class AccessListEditView(generic.ObjectEditView):
    queryset = models.AccessList.objects.all()
    form = forms.AccessListForm

class AccessListRuleEditView(generic.ObjectEditView):
    queryset = models.AccessListRule.objects.all()
    form = forms.AccessListRuleForm

Trying to render the pages an error occur:

TypeError at /plugins/access-lists/access-lists/add/
'NoneType' object is not callable
Request Method:	GET
Request URL:	http://127.0.0.1:8000/plugins/access-lists/access-lists/add/
Django Version:	4.0.3
Exception Type:	TypeError
Exception Value:	
'NoneType' object is not callable
Exception Location:	/opt/netbox/netbox/netbox/views/generic/object_views.py, line 342, in get
Python Executable:	/opt/netbox/venv/bin/python3
Python Version:	3.8.10
Python Path:	
['/opt/netbox/netbox',
 '/usr/lib/python38.zip',
 '/usr/lib/python3.8',
 '/usr/lib/python3.8/lib-dynload',
 '/opt/netbox/venv/lib/python3.8/site-packages',
 '/home/network/netbox-plugin-demo']
Server time:	Tue, 05 Apr 2022 12:43:58 +0000

Checking the inherited class generic.ObjectEditView it seems the variable name for model form should be model_form

Updating the two views in views.py as shown here seems to fix the issue:

class AccessListEditView(generic.ObjectEditView):
    queryset = models.AccessList.objects.all()
-   form = forms.AccessListForm
+   model_form = forms.AccessListForm

class AccessListRuleEditView(generic.ObjectEditView):
    queryset = models.AccessListRule.objects.all()
-   form = forms.AccessListRuleForm
+   model_form = forms.AccessListRuleForm

ImportError in api/urls.py

Environment
Python: 3.8.10
Code: v3.2-beta2 (got from sudo git clone -b v3.2-beta2 --depth 1 https://github.com/netbox-community/netbox.git . )

Cloning the netbox-plugin-tutorial doing a checkout on the last step to try out the functionality.

When applying the migrations with python netbox/manage.py migrate produces the following error.

  File "/home/network/netbox-plugin-demo/netbox_access_lists/api/urls.py", line 1, in <module>
    from netbox.api.routers import NetBoxRouter
ImportError: cannot import name 'NetBoxRouter' from 'netbox.api.routers' (/opt/netbox/netbox/netbox/api/routers.py)

Looking at the contents of netbox/netbox/netbox/api/routers.py in v3.2-beta2 it does not seem to have a NetBoxRouter class

from collections import OrderedDict
  
from rest_framework.routers import DefaultRouter


class OrderedDefaultRouter(DefaultRouter):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Extend the list view mappings to support the DELETE operation
        self.routes[0].mapping.update({
            'put': 'bulk_update',
            'patch': 'bulk_partial_update',
            'delete': 'bulk_destroy',
        })

    def get_api_root_view(self, api_urls=None):
        """
        Wrap DRF's DefaultRouter to return an alphabetized list of endpoints.
        """
        api_root_dict = OrderedDict()
        list_name = self.routes[0].name
        for prefix, viewset, basename in sorted(self.registry, key=lambda x: x[0]):
            api_root_dict[prefix] = list_name.format(basename=basename)

        return self.APIRootView.as_view(api_root_dict=api_root_dict)```

Debugging a plugin

Hello everyone,

I'm trying to debug a new plugin I'm writing for Netbox. But I'm currently stuck at the error. 'netbox_redfish' is not a registered namespace inside 'plugins'

There is a stack trace but it isn't pointing to the line of code wich is causing the error.

image

Code can be found here: https://github.com/accelleran/netbox_redfish

Correct the URL in guides step 5

Near the bottom of the page for Step5 there is a section Test the Views that contains the following URL: http://localhost:8000/plugins/netbox-access-lists/access-lists/

Trying to open the URL provides the following error:

Using the URLconf defined in netbox.urls, Django tried these URL patterns, in this order:

[name='home']
search/ [name='search']
login/ [name='login']
logout/ [name='logout']
oauth/
circuits/
dcim/
extras/
ipam/
tenancy/
user/
virtualization/
wireless/
api/ [name='api-root']
api/circuits/
api/dcim/
api/extras/
api/ipam/
api/tenancy/
api/users/
api/virtualization/
api/wireless/
api/status/ [name='api-status']
api/docs/ [name='api_docs']
api/redoc/ [name='api_redocs']
^api/swagger(?P<format>.json|.yaml)$ [name='schema_swagger']
graphql/ [name='graphql']
media/<path:path>
media-failure/ [name='media_failure']
plugins/ access-lists/
api/plugins/
admin/background-tasks/
admin/plugins/
admin/
__debug__/
The current path, plugins/netbox-access-lists/access-lists/, didn’t match any of these.

error message in step one

When I run python3 setup.py develop I get the message:

running develop
/usr/lib/python3/dist-packages/setuptools/command/easy_install.py:158: EasyInstallDeprecationWarning: easy_install command is deprecated. Use build and pip and other standards-based tools.
  warnings.warn(
/usr/lib/python3/dist-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
  warnings.warn(
/usr/lib/python3/dist-packages/pkg_resources/__init__.py:116: PkgResourcesDeprecationWarning: 0.1.43ubuntu1 is an invalid version and will not be supported in a future release
  warnings.warn(
/usr/lib/python3/dist-packages/pkg_resources/__init__.py:116: PkgResourcesDeprecationWarning: 1.1build1 is an invalid version and will not be supported in a future release
  warnings.warn(
running egg_info
writing netbox_end_of_support.egg-info/PKG-INFO
writing dependency_links to netbox_end_of_support.egg-info/dependency_links.txt
writing top-level names to netbox_end_of_support.egg-info/top_level.txt
reading manifest file 'netbox_end_of_support.egg-info/SOURCES.txt'
writing manifest file 'netbox_end_of_support.egg-info/SOURCES.txt'
running build_ext
Creating /usr/local/lib/python3.8/dist-packages/netbox-end-of-support.egg-link (link to .)
netbox-end-of-support 0.1 is already the active version in easy-install.pth

Installed /opt/netbox-3.4.4/plugins
Processing dependencies for netbox-end-of-support==0.1
Finished processing dependencies for netbox-end-of-support==0.1

When running the command mange.py run server. I get the message:

Unable to import plugin netbox-end-of-support: Module not found. Check that the plugin module has been installed within the correct Python environment.

What am I doing wrong

New plugin, but API won't load

I've followed the tutorial, started a very basic plugin (just 1 model in models.py for now) from scratch and for the life of me I can't get the API of the plugin to load. If I put an obvious syntax error into urls.py, automatic reloading or manually restarting the server doesn't give an error. Opening netbox, no error. Trying to access the API URL just returns a 404 (or rather the debug version of that) that the route doesn't exist, which matches the behaviour I am seeing.

The plugin itself works fine. I must be missing something obvious, but after looking at all the files I don't see any difference apart from naming to the tutorial or existing plugins with an API. And yet... The API directory has just the name "api", I even checked that....

Has anyone ever seen this before and can help? If necessary I can add some files here, but I am not sure which ones would be relevant.

Thanks!

ChoiceSet must be list not tuple to support extending

Following the tutorial and creating the ChoiceSet as a tuple results in the following error when extending via FIELD_CHOICES

AttributeError: 'tuple' object has no attribute 'extend'

The tutorial has the following

class ActionChoices(ChoiceSet):
    key = 'AccessListRule.action'

    CHOICES = (
        ('permit', 'Permit', 'green'),
        ('deny', 'Deny', 'red'),
        ('reject', 'Reject (Reset)', 'orange'),
    )

It should be

class ActionChoices(ChoiceSet):
    key = 'AccessListRule.action'

    CHOICES = [
        ('permit', 'Permit', 'green'),
        ('deny', 'Deny', 'red'),
        ('reject', 'Reject (Reset)', 'orange'),
    ]

Error when open plugin

Hello, I have one error when I open plugin in my netbox . Is it compatible with v3.6.4 Netbox ?

Server Error

There was a problem with your request. Please contact an administrator.

The complete exception is provided below:

<class 'ValueError'>

Cannot query "rpawela": Must be "SavedTopology" instance.

Python version: 3.9.2
NetBox version: 3.6.4
Plugins:
netbox_bgp: 0.11.0
netbox_dns: 0.20.2
netbox_interface_sync: 0.2.0
netbox_qrcode: 0.0.10
netbox_topology_views: 3.8.1
nextbox_ui_plugin: 0.13.0

If further assistance is required, please post to the NetBox discussion forum on GitHub.

Getting error after at views

File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/usr/lib/python3.8/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "/usr/local/lib/python3.8/dist-packages/django/utils/autoreload.py", line 64, in wrapper
fn(*args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/django/core/management/commands/runserver.py", line 133, in inner_run
self.check(display_num_errors=True)
File "/usr/local/lib/python3.8/dist-packages/django/core/management/base.py", line 485, in check
all_issues = checks.run_checks(
File "/usr/local/lib/python3.8/dist-packages/django/core/checks/registry.py", line 88, in run_checks
new_errors = check(app_configs=app_configs, databases=databases)
File "/usr/local/lib/python3.8/dist-packages/django/core/checks/urls.py", line 42, in check_url_namespaces_unique
all_namespaces = _load_all_namespaces(resolver)
File "/usr/local/lib/python3.8/dist-packages/django/core/checks/urls.py", line 61, in _load_all_namespaces
url_patterns = getattr(resolver, "url_patterns", [])
File "/usr/local/lib/python3.8/dist-packages/django/utils/functional.py", line 57, in get
res = instance.dict[self.name] = self.func(instance)
File "/usr/local/lib/python3.8/dist-packages/django/urls/resolvers.py", line 715, in url_patterns
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
File "/usr/local/lib/python3.8/dist-packages/django/utils/functional.py", line 57, in get
res = instance.dict[self.name] = self.func(instance)
File "/usr/local/lib/python3.8/dist-packages/django/urls/resolvers.py", line 708, in urlconf_module
return import_module(self.urlconf_name)
File "/usr/lib/python3.8/importlib/init.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "", line 1014, in _gcd_import
File "", line 991, in _find_and_load
File "", line 975, in _find_and_load_unlocked
File "", line 671, in _load_unlocked
File "", line 848, in exec_module
File "", line 219, in _call_with_frames_removed
File "/opt/netbox-3.6.6/netbox/netbox/urls.py", line 9, in
from extras.plugins.urls import plugin_admin_patterns, plugin_patterns, plugin_api_patterns
File "/opt/netbox-3.6.6/netbox/extras/plugins/urls.py", line 31, in
urlpatterns = import_string(f"{plugin_path}.urls.urlpatterns")
File "/usr/local/lib/python3.8/dist-packages/django/utils/module_loading.py", line 30, in import_string
return cached_import(module_path, class_name)
File "/usr/local/lib/python3.8/dist-packages/django/utils/module_loading.py", line 15, in cached_import
module = import_module(module_path)
File "/usr/lib/python3.8/importlib/init.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "/home/vayu/netbox-plugins/netbox_access_lists/urls.py", line 13, in
path('access-lists/int:pk/changelog/', ObjectChangeLogView.as_view(), name='accesslist_changelog', kwargs={
NameError: name 'ObjectChangeLogView' is not defined

This is the error I am facing while running the views

Issue with actions for AccessListListView and AccessListRuleListView in views.py

When defining the AccessListListView and AccessListRuleListView in views.py

class AccessListListView(generic.ObjectListView):
    queryset = models.AccessList.objects.annotate(
        rule_count=Count('rules')
    )
    table = tables.AccessListTable


class AccessListRuleListView(generic.ObjectListView):
    queryset = models.AccessListRule.objects.all()
    table = tables.AccessListRuleTable
    filterset = filtersets.AccessListRuleFilterSet
    filterset_form = forms.AccessListRuleFilterForm

If we do not define actions it seem they default to actions present in netbox/views/generic/bulk_views.py class ObjectListView which requires to have all of the following: actions = ('add', 'import', 'export', 'bulk_edit', 'bulk_delete').

Since for the demo example does not define urls and views for 'import' , 'bulk_edit', 'bulk_delete' the rendering of the page fails with Error:

Reverse for 'None' not found. 'None' is not a valid view function or pattern name.
1	<a href="{% url import_url %}" type="button" class="btn btn-sm btn-info">
2	  <i class="mdi mdi-upload"></i>&nbsp;Import
3	</a>
4

Editing the two Class views in views.py to add the actions variable seems to fix the issue (but please verify if this is even a proper fix)

class AccessListListView(generic.ObjectListView):
    queryset = models.AccessList.objects.annotate(
        rule_count=Count('rules')
    )
+   actions = ('add', 'export')
    table = tables.AccessListTable


class AccessListRuleListView(generic.ObjectListView):
    queryset = models.AccessListRule.objects.all()
+   actions = ('add', 'export')
    table = tables.AccessListRuleTable
    filterset = filtersets.AccessListRuleFilterSet
    filterset_form = forms.AccessListRuleFilterForm

Error in documentation to create views.py

There is an error in the documentation step05_views.md. It says "models.AccessListTable" instead of "tables.AccessListTable"

class AccessListListView(generic.ObjectListView):
    queryset = models.AccessList.objects.all()
    table = models.AccessListTable

It is then correct in the next code example:

from django.db.models import Count
# ...
class AccessListListView(generic.ObjectListView):
    queryset = models.AccessList.objects.annotate(
        rule_count=Count('rules')
    )
    table = tables.AccessListTable

Add MANIFEST.in into tutorial

In the tutorial is missing creating a MANIFEST.in file.
When missing without proper lines

recursive-include <plugin_folder>/templates *

it causes the django.template.exceptions.TemplateDoesNotExist: <plugin_name>/<templates>.html when installing within a netbox.

Tags field not working properly in AccessListForm and AccessListRuleForm

In the current configuration (show bellow) using the AccessListForm and AccessListRuleForm forms to add new objects makes it mandatory to use tags field. Also the Tags should load automatically similar how the source and destination prefix work on the AccessListRuleForm form.

class AccessListForm(NetBoxModelForm):
    comments = CommentField()

    class Meta:
        model = AccessList
        fields = ('name', 'default_action', 'comments', 'tags')


class AccessListRuleForm(NetBoxModelForm):
    access_list = DynamicModelChoiceField(
        queryset=AccessList.objects.all()
    )
    source_prefix = DynamicModelChoiceField(
        queryset=Prefix.objects.all()
    )
    destination_prefix = DynamicModelChoiceField(
        queryset=Prefix.objects.all()
    )

    class Meta:
        model = AccessListRule
        fields = (
            'access_list', 'index', 'description', 'source_prefix', 'source_ports', 'destination_prefix',
            'destination_ports', 'protocol', 'action', 'tags',
        )

To get away from mandatory tags field and to make tags dynamically load and support multiple tags on the created object we should change the the Forms.

changes:

-from utilities.forms.fields import CommentField, DynamicModelChoiceField
+from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField

class AccessListForm(NetBoxModelForm):
    comments = CommentField()

+    tags = DynamicModelMultipleChoiceField(
+        queryset=Tag.objects.all(),
+        required=False
+    )
+

    class Meta:
        model = AccessList
        fields = ('name', 'default_action', 'comments', 'tags')



class AccessListRuleForm(NetBoxModelForm):
    access_list = DynamicModelChoiceField(
        queryset=AccessList.objects.all()
    )
    source_prefix = DynamicModelChoiceField(
        queryset=Prefix.objects.all()
    )
    destination_prefix = DynamicModelChoiceField(
        queryset=Prefix.objects.all()
    )
+    tags = DynamicModelMultipleChoiceField(
+        queryset=Tag.objects.all(),
+        required=False
+    )

    class Meta:
        model = AccessListRule
        fields = (
            'access_list', 'index', 'description', 'source_prefix', 'source_ports', 'destination_prefix',
            'destination_ports', 'protocol', 'action', 'tags',
        )

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.