-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[general] Refactored backends, renderers, added converters #70
This is the first step in implementing #70. This patch does not introduce changes of behaviour in the library, infact tests remain unaltered, except for their names (because they were named after renderer classes which now are a much smaller part of the library). This patch introduces the concept of converter classes, which are responsible for converting the NetJSON configuration dictionary to an intermediate data structure that is then used by renderers to be rendered. The backward conversion will then implement the reverse process: Parsers will be responsible of converting native configuration to the intermediate data structure; Converters will have a to_netjson method that will be responsible of converting the intermediate data structure to the NetJSON configuration dictionary.
- Loading branch information
1 parent
d340d33
commit 2a6cfb2
Showing
32 changed files
with
515 additions
and
569 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
class BaseConverter(object): | ||
""" | ||
Base Converter class | ||
Converters are used to convert a configuration dictionary | ||
which represent a NetJSON object to a data structure that | ||
can be easily rendered as the final router configuration | ||
and vice versa. | ||
""" | ||
netjson_key = None | ||
|
||
def __init__(self, backend): | ||
self.backend = backend | ||
self.netjson = backend.config | ||
self.intermediate_data = backend.intermediate_data | ||
|
||
@classmethod | ||
def should_run(cls, config): | ||
""" | ||
Returns True if Converter should be instantiated and run | ||
Used to skip processing if the configuration part related to | ||
the converter is not present in the configuration dictionary. | ||
""" | ||
netjson_key = cls.netjson_key or cls.__name__.lower() | ||
return netjson_key in config | ||
|
||
def to_intermediate(self): # pragma: no cover | ||
raise NotImplementedError() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
from jinja2 import Environment, PackageLoader | ||
|
||
|
||
class BaseRenderer(object): | ||
""" | ||
Base Renderer class | ||
Renderers are used to generate a string | ||
which represents the router configuration | ||
""" | ||
def __init__(self, backend): | ||
self.config = backend.config | ||
self.backend = backend | ||
|
||
@property | ||
def env_path(self): | ||
return self.__module__ | ||
|
||
@property | ||
def template_env(self): | ||
return Environment(loader=PackageLoader(self.env_path, 'templates'), trim_blocks=True) | ||
|
||
@classmethod | ||
def get_name(cls): | ||
""" | ||
Returns the name of the render class without its prefix | ||
""" | ||
return str(cls.__name__).replace('Renderer', '').lower() | ||
|
||
def cleanup(self, output): | ||
""" | ||
Performs cleanup of output (indentation, new lines) | ||
:param output: string representation of the client configuration | ||
""" | ||
return output | ||
|
||
def render(self): | ||
""" | ||
Renders configuration by using the jinja2 templating engine | ||
""" | ||
# get jinja2 template | ||
template_name = '{0}.jinja2'.format(self.get_name()) | ||
template = self.template_env.get_template(template_name) | ||
# render template and cleanup | ||
context = getattr(self.backend, 'intermediate_data', {}) | ||
output = template.render(data=context) | ||
return self.cleanup(output) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from ..base.renderer import BaseRenderer | ||
|
||
|
||
class OpenVpnRenderer(BaseRenderer): | ||
""" | ||
OpenVPN Renderer | ||
""" | ||
def cleanup(self, output): | ||
# remove indentations | ||
output = output.replace(' ', '') | ||
# remove last newline | ||
if output.endswith('\n\n'): | ||
output = output[0:-1] | ||
return output |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
2a6cfb2
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.
@ritwickdsouza @edoput I already deployed this change in 3 production instances.
This change is the first step that will make possible to implement #70 (backward conversion), but it should also simplify development for the forward conversion (from NetJSON to native router configuration).
It is especially handy for you @edoput because you can create an "intermediate data" structure that represents the AirOS configuration format and then use only one jinja template to render that data structure (like is now for OpenWRT, notice that there's only one renderer class and one jinja template for OpenWRT now).
It will be less easy for @ritwickdsouza because he has to deal with several configuration formats, which will require to write more renderers and jinja2 templates.
I will try to explain in detail this change via email as soon as possible.