Skip to content

Commit

Permalink
Added command line utility #15
Browse files Browse the repository at this point in the history
Closes #15
  • Loading branch information
nemesifier committed Oct 2, 2015
1 parent c504dfa commit d4b90f2
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 2 deletions.
16 changes: 16 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,22 @@ Will print::
option proto 'static'
option ip6addr 'fd87::1/128'

Command line utility
--------------------

netjsonconfig ships a command line utility that can be
used from the interactive shell or in bash scripts::

netjsonconfig --help

A few common use scenarios:

# generate tar.gz from a NetJSON DeviceConfiguration object
netjsonconfig config.json

# see output of render OpenWrt render method
netjsonconfig --backend openwrt --method render config.json

Running tests
-------------

Expand Down
89 changes: 89 additions & 0 deletions bin/netjsonconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/usr/bin/env python

import sys
import argparse

import netjsonconfig

license = """
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

parser = argparse.ArgumentParser(description='Converts a NetJSON DeviceConfiguration object'
'to working router configurations.',
epilog=license,
prog='netjsonconfig')

parser.add_argument('config',
action='store',
type=str,
help='config file or string, must be valid NetJSON DeviceConfiguration')

parser.add_argument('--backend', '-b',
choices=['openwrt'],
action='store',
default='openwrt',
type=str,
help='Configuration backend: openwrt')

parser.add_argument('--method', '-m',
choices=['generate', 'render'],
action='store',
default='generate',
help='Backend method to use. ("generate" creates a tar.gz, "render"'
'returns the entire config as a string)')

parser.add_argument('--verbose',
action='store_true',
default=False,
help='verbose output')

parser.add_argument('--version', '-v',
action='version',
version=netjsonconfig.get_version())

args = parser.parse_args()

# if config argument does not look like JSON try opening a file
if not args.config.strip().startswith('{'):
try:
config = open(args.config, 'r').read()
except FileNotFoundError:
print('\n\tError: file "{0}" not found\n'.format(args.config))
sys.exit(1)
else:
config = args.config.strip()

backends = {
'openwrt': netjsonconfig.OpenWrt
}

backend_class = backends[args.backend]
try:
instance = backend_class(config)
except TypeError:
print('\n\tError: config argument contains invalid JSON\n')
sys.exit(2)

try:
output = getattr(instance, args.method)()
if output:
print('{0}\n'.format(output))
except netjsonconfig.exceptions.ValidationError as e:
if not args.verbose:
print('\n\tError: JSON Schema violation.\n'
'\tFor more information repeat the command using --verbose\n')
else:
print(e)
sys.exit(3)
6 changes: 5 additions & 1 deletion netjsonconfig/backends/openwrt/openwrt.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ def __init__(self, config):
self.env = Environment(loader=PackageLoader('netjsonconfig.backends.openwrt',
'templates'),
trim_blocks=True)
self.__find_bridges()
try:
self.__find_bridges()
except (AttributeError, KeyError):
# validation will take care of errors later
pass

def render(self):
self.validate()
Expand Down
3 changes: 2 additions & 1 deletion setup.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,6 @@ def get_install_requires():
'Topic :: System :: Networking',
],
install_requires=get_install_requires(),
test_suite='nose.collector'
test_suite='nose.collector',
scripts=['bin/netjsonconfig'],
)
5 changes: 5 additions & 0 deletions tests/openwrt/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ def test_validate(self):
with self.assertRaises(ValidationError):
o.validate()

def test_find_bridge_skip_error(self):
o = OpenWrt({'interfaces': ['WRONG']})
with self.assertRaises(ValidationError):
o.validate()

def test_type_error(self):
with self.assertRaises(TypeError):
o = OpenWrt([])
Expand Down
25 changes: 25 additions & 0 deletions tests/test_bin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import unittest
import subprocess

from .openwrt.utils import _TabsMixin


class TestBin(unittest.TestCase, _TabsMixin):
"""
tests for netjsonconfig command line tool
"""
def test_file_not_found(self):
with self.assertRaises(subprocess.CalledProcessError):
output = subprocess.check_output("netjsonconfig WRONG", shell=True)

def test_invalid_netjson(self):
with self.assertRaises(subprocess.CalledProcessError):
output = subprocess.check_output('''netjsonconfig '{ "interfaces":["w"] }' -m render''', shell=True)

def test_invalid_netjson_verbose(self):
with self.assertRaises(subprocess.CalledProcessError):
output = subprocess.check_output('''netjsonconfig '{ "interfaces":["w"] }' -m render --verbose''', shell=True)

def test_invalid_netjson(self):
output = subprocess.check_output('''netjsonconfig '{}' -m render''', shell=True)
self.assertEqual(output.decode(), '')

0 comments on commit d4b90f2

Please sign in to comment.