Create your backend
Every backend is based on the common ground of some elements provided by
the netjsonconfig library. The BaseBackend
, BaseConverter
,
BaseParser
and BaseRenderer
are a battle proven set of tools that
can be extended when creating you backend.
But the netjsonconfig package is not a playground to experiment, your contributions to a new backend should start elsewhere, a different package, where you are in control and can make errors and experiment more.
Netjsonconfig can now discover packages that provides a custom backend using a feature available in the Python packaging ecosystem which is called entry_points.
To create a new backend start from scratch with a new folder and add this file to your project root directory.
# example_backend/setup.py
from setuptools import setup, find_packages
setup(
name="example_backend",
version="0.0.0",
description="an example to illustrate a netjsonconfig backend as an external module",
install_requires=["netjsonconfig>=0.6.3"],
packages=find_packages(),
entry_points={
"netjsonconfig.backends": [
"example=example_backend.__init__:ExampleBackend",
]
},
)
this file can be used to create a package that can be installed using pip or other tools in the python ecosystem. You can find more information about Python packaging at packaging.python.org and at the hitchhikers guide to packaging.
The most important part is to give your package a good name, a well
thought description and to add the entry_points
keyword argument with
the following code
{
# this is used by netjsonconfig
# to find your backend
"netjsonconfig.backends": [...]
}
Now your package will be in the list of backends that netjsonconfig can use!
But we still have to give us a name to be unique! Netjsonconfig already
defined the names openwisp
, openwrt
and openvpn
but you can
choose whatever you like most.
The name netjsonconfig.backends
will be associated with a list of
classes from your package that will be presented to netjconfig at runtime.
To specify which classes you want to expose write the triple name
,
path
and class_name
using the format name=path:class_name
as
in the example below.
The path
part is simply the path to the file that contains the class
you want to expose and the class_name
is the name of the class.
{
"netjsonconfig.backends": [
# name=path:class_name
"example=example_backend.__init__:ExampleBackend",
]
}
The previous example can be used with the following class definition
# example_backend/example_backend/__init__.py
from netjsonconfig.backends.base.backend import BaseBackend
from netjsonconfig.backends.base.renderer import BaseRenderer
from netjsonconfig.backends.base.parser import BaseParser
from netjsonconfig.schema import schema as default_schema
class ExampleBackend(BaseBackend):
schema = default_schema
converter = []
parser = BaseParser
renderer = BaseRenderer
Once you have your python package configured with the correct entry points you should have a directory tree that looks like this.
$ tree example_backend
example_backend
├── example_backend
│ └── __init__.py
└── setup.py
And now you can install your package using pip install -e
./example_backend
or python setup.py install
.
As netjsonconfig
is a dependency for example_backend
you can use
your backend directly from the command line, e.g.
$ netjsonconfig
usage: netjsonconfig [-h] [--config CONFIG]
[--templates [TEMPLATES [TEMPLATES ...]]]
[--native NATIVE] --backend
{openwrt,openwisp,openvpn,example} --method
{render,generate,write,validate,json}
[--args [ARGS [ARGS ...]]] [--verbose] [--version]
netjsonconfig: error: the following arguments are required: --backend/-b, --method/-m
Notice the example in {openwrt,openwisp,openvpn,example}
? That’s
your backend!
The name exposed is the one chosen in the name, path, class triple from before
# name=path:class
"example=example_backend.__init__:ExampleBackend",