Skip to content

Commit

Permalink
[req-changes] Added ZeroTier Parser
Browse files Browse the repository at this point in the history
  • Loading branch information
Aryamanz29 committed Jun 11, 2023
1 parent f98e26f commit 0f82d3f
Show file tree
Hide file tree
Showing 6 changed files with 466 additions and 59 deletions.
2 changes: 1 addition & 1 deletion netjsonconfig/backends/base/backend.py
Expand Up @@ -380,7 +380,7 @@ def _generate_contents(self, tar):
# create a file for each VPN
for vpn in vpn_instances:
lines = vpn.split('\n')
vpn_name = lines[0]
vpn_name = lines[0].split(self.config_suffix)[0]
text_contents = '\n'.join(lines[2:])
# do not end with double new line
if text_contents.endswith('\n\n'):
Expand Down
5 changes: 5 additions & 0 deletions netjsonconfig/backends/zerotier/converters.py
Expand Up @@ -15,3 +15,8 @@ def to_intermediate_loop(self, block, result, index=None):

def __intermediate_vpn(self, config, remove=None):
return self.sorted_dict(config)

def to_netjson_loop(self, block, result, index):
result.setdefault('zerotier', [])
result['zerotier'].append(block)
return result
38 changes: 30 additions & 8 deletions netjsonconfig/backends/zerotier/parser.py
@@ -1,21 +1,43 @@
import re
import tarfile
from json import loads

from ..base.parser import BaseParser

vpn_pattern = re.compile('^// zerotier controller config:\s', flags=re.MULTILINE)
config_pattern = re.compile('^([^\s]*) ?(.*)$')
config_suffix = ''
config_suffix = '.json'


class ZeroTierParser(BaseParser):
def parse_text(self, config):
raise NotImplementedError()
return {'zerotier': self._get_vpn_config(config)}

def parse_tar(self, tar):
raise NotImplementedError()
fileobj = tar.buffer if hasattr(tar, 'buffer') else tar
tar = tarfile.open(fileobj=fileobj)
text = ''
for member in tar.getmembers():
if not member.name.endswith(config_suffix):
continue
text += '// zerotier controller config: {name}\n\n{contents}\n'.format(
**{
'name': member.name.replace(config_suffix, ''),
'contents': tar.extractfile(member).read().decode(),
}
)
return self.parse_text(text)

def _get_vpns(self, text):
raise NotImplementedError()

def _get_config(self, contents):
raise NotImplementedError()
def _get_vpn_config(self, text):
vpn_configs = []
vpn_instances = vpn_pattern.split(text)
if '' in vpn_instances:
vpn_instances.remove('')
for vpn in vpn_instances:
lines = vpn.split('\n')
text_contents = '\n'.join(lines[2:])
# do not end with double new line
if text_contents.endswith('\n\n'):
text_contents = text_contents[0:-1]
vpn_configs.append(loads(text_contents))
return vpn_configs
3 changes: 2 additions & 1 deletion netjsonconfig/backends/zerotier/zerotier.py
@@ -1,6 +1,6 @@
from ..base.backend import BaseVpnBackend
from . import converters
from .parser import config_suffix, vpn_pattern
from .parser import ZeroTierParser, config_suffix, vpn_pattern
from .renderer import ZeroTierRenderer
from .schema import schema

Expand All @@ -9,6 +9,7 @@ class ZeroTier(BaseVpnBackend):
schema = schema
converters = [converters.ZeroTier]
renderer = ZeroTierRenderer
parser = ZeroTierParser
# BaseVpnBackend attributes
vpn_pattern = vpn_pattern
config_suffix = config_suffix
Expand Down
134 changes: 110 additions & 24 deletions tests/zerotier/test_backend.py
@@ -1,5 +1,6 @@
import tarfile
import unittest
from copy import deepcopy

from netjsonconfig import ZeroTier
from netjsonconfig.exceptions import ValidationError
Expand All @@ -11,6 +12,8 @@ class TestBackend(unittest.TestCase):
"""

maxDiff = None

# Single test config
_TEST_CONFIG = {
"zerotier": [
{
Expand Down Expand Up @@ -57,32 +60,37 @@ class TestBackend(unittest.TestCase):
"tags": [{"default": 1, "id": 1}],
"remoteTraceTarget": "7f5d90eb87",
"remoteTraceLevel": 1,
},
{
"id": "9536600adf654322",
"nwid": "9536600adf654322",
"objtype": "network",
"revision": 1,
"creationTime": 1632012345,
"name": "zerotier-openwisp-network-2",
"private": True,
"enableBroadcast": True,
"v4AssignMode": {"zt": True},
"v6AssignMode": {"6plane": False, "rfc4193": True, "zt": True},
"mtu": 2700,
"multicastLimit": 16,
"routes": [{"target": "10.0.0.0/24", "via": "10.0.0.1"}],
"ipAssignmentPools": [
{"ipRangeStart": "10.0.0.10", "ipRangeEnd": "10.0.0.100"}
],
"dns": {"domain": "zerotier.openwisp.io", "servers": ["10.147.20.3"]},
"tags": [{"default": 1, "id": 1}],
"remoteTraceTarget": "7f5d90eb87",
"remoteTraceLevel": 1,
},
}
]
}

# Multiple test config
_TEST_MULTIPLE_CONFIG = deepcopy(_TEST_CONFIG)
_TEST_MULTIPLE_CONFIG['zerotier'].append(
{
"id": "9536600adf654322",
"nwid": "9536600adf654322",
"objtype": "network",
"revision": 1,
"creationTime": 1632012345,
"name": "zerotier-openwisp-network-2",
"private": True,
"enableBroadcast": True,
"v4AssignMode": {"zt": True},
"v6AssignMode": {"6plane": False, "rfc4193": True, "zt": True},
"mtu": 2700,
"multicastLimit": 16,
"routes": [{"target": "10.0.0.0/24", "via": "10.0.0.1"}],
"ipAssignmentPools": [
{"ipRangeStart": "10.0.0.10", "ipRangeEnd": "10.0.0.100"}
],
"dns": {"domain": "zerotier.openwisp.io", "servers": ["10.147.20.3"]},
"tags": [{"default": 1, "id": 1}],
"remoteTraceTarget": "7f5d90eb87",
"remoteTraceLevel": 1,
}
)

def test_test_schema(self):
with self.assertRaises(ValidationError) as context_manager:
ZeroTier({}).validate()
Expand All @@ -94,6 +102,84 @@ def test_confs(self):
c = ZeroTier(self._TEST_CONFIG)
expected = """// zerotier controller config: 9536600adf654321.json
{
"capabilities": [
{
"default": true,
"id": 1,
"rules": [
{
"etherType": 2048,
"not": true,
"or": false,
"type": "MATCH_ETHERTYPE"
}
]
}
],
"creationTime": 1632012345,
"dns": {
"domain": "zerotier.openwisp.io",
"servers": [
"10.147.20.3"
]
},
"enableBroadcast": true,
"id": "9536600adf654321",
"ipAssignmentPools": [
{
"ipRangeEnd": "10.0.0.100",
"ipRangeStart": "10.0.0.10"
}
],
"mtu": 2700,
"multicastLimit": 16,
"name": "zerotier-openwisp-network",
"nwid": "9536600adf654321",
"objtype": "network",
"private": true,
"remoteTraceLevel": 1,
"remoteTraceTarget": "7f5d90eb87",
"revision": 1,
"routes": [
{
"target": "10.0.0.0/24",
"via": "10.0.0.1"
}
],
"rules": [
{
"etherType": 2048,
"not": true,
"or": false,
"type": "MATCH_ETHERTYPE"
},
{
"type": "ACTION_DROP"
}
],
"tags": [
{
"default": 1,
"id": 1
}
],
"v4AssignMode": {
"zt": true
},
"v6AssignMode": {
"6plane": false,
"rfc4193": true,
"zt": true
}
}
"""
self.assertEqual(c.render(), expected)

def test_mutiple_confs(self):
c = ZeroTier(self._TEST_MULTIPLE_CONFIG)
expected = """// zerotier controller config: 9536600adf654321.json
{
"capabilities": [
{
Expand Down Expand Up @@ -218,7 +304,7 @@ def test_confs(self):
self.assertEqual(c.render(), expected)

def test_generate(self):
c = ZeroTier(self._TEST_CONFIG)
c = ZeroTier(self._TEST_MULTIPLE_CONFIG)
expected = """{
"capabilities": [
{
Expand Down

0 comments on commit 0f82d3f

Please sign in to comment.