Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test pr #1

Open
wants to merge 34 commits into
base: dev/qe
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f01c7df
Merge pull request #22 from yfried-redhat/dev/qe
Feb 10, 2016
bfb63a8
Moves the excepthood closure to the module level
aopincar Feb 10, 2016
ae51f97
Moves logger import to the haed of local imports
aopincar Feb 10, 2016
5f54f4b
Changes the exception import way in main.py
aopincar Feb 10, 2016
370c59b
Fixes CR comments
aopincar Feb 10, 2016
127cbaf
Merge pull request #23 from aopincar/kcli
Feb 10, 2016
3864723
Splits code to seperate modules & add documention
aopincar Feb 10, 2016
e7c5516
Adds unittest for dict_insert method
aopincar Feb 11, 2016
fee3c14
Fixes CR comments (commit # 38647237)
aopincar Feb 14, 2016
9c7e651
Adds missing new line in enumerated lists lines
aopincar Feb 15, 2016
8466816
Moves 'execute' package to a module in kcli dir
aopincar Feb 16, 2016
51cd9b2
Moves 'dict_lookup' method int 'Lookup' class
aopincar Feb 16, 2016
8e92465
Adds a handler for yaml ConstructorError
aopincar Feb 16, 2016
bfea12b
Merge pull request #24 from aopincar/kcli
Feb 17, 2016
dae2bd9
Merge pull request #25 from aopincar/unittest
Feb 17, 2016
428ee7a
Merge pull request #27 from aopincar/execute
Feb 17, 2016
935de3c
Merge pull request #28 from aopincar/move_dict_lookup_into_Lookup
Feb 17, 2016
42e4092
Merge pull request #30 from aopincar/general_unhandled_yaml_construct…
Feb 17, 2016
d7e7f0c
Organizes all lookup method in Lookup class
aopincar Feb 17, 2016
980ccdb
Adds unitest for unsupported YAML constructor
aopincar Feb 17, 2016
fbdbcb6
Merge pull request #34 from aopincar/organize_all_lookup_funcs
Feb 18, 2016
36896a6
Fixes comments from pull request #38 - pep8 fix
aopincar Feb 18, 2016
a4add1d
Merge pull request #38 from aopincar/unittest
Feb 18, 2016
cad99ce
Removes the un-needed parser in execute.py
aopincar Feb 18, 2016
e0d8990
Adds constructor & unittest for !placeholder tag
aopincar Feb 18, 2016
d5dfd43
Merge pull request #39 from aopincar/remove_parser_from_execute
Feb 18, 2016
6c8a0fa
Fixes comments from pull #40
aopincar Feb 18, 2016
bdabd7b
Fixes typo in placholder's yamles & add data check
aopincar Feb 18, 2016
5327725
Merge pull request #40 from aopincar/placeholder
Feb 21, 2016
e655268
WIP - dereference khaleesi & kcli
aopincar Feb 21, 2016
60b87cc
More deref
Feb 21, 2016
9fed394
Merge pull request #42 from yfried-redhat/aopincar-dereference_khalee…
Feb 21, 2016
590c2c4
A testing file only
Apr 13, 2016
6703209
Delete TestingOnly
Apr 13, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ stackrc
id_rsa*
hosts
*-hosts
ksgen_settings.yml
instack_hosts
doc/_build/
fence_xvm.key
vm-host-table
tools/kcli/etc/kcli.cfg
tools/cli/etc/infrared.cfg
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ python:
install:
- pip install pep8 --use-mirrors
- pip install https://github.com/dcramer/pyflakes/tarball/master
- pip install tools/kcli
- pip install tools/cli
# command to run tests
script:
- pep8 tools/kcli
- py.test tools/kcli
- pep8 tools/cli
- py.test tools/cli -v
1 change: 0 additions & 1 deletion tools/__init__.py

This file was deleted.

71 changes: 71 additions & 0 deletions tools/cli/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
=================
InfraRed CLI tool
=================

Intended to reduce InfraRed users' dependency on external CLI tools.

Setup
=====

.. note:: On Fedora 23 `BZ#1103566 <https://bugzilla.redhat.com/show_bug.cgi?id=1103566>`_
calls for::

$ dnf install redhat-rpm-config

Use pip to install from source::

$ pip install tools/cli

.. note:: For development work it's better to install in editable mode::

$ pip install -e tools/cli

Conf
====

.. note:: Assumes that ``infrared`` is installed, else follow Setup_.

``infrared`` will look for ``infrared.cfg`` in the following order:

#. In working directory: ``./infrared.cfg``
#. In user home directory: ``~/.infrared.cfg``
#. In system settings: ``/etc/infrared /infrared.cfg``

.. note:: To specify a different directory or different filename, override the
lookup order with ``IR_CONFIG`` environment variable::

$ IR_CONFIG=/my/config/file.ini infrared --help

Running InfraRed
================

.. note:: Assumes that ``infrared`` is installed, else follow Setup_.

You can get general usage information with the ``--help`` option::

infrared --help

This displays options you can pass to ``infrared``.

Extra-Vars
----------
One can set/overwrite settings in the output file using the '-e/--extra-vars'
option. There are 2 ways of doing so:

1. specific settings: (``key=value`` form)
``--extra-vars provisioner.site.user=a_user``
2. path to a settings file: (starts with ``@``)
``--extra-vars @path/to/a/settings_file.yml``

The ``-e``/``--extra-vars`` can be used more than once.

Merging order
-------------
Except options based on the settings dir structure, ``infrared`` accepts input of
predefined settings files (with ``-n``/``--input``) and user defined specific options
(``-e``/``--extra-vars``).
The merging priority order listed below:

1. Input files
2. Settings dir based options
3. Extra Vars
File renamed without changes.
20 changes: 11 additions & 9 deletions tools/kcli/kcli/conf.py → tools/cli/cli/conf.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import ConfigParser
import os
import time

from kcli import exceptions
from cli import exceptions

from kcli.exceptions import IRFileNotFoundException

ENV_VAR_NAME = "KCLI_CONFIG"
KCLI_CONF_FILE = 'kcli.cfg'
CWD_PATH = os.path.join(os.getcwd(), KCLI_CONF_FILE)
USER_PATH = os.path.expanduser('~/.' + KCLI_CONF_FILE)
SYSTEM_PATH = os.path.join('/etc/khaleesi', KCLI_CONF_FILE)
ENV_VAR_NAME = "IR_CONFIG"
IR_CONF_FILE = 'infrared.cfg'
CWD_PATH = os.path.join(os.getcwd(), IR_CONF_FILE)
USER_PATH = os.path.expanduser('~/.' + IR_CONF_FILE)
SYSTEM_PATH = os.path.join('/etc/infrared', IR_CONF_FILE)
YAML_EXT = ".yml"
TMP_OUTPUT_FILE = 'ir_settings_' + str(time.time()) + YAML_EXT
INFRARED_DIR_ENV_VAR = 'IR_SETTINGS'


def load_config_file():
Expand All @@ -22,7 +24,7 @@ def load_config_file():
if env_path is not None:
env_path = os.path.expanduser(env_path)
if os.path.isdir(env_path):
env_path = os.path.join(env_path, KCLI_CONF_FILE)
env_path = os.path.join(env_path, IR_CONF_FILE)
for path in (env_path, CWD_PATH, USER_PATH, SYSTEM_PATH):
if path is not None and os.path.exists(path):
_config.read(path)
Expand Down
15 changes: 15 additions & 0 deletions tools/kcli/kcli/exceptions.py → tools/cli/cli/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,18 @@ class IRPlaybookFailedException(IRException):
def __init__(self, playbook):
super(self.__class__, self).__init__(
'Playbook "%s" failed!' % playbook)


class IRYAMLConstructorError(IRException):
def __init__(self, mark_obj, where):
self.message = mark_obj.problem
pm = mark_obj.problem_mark
self.message += ' in:\n "{where}", line {line_no}, column ' \
'{column_no}'.format(where=where,
line_no=pm.line + 1,
column_no=pm.column + 1)


class IRPlaceholderException(IRException):
def __init__(self, trace_message):
self.message = 'Mandatory value is missing.\n' + trace_message
13 changes: 9 additions & 4 deletions tools/kcli/kcli/execute/execute.py → tools/cli/cli/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@
import ansible.utils
from ansible import callbacks

from kcli import conf, exceptions
from kcli.execute import core
from cli import conf, exceptions, logger

LOG = logger.LOG

VERBOSITY = 0
HOSTS_FILE = "hosts"
LOCAL_HOSTS = "local_hosts"
PROVISION = "provision"
PLAYBOOKS = [PROVISION, "install", "test", "collect-logs", "cleanup"]

assert "playbooks" == path.basename(conf.PLAYBOOKS_DIR), \
"Bad path to playbooks"


# ansible-playbook
# https://github.com/ansible/ansible/blob/devel/bin/ansible-playbook
Expand Down Expand Up @@ -135,11 +140,11 @@ def execute_ansible(playbook, args):


def ansible_wrapper(args):
"""Wraps the 'anisble-playbook' CLI."""
""" Wraps the 'ansible-playbook' CLI. """

playbooks = [p for p in PLAYBOOKS if getattr(args, p, False)]
if not playbooks:
core.parser.error("No playbook to execute (%s)" % PLAYBOOKS)
LOG.error("No playbook to execute (%s)" % PLAYBOOKS)

for playbook in (p for p in PLAYBOOKS if getattr(args, p, False)):
print "Executing Playbook: %s" % playbook
Expand Down
55 changes: 55 additions & 0 deletions tools/cli/cli/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import logging
import sys
import traceback

import colorlog

from cli import exceptions

logger_formatter = colorlog.ColoredFormatter(
"%(log_color)s%(levelname)-8s%(message)s",
log_colors=dict(
DEBUG='blue',
INFO='green',
WARNING='yellow',
ERROR='red',
CRITICAL='bold_red,bg_white',
)
)

LOGGER_NAME = "IRLogger"
DEFAULT_LOG_LEVEL = logging.WARNING

LOG = logging.getLogger(LOGGER_NAME)
LOG.setLevel(DEFAULT_LOG_LEVEL)

# Create stream handler with debug level
sh = logging.StreamHandler()
sh.setLevel(logging.DEBUG)

# Add the logger_formatter to sh
sh.setFormatter(logger_formatter)

# Create logger and add handler to it
LOG.addHandler(sh)


def ir_excepthook(exc_type, exc_value, exc_traceback):
"""
exception hook that sends IRException to log and other exceptions to
stderr (default excepthook)
"""

# sends full exception with trace to log
if not isinstance(exc_value, exceptions.IRException):
return sys.__excepthook__(exc_type, exc_value, exc_traceback)

if LOG.getEffectiveLevel() <= logging.DEBUG:
formated_exception = "".join(
traceback.format_exception(exc_type, exc_value, exc_traceback))
LOG.error(formated_exception + exc_value.message)
else:
LOG.error(exc_value.message)


sys.excepthook = ir_excepthook
119 changes: 119 additions & 0 deletions tools/cli/cli/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#!/usr/bin/env python

import logging
import os

import yaml

# logger creation is first thing to be done
from cli import logger

from cli import conf
from cli import options as cli_options
from cli import execute
from cli import parse
from cli import utils
import cli.yamls

LOG = logger.LOG
CONF = conf.config


def main():
options_trees = []
settings_files = []
settings_dir = utils.validate_settings_dir(
CONF.get('DEFAULTS', 'SETTINGS_DIR'))

for option in CONF.options('ROOT_OPTS'):
options_trees.append(cli_options.OptionsTree(settings_dir, option))

parser = parse.create_parser(options_trees)
args = parser.parse_args()

verbose = int(args.verbose)

if args.verbose == 0:
args.verbose = logging.WARNING
elif args.verbose == 1:
args.verbose = logging.INFO
else:
args.verbose = logging.DEBUG

LOG.setLevel(args.verbose)

# settings generation stage
if args.which.lower() != 'execute':
for input_file in args.input:
settings_files.append(utils.normalize_file(input_file))

for options_tree in options_trees:
options = {key: value for key, value in vars(args).iteritems()
if value and key.startswith(options_tree.name)}

settings_files += (options_tree.get_options_ymls(options))

LOG.debug("All settings files to be loaded:\n%s" % settings_files)

cli.yamls.Lookup.settings = utils.generate_settings(settings_files,
args.extra_vars)

LOG.debug("Dumping settings...")
output = yaml.safe_dump(cli.yamls.Lookup.settings,
default_flow_style=False)

if args.output_file:
with open(args.output_file, 'w') as output_file:
output_file.write(output)
else:
print output

exec_playbook = (args.which == 'execute') or \
(not args.dry_run and args.which in CONF.options(
'AUTO_EXEC_OPTS'))

# playbook execution stage
if exec_playbook:
if args.which == 'execute':
execute_args = parser.parse_args()
elif args.which not in execute.PLAYBOOKS:
LOG.debug("No playbook named \"%s\", nothing to execute.\n"
"Please choose from: %s" % (args.which,
execute.PLAYBOOKS))
return
else:
args_list = ["execute"]
if verbose:
args_list.append('-%s' % ('v' * verbose))
if 'inventory' in args:
inventory = args.inventory
else:
inventory = 'local_hosts' if args.which == 'provision' \
else 'hosts'
args_list.append('--inventory=%s' % inventory)
args_list.append('--' + args.which)
args_list.append('--collect-logs')
if args.output_file:
LOG.debug('Using the newly created settings file: "%s"'
% args.output_file)
args_list.append('--settings=%s' % args.output_file)
else:
with open(conf.TMP_OUTPUT_FILE, 'w') as output_file:
output_file.write(output)
LOG.debug('Temporary settings file "%s" has been created for '
'execution purpose only.' % conf.TMP_OUTPUT_FILE)
args_list.append('--settings=%s' % conf.TMP_OUTPUT_FILE)

execute_args = parser.parse_args(args_list)

LOG.debug("execute parser args: %s" % args)
execute_args.func(execute_args)

if not args.output_file and args.which != 'execute':
LOG.debug('Temporary settings file "%s" has been deleted.'
% conf.TMP_OUTPUT_FILE)
os.remove(conf.TMP_OUTPUT_FILE)


if __name__ == '__main__':
main()
Loading