diff --git a/jerakia/cli.py b/jerakia/cli.py new file mode 100644 index 0000000..30b8b64 --- /dev/null +++ b/jerakia/cli.py @@ -0,0 +1,100 @@ +import sys +import os +import collections +import errno +import subprocess +import six +import click +from os import walk +from .client import Client,ClientError +from pkg_resources import iter_entry_points +from click_plugins import with_plugins +from distutils import dir_util # https://github.com/PyCQA/pylint/issues/73; pylint: disable=no-name-in-module + +sys.path.insert(0, os.getcwd()) + +class InvalidDataFormat(Exception): + """Invalid data exception""" + pass + +class InvalidInputData(Exception): + """Invalid input data exception""" + pass + +class MalformedYAML(InvalidInputData): + """Invalid YAML data exception""" + pass + +def get_format(fmt): + """Returns a data loading function""" + try: + return FORMATS[fmt]() + except ImportError: + raise InvalidDataFormat(fmt) + +def _load_yaml(): + import yaml + return yaml.load, yaml.YAMLError, MalformedYAML + +def merge_dicts(*dicts): + result = {} + for dictionary in dicts: + result.update(dictionary) + return result + +FORMATS = { + 'yaml': _load_yaml, + 'yml': _load_yaml, +} + +@click.group() +def main(): + """jerakia is a tool to perform hierarchical data lookups.""" +@main.command('lookup') +@click.argument('namespace') +@click.argument('key') +@click.option('-T','--token', envvar='JERAKIA_TOKEN') +@click.option('-P','--port', default='9843', envvar='JERAKIA_PORT') +@click.option('-H','--host', default='localhost', envvar='JERAKIA_HOST') +@click.option('--protocol', default='http', envvar='JERAKIA_PROTOCOL') +@click.option('-t','--type') +@click.option('-p','--policy') +@click.option('-m','--metadata',required=False, multiple=True) +@click.option('-i', '--configfile', type=click.Path(), default='$HOME/.jerakia/jerakia.yaml') +def lookup(namespace,key,token,port,type,host,protocol,policy,metadata,configfile): + # Parse metadata options + met = dict() + for item in metadata: + met.update([item.split('=')]) + # Load configfile if exists + if os.path.exists(configfile): + with open(configfile, "r") as filename: + config = yaml.load(filename) + # Merge dicts from cli args/env vars with config file + else: + config = dict() + options_config = dict(token=token,port=port,host=host,version=1,protocol=protocol) + combined_config = merge_dicts(config,options_config) + + # Perform lookup + if (combined_config['token'] is not None): + jerakiaobj = Client(**combined_config) + ns = [] + ret = [] + ns.append(str(namespace)) + response = jerakiaobj.lookup(key=str(key), namespace=ns, metadata_dict=met, content_type='json') + ret.append(response['payload']) + + if len(ret) == 1: + try: + print ("Result outputs", response['payload'].encode('ascii', 'ignore')) + except Exception as detail: + print 'The Jerakia lookup resulted in an empty response:', detail + else: + try: + [x.encode('ascii', 'ignore') for x in ret] + print ("Result outputs ", ret) + except Exception as detail: + print 'The Jerakia lookup resulted in an empty response:', detail + else: + print "Token not found in env var JERAKIA_TOKEN, aborting" \ No newline at end of file diff --git a/jerakia/render.py b/jerakia/render.py index 2489356..8788271 100644 --- a/jerakia/render.py +++ b/jerakia/render.py @@ -9,12 +9,15 @@ from jinja2.ext import Extension jerakia = None +metadata = None -def render(template_path, jerakia_instance, data, extensions=None, strict=False): +def render(template_path, jerakia_instance, metadata_dict, data, extensions=None, strict=False): """Renders a jinja2 template using data looked up via Jerakia""" global jerakia jerakia = jerakia_instance + global metadata + metadata = metadata_dict if extensions is None: extensions = [] @@ -37,12 +40,13 @@ def retrieveJerakia(item): """Retrieves the result from the Jerakia lookup""" global jerakia + global metadata lookuppath =item.split('/') key = lookuppath.pop() namespace = lookuppath ret = [] - response = jerakia.lookup(key=key, namespace=namespace, content_type='json') + response = jerakia.lookup(key=key, namespace=namespace, metadata_dict=metadata, content_type='json') ret.append(response['payload']) if len(ret) == 1: diff --git a/setup.py b/setup.py index 3013057..bf81207 100644 --- a/setup.py +++ b/setup.py @@ -2,13 +2,15 @@ setup( name='python-jerakia', - version='0.5.0', + version='0.8.4', packages=find_packages(), include_package_data=True, description='Python client library for Jerakia (https://jerakia.io)', author='Jon Ander Novella', install_requires=[ 'requests>=2.0', + 'click>=6.7', + 'click-plugins', 'msgpack', 'mock', 'jinja2', @@ -16,5 +18,14 @@ 'six', 'cryptography>=2.2.1', 'pyOpenSSL' - ] + ], + entry_points=''' + [console_scripts] + jerakia=jerakia.cli:main + [root.plugins] + plugin=jerakia.cli:main + ''', + extras_require = { + 'kcli': ["kcli"] + } ) diff --git a/tests/test_jerakia.py b/tests/test_jerakia.py index 27088be..056d0f2 100644 --- a/tests/test_jerakia.py +++ b/tests/test_jerakia.py @@ -123,7 +123,7 @@ def test_render_json(self,mock_lookup): fields = {'it': 'common/test'} if 'it' in fields: - test_out = render.render(template_path=config_file_path, jerakia_instance=instance, data=fields) + test_out = render.render(template_path=config_file_path, jerakia_instance=instance, metadata_dict=dict(env='dev'), data=fields) self.assertIsNotNone(test_out) expected_test_out = '{' + "fieldA: 'sesame'" + ', ' + "fieldB: test" + '}'+ '\n' self.assertEqual(test_out, expected_test_out)