Skip to content

Commit ec56134

Browse files
authored
Merge pull request #106 from edoput/master
query backends from installed packages
2 parents 11cfed1 + 2bf557c commit ec56134

5 files changed

Lines changed: 121 additions & 9 deletions

File tree

bin/netjsonconfig

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#!/usr/bin/env python
22

3+
import argparse
34
import os
45
import sys
6+
57
import six
6-
import argparse
8+
79
import netjsonconfig
810

911
description = """
@@ -56,7 +58,7 @@ output = parser.add_argument_group('output')
5658

5759
output.add_argument('--backend', '-b',
5860
required=True,
59-
choices=['openwrt', 'openwisp', 'openvpn'],
61+
choices=netjsonconfig.get_backends().keys(),
6062
action='store',
6163
type=str,
6264
help='Configuration backend')
@@ -166,13 +168,8 @@ context = dict(os.environ)
166168
method = args.method
167169
method_arguments = parse_method_arguments(args.args)
168170

169-
backends = {
170-
'openwrt': netjsonconfig.OpenWrt,
171-
'openwisp': netjsonconfig.OpenWisp,
172-
'openvpn': netjsonconfig.OpenVpn
173-
}
174171

175-
backend_class = backends[args.backend]
172+
backend_class = netjsonconfig.get_backends()[args.backend]
176173
try:
177174
options = dict(templates=templates, context=context)
178175
if args.config:
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
2+
===================
3+
Create your backend
4+
===================
5+
6+
.. include:: ../_github.rst
7+
8+
Every backend is based on the common ground of some elements provided by the
9+
netjsonconfig library. The `BaseBackend`, `BaseConverter`, `BaseParser` and
10+
`BaseRenderer` are a battle proven set of tools that can be extended when
11+
creating you backend.
12+
13+
But the netjsonconfig package is not a playground to experiment, your contributions
14+
to a new backend should start elsewhere, a different package, where you are in control
15+
and can make errors and experiment more.
16+
17+
Netjsonconfig can now discover packages that provides a custom backend using
18+
a feature available in the Python packaging ecosystem which is called `entry_points`.
19+
20+
To create a new backend start from scratch with a new folder and add this file to your
21+
project root directory.
22+
23+
.. code-block:: python
24+
25+
# setup.py
26+
from setuptools import setup, find_packages
27+
28+
setup(
29+
name='example_backend',
30+
version='0.0.0',
31+
description='an example to illustrate a netjsonconfig backend as an external module',
32+
packages=find_packages(),
33+
entry_points={
34+
'netjsonconfig.backends': [
35+
'example=example_backend.__init__:ExampleBackend',
36+
]
37+
}
38+
)
39+
40+
this file can be used to create a package that can be installed using pip or other tools
41+
in the python ecosystem. You can find more information about Python packaging
42+
`at packaging.python.org <https://packaging.python.org/>`_
43+
and `at the hitchhikers guide to packaging <https://the-hitchhikers-guide-to-packaging.readthedocs.io/en/latest/>`_.
44+
45+
The most important part is to give your package a good name, a well thought description and
46+
to add the `entry_points` keyword argument with the following code
47+
48+
.. code-block:: python
49+
50+
{
51+
# this is used by netjsonconfig
52+
# to find your backend
53+
'netjsonconfig.backends': [
54+
...
55+
]
56+
}
57+
58+
Now your package will be in the list of backends that netjsonconfig can use!
59+
60+
But we still have to give us a name to be unique! Netjsonconfig already
61+
defined the names `openwisp`, `openwrt` and `openvpn` but you can choose
62+
whatever you like most.
63+
64+
The name `netjsonconfig.backends` will be associated with a list of classes
65+
from your package that will be presented to netjconfig at runtime. To specify
66+
which classes you want to expose write the triple `name`, `path` and `class_name`
67+
using the format `name=path:class_name` as in the example below.
68+
69+
The `path` part is simply the path to the file that contains the class
70+
you want to expose and the `class_name` is the name of the class.
71+
72+
.. code-block:: python
73+
74+
{
75+
'netjsonconfig.backends': [
76+
# name=path:class_name
77+
'example=example_backend.__init__:ExampleBackend',
78+
]
79+
}
80+
81+
The previous example can be used with the following class definition
82+
83+
.. code-block:: python
84+
85+
# example_backend/__init__.py
86+
from netjsonconfig.backends.base.backend import BaseBackend
87+
from netjsonconfig.backends.base.renderer import BaseRenderer
88+
from netjsonconfig.backends.base.parser import BaseParser
89+
90+
from netjsonconfig.schema import schema as default_schema
91+
92+
class ExampleBackend(BaseBackend):
93+
schema = default_schema
94+
converter = []
95+
parser = BaseParser
96+
renderer = BaseRenderer

docs/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Contents:
5555
/backends/openwrt
5656
/backends/openwisp
5757
/backends/openvpn
58+
/backends/create_your_backend
5859
/general/commandline_utility
5960
/general/running_tests
6061
/general/contributing

netjsonconfig/__init__.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
1+
from pkg_resources import iter_entry_points
2+
import logging
3+
14
from .version import VERSION, __version__, get_version # noqa
25

36
from .backends.openwrt.openwrt import OpenWrt # noqa
47
from .backends.openwisp.openwisp import OpenWisp # noqa
58
from .backends.openvpn.openvpn import OpenVpn # noqa
9+
10+
11+
def get_backends():
12+
default = {
13+
'openwrt': OpenWrt,
14+
'openwisp': OpenWisp,
15+
'openvpn': OpenVpn,
16+
}
17+
logger = logging.getLogger(__name__)
18+
19+
for entry_point in iter_entry_points('netjsonconfig.backends'):
20+
try:
21+
default.update({entry_point.name.lower(): entry_point.load()})
22+
except ImportError as e: # noqa
23+
logger.error("Error loading backend {}".format(entry_point.name.lower()))
24+
return default

netjsonconfig/backends/openwrt/schema.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from ..openvpn.schema import base_openvpn_schema
77
from .timezones import timezones
88

9-
109
default_radio_driver = "mac80211"
1110

1211

0 commit comments

Comments
 (0)