Skip to content

Commit

Permalink
Migrate cli and dependencies to use global display
Browse files Browse the repository at this point in the history
  • Loading branch information
abadger committed Nov 11, 2015
1 parent 1b7d3f2 commit 318bfbb
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 131 deletions.
2 changes: 1 addition & 1 deletion bin/ansible
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ if __name__ == '__main__':
else:
raise

cli = mycli(sys.argv, display=display)
cli = mycli(sys.argv)
cli.parse()
sys.exit(cli.run())

Expand Down
39 changes: 17 additions & 22 deletions lib/ansible/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,14 @@
from ansible import constants as C
from ansible.errors import AnsibleError, AnsibleOptionsError
from ansible.utils.unicode import to_bytes
from ansible.utils.display import Display

try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()


class SortedOptParser(optparse.OptionParser):
'''Optparser which sorts the options by opt before outputting --help'''
Expand All @@ -44,6 +51,7 @@ def format_help(self, formatter=None, epilog=None):
self.option_list.sort(key=operator.methodcaller('get_opt_string'))
return optparse.OptionParser.format_help(self, formatter=None)


class CLI(object):
''' code behind bin/ansible* programs '''

Expand All @@ -59,7 +67,7 @@ class CLI(object):
LESS_OPTS = 'FRSX' # -F (quit-if-one-screen) -R (allow raw ansi control chars)
# -S (chop long lines) -X (disable termcap init and de-init)

def __init__(self, args, display=None):
def __init__(self, args):
"""
Base init method for all command line programs
"""
Expand All @@ -69,11 +77,6 @@ def __init__(self, args, display=None):
self.parser = None
self.action = None

if display is None:
self.display = Display()
else:
self.display = display

def set_action(self):
"""
Get the action the user wants to execute from the sys argv list.
Expand Down Expand Up @@ -102,9 +105,9 @@ def run(self):

if self.options.verbosity > 0:
if C.CONFIG_FILE:
self.display.display("Using %s as config file" % C.CONFIG_FILE)
display.display("Using %s as config file" % C.CONFIG_FILE)
else:
self.display.display("No config file found; using defaults")
display.display("No config file found; using defaults")

@staticmethod
def ask_vault_passwords(ask_new_vault_pass=False, rekey=False):
Expand Down Expand Up @@ -135,7 +138,6 @@ def ask_vault_passwords(ask_new_vault_pass=False, rekey=False):

return vault_pass, new_vault_pass


def ask_passwords(self):
''' prompt for connection and become passwords if needed '''

Expand Down Expand Up @@ -164,7 +166,6 @@ def ask_passwords(self):

return (sshpass, becomepass)


def normalize_become_options(self):
''' this keeps backwards compatibility with sudo/su self.options '''
self.options.become_ask_pass = self.options.become_ask_pass or self.options.ask_sudo_pass or self.options.ask_su_pass or C.DEFAULT_BECOME_ASK_PASS
Expand All @@ -179,7 +180,6 @@ def normalize_become_options(self):
self.options.become = True
self.options.become_method = 'su'


def validate_conflicts(self, vault_opts=False, runas_opts=False, fork_opts=False):
''' check for conflicting options '''

Expand All @@ -190,7 +190,6 @@ def validate_conflicts(self, vault_opts=False, runas_opts=False, fork_opts=False
if (op.ask_vault_pass and op.vault_password_file):
self.parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive")


if runas_opts:
# Check for privilege escalation conflicts
if (op.su or op.su_user or op.ask_su_pass) and \
Expand All @@ -215,7 +214,7 @@ def expand_tilde(option, opt, value, parser):

@staticmethod
def base_parser(usage="", output_opts=False, runas_opts=False, meta_opts=False, runtask_opts=False, vault_opts=False, module_opts=False,
async_opts=False, connect_opts=False, subset_opts=False, check_opts=False, inventory_opts=False, epilog=None, fork_opts=False):
async_opts=False, connect_opts=False, subset_opts=False, check_opts=False, inventory_opts=False, epilog=None, fork_opts=False):
''' create an options parser for most ansible scripts '''

# TODO: implement epilog parsing
Expand Down Expand Up @@ -257,7 +256,6 @@ def base_parser(usage="", output_opts=False, runas_opts=False, meta_opts=False,
parser.add_option('--output', default=None, dest='output_file',
help='output file name for encrypt or decrypt; use - for stdout')


if subset_opts:
parser.add_option('-t', '--tags', dest='tags', default='all',
help="only run plays and tasks tagged with these values")
Expand Down Expand Up @@ -295,7 +293,6 @@ def base_parser(usage="", output_opts=False, runas_opts=False, meta_opts=False,
parser.add_option('--ask-become-pass', default=False, dest='become_ask_pass', action='store_true',
help='ask for privilege escalation password')


if connect_opts:
parser.add_option('-k', '--ask-pass', default=C.DEFAULT_ASK_PASS, dest='ask_pass', action='store_true',
help='ask for connection password')
Expand Down Expand Up @@ -427,7 +424,7 @@ def _gitinfo():
result = CLI._git_repo_info(repo_path)
submodules = os.path.join(basedir, '.gitmodules')
if not os.path.exists(submodules):
return result
return result
f = open(submodules)
for line in f:
tokens = line.strip().split(' ')
Expand All @@ -440,21 +437,20 @@ def _gitinfo():
f.close()
return result


def pager(self, text):
''' find reasonable way to display text '''
# this is a much simpler form of what is in pydoc.py
if not sys.stdout.isatty():
self.display.display(text)
display.display(text)
elif 'PAGER' in os.environ:
if sys.platform == 'win32':
self.display.display(text)
display.display(text)
else:
self.pager_pipe(text, os.environ['PAGER'])
elif subprocess.call('(less --version) 2> /dev/null', shell = True) == 0:
self.pager_pipe(text, 'less')
else:
self.display.display(text)
display.display(text)

@staticmethod
def pager_pipe(text, cmd):
Expand Down Expand Up @@ -521,4 +517,3 @@ def get_opt(self, k, defval=""):
if os.pathsep in data:
data = data.split(os.pathsep)[0]
return data

18 changes: 12 additions & 6 deletions lib/ansible/cli/adhoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@
from ansible.utils.vars import load_extra_vars
from ansible.vars import VariableManager

try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()


########################################################

class AdHocCLI(CLI):
Expand Down Expand Up @@ -68,7 +76,7 @@ def parse(self):
if len(self.args) != 1:
raise AnsibleOptionsError("Missing target hosts")

self.display.verbosity = self.options.verbosity
display.verbosity = self.options.verbosity
self.validate_conflicts(runas_opts=True, vault_opts=True, fork_opts=True)

return True
Expand All @@ -86,7 +94,6 @@ def run(self):

super(AdHocCLI, self).run()


# only thing left should be host pattern
pattern = self.args[0]

Expand Down Expand Up @@ -121,7 +128,7 @@ def run(self):
hosts = inventory.list_hosts(pattern)
no_hosts = False
if len(hosts) == 0:
self.display.warning("provided hosts list is empty, only localhost is available")
display.warning("provided hosts list is empty, only localhost is available")
no_hosts = True

if self.options.subset:
Expand All @@ -131,9 +138,9 @@ def run(self):
raise AnsibleError("Specified --limit does not match any hosts")

if self.options.listhosts:
self.display.display(' hosts (%d):' % len(hosts))
display.display(' hosts (%d):' % len(hosts))
for host in hosts:
self.display.display(' %s' % host)
display.display(' %s' % host)
return 0

if self.options.module_name in C.MODULE_REQUIRE_ARGS and not self.options.module_args:
Expand Down Expand Up @@ -168,7 +175,6 @@ def run(self):
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
display=self.display,
options=self.options,
passwords=passwords,
stdout_callback=cb,
Expand Down
33 changes: 19 additions & 14 deletions lib/ansible/cli/doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,23 @@
from ansible.cli import CLI
from ansible.utils import module_docs

try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()


class DocCLI(CLI):
""" Vault command line class """

BLACKLIST_EXTS = ('.pyc', '.swp', '.bak', '~', '.rpm', '.md', '.txt')
IGNORE_FILES = [ "COPYING", "CONTRIBUTING", "LICENSE", "README", "VERSION", "GUIDELINES", "test-docs.sh"]

def __init__(self, args, display=None):
def __init__(self, args):

super(DocCLI, self).__init__(args, display)
super(DocCLI, self).__init__(args)
self.module_list = []

def parse(self):
Expand All @@ -56,8 +64,7 @@ def parse(self):
help='Show playbook snippet for specified module(s)')

self.options, self.args = self.parser.parse_args()
self.display.verbosity = self.options.verbosity

display.verbosity = self.options.verbosity

def run(self):

Expand Down Expand Up @@ -86,7 +93,7 @@ def run(self):
try:
filename = module_loader.find_plugin(module)
if filename is None:
self.display.warning("module %s not found in %s\n" % (module, DocCLI.print_paths(module_loader)))
display.warning("module %s not found in %s\n" % (module, DocCLI.print_paths(module_loader)))
continue

if any(filename.endswith(x) for x in self.BLACKLIST_EXTS):
Expand All @@ -95,8 +102,8 @@ def run(self):
try:
doc, plainexamples, returndocs = module_docs.get_docstring(filename, verbose=(self.options.verbosity > 0))
except:
self.display.vvv(traceback.print_exc())
self.display.error("module %s has a documentation error formatting or is missing documentation\nTo see exact traceback use -vvv" % module)
display.vvv(traceback.print_exc())
display.error("module %s has a documentation error formatting or is missing documentation\nTo see exact traceback use -vvv" % module)
continue

if doc is not None:
Expand All @@ -122,7 +129,7 @@ def run(self):
# probably a quoting issue.
raise AnsibleError("Parsing produced an empty object.")
except Exception as e:
self.display.vvv(traceback.print_exc())
display.vvv(traceback.print_exc())
raise AnsibleError("module %s missing documentation (or could not parse documentation): %s\n" % (module, str(e)))

self.pager(text)
Expand Down Expand Up @@ -150,9 +157,8 @@ def find_modules(self, path):
module = os.path.splitext(module)[0] # removes the extension
self.module_list.append(module)


def get_module_list_text(self):
columns = self.display.columns
columns = display.columns
displace = max(len(x) for x in self.module_list)
linelimit = columns - displace - 5
text = []
Expand Down Expand Up @@ -189,7 +195,6 @@ def get_module_list_text(self):
text.extend(deprecated)
return "\n".join(text)


@staticmethod
def print_paths(finder):
''' Returns a string suitable for printing of the search path '''
Expand All @@ -209,7 +214,7 @@ def get_snippet_text(self, doc):
text.append(" action: %s" % (doc['module']))
pad = 31
subdent = ''.join([" " for a in xrange(pad)])
limit = self.display.columns - pad
limit = display.columns - pad

for o in sorted(doc['options'].keys()):
opt = doc['options'][o]
Expand All @@ -229,8 +234,8 @@ def get_man_text(self, doc):
opt_indent=" "
text = []
text.append("> %s\n" % doc['module'].upper())
pad = self.display.columns * 0.20
limit = max(self.display.columns - int(pad), 70)
pad = display.columns * 0.20
limit = max(display.columns - int(pad), 70)

if isinstance(doc['description'], list):
desc = " ".join(doc['description'])
Expand Down
Loading

0 comments on commit 318bfbb

Please sign in to comment.