Migrate cli and dependencies to use global display

pull/12547/merge
Toshio Kuratomi 9 years ago
parent 1b7d3f2898
commit 318bfbb207

@ -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())

@ -33,7 +33,14 @@ from ansible import __version__
from ansible import constants as C
from ansible.errors import AnsibleError, AnsibleOptionsError
from ansible.utils.unicode import to_bytes
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'''
@ -44,6 +51,7 @@ class SortedOptParser(optparse.OptionParser):
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 '''
@ -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
"""
@ -69,11 +77,6 @@ class CLI(object):
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.
@ -102,9 +105,9 @@ class CLI(object):
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):
@ -135,7 +138,6 @@ class CLI(object):
return vault_pass, new_vault_pass
def ask_passwords(self):
''' prompt for connection and become passwords if needed '''
@ -164,7 +166,6 @@ class CLI(object):
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
@ -179,7 +180,6 @@ class CLI(object):
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 '''
@ -190,7 +190,6 @@ class CLI(object):
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 \
@ -257,7 +256,6 @@ class CLI(object):
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")
@ -295,7 +293,6 @@ class CLI(object):
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')
@ -440,21 +437,20 @@ class CLI(object):
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):
@ -521,4 +517,3 @@ class CLI(object):
if os.pathsep in data:
data = data.split(os.pathsep)[0]
return data

@ -34,6 +34,14 @@ from ansible.plugins import get_all_plugin_loaders
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):
@ -68,7 +76,7 @@ class AdHocCLI(CLI):
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
@ -86,7 +94,6 @@ class AdHocCLI(CLI):
super(AdHocCLI, self).run()
# only thing left should be host pattern
pattern = self.args[0]
@ -121,7 +128,7 @@ class AdHocCLI(CLI):
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:
@ -131,9 +138,9 @@ class AdHocCLI(CLI):
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:
@ -168,7 +175,6 @@ class AdHocCLI(CLI):
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
display=self.display,
options=self.options,
passwords=passwords,
stdout_callback=cb,

@ -31,15 +31,23 @@ from ansible.plugins import module_loader
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):
@ -56,8 +64,7 @@ class DocCLI(CLI):
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):
@ -86,7 +93,7 @@ class DocCLI(CLI):
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):
@ -95,8 +102,8 @@ class DocCLI(CLI):
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:
@ -122,7 +129,7 @@ class DocCLI(CLI):
# 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)
@ -150,9 +157,8 @@ class DocCLI(CLI):
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 = []
@ -189,7 +195,6 @@ class DocCLI(CLI):
text.extend(deprecated)
return "\n".join(text)
@staticmethod
def print_paths(finder):
''' Returns a string suitable for printing of the search path '''
@ -209,7 +214,7 @@ class DocCLI(CLI):
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]
@ -229,8 +234,8 @@ class DocCLI(CLI):
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'])

@ -28,7 +28,6 @@ import sys
import yaml
from collections import defaultdict
from distutils.version import LooseVersion
from jinja2 import Environment
import ansible.constants as C
@ -39,16 +38,24 @@ from ansible.galaxy.api import GalaxyAPI
from ansible.galaxy.role import GalaxyRole
from ansible.playbook.role.requirement import RoleRequirement
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
class GalaxyCLI(CLI):
VALID_ACTIONS = ("init", "info", "install", "list", "remove", "search")
SKIP_INFO_KEYS = ("name", "description", "readme_html", "related", "summary_fields", "average_aw_composite", "average_aw_score", "url" )
def __init__(self, args, display=None):
def __init__(self, args):
self.api = None
self.galaxy = None
super(GalaxyCLI, self).__init__(args, display)
super(GalaxyCLI, self).__init__(args)
def parse(self):
''' create an options parser for bin/ansible '''
@ -58,7 +65,6 @@ class GalaxyCLI(CLI):
epilog = "\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0])
)
self.set_action()
# options specific to actions
@ -109,8 +115,8 @@ class GalaxyCLI(CLI):
# get options, args and galaxy object
self.options, self.args =self.parser.parse_args()
self.display.verbosity = self.options.verbosity
self.galaxy = Galaxy(self.options, self.display)
display.verbosity = self.options.verbosity
self.galaxy = Galaxy(self.options)
return True
@ -178,10 +184,10 @@ class GalaxyCLI(CLI):
if os.path.isfile(role_path):
raise AnsibleError("- the path %s already exists, but is a file - aborting" % role_path)
elif not force:
raise AnsibleError("- the directory %s already exists." % role_path + \
"you can use --force to re-initialize this directory,\n" + \
"however it will reset any main.yml files that may have\n" + \
"been modified there already.")
raise AnsibleError("- the directory %s already exists."
"you can use --force to re-initialize this directory,\n"
"however it will reset any main.yml files that may have\n"
"been modified there already." % role_path)
# create the default README.md
if not os.path.exists(role_path):
@ -234,7 +240,7 @@ class GalaxyCLI(CLI):
f = open(main_yml_path, 'w')
f.write('---\n# %s file for %s\n' % (dir,role_name))
f.close()
self.display.display("- %s was created successfully" % role_name)
display.display("- %s was created successfully" % role_name)
def execute_info(self):
"""
@ -297,7 +303,7 @@ class GalaxyCLI(CLI):
# the user needs to specify one of either --role-file
# or specify a single user/role name
raise AnsibleOptionsError("- you must specify a user/role name or a roles file")
elif len(self.args) == 1 and not role_file is None:
elif len(self.args) == 1 and role_file is not None:
# using a role file is mutually exclusive of specifying
# the role name on the command line
raise AnsibleOptionsError("- please specify a user/role name, or a roles file, but not both")
@ -320,22 +326,22 @@ class GalaxyCLI(CLI):
for role in required_roles:
role = RoleRequirement.role_yaml_parse(role)
self.display.debug('found role %s in yaml file' % str(role))
display.debug('found role %s in yaml file' % str(role))
if 'name' not in role and 'scm' not in role:
raise AnsibleError("Must specify name or src for role")
roles_left.append(GalaxyRole(self.galaxy, **role))
else:
self.display.deprecated("going forward only the yaml format will be supported")
display.deprecated("going forward only the yaml format will be supported")
# roles listed in a file, one per line
for rline in f.readlines():
if rline.startswith("#") or rline.strip() == '':
continue
self.display.debug('found role %s in text file' % str(rline))
display.debug('found role %s in text file' % str(rline))
role = RoleRequirement.role_yaml_parse(rline.strip())
roles_left.append(GalaxyRole(self.galaxy, **role))
f.close()
except (IOError, OSError) as e:
self.display.error('Unable to open %s: %s' % (role_file, str(e)))
display.error('Unable to open %s: %s' % (role_file, str(e)))
else:
# roles were specified directly, so we'll just go out grab them
# (and their dependencies, unless the user doesn't want us to).
@ -343,18 +349,17 @@ class GalaxyCLI(CLI):
roles_left.append(GalaxyRole(self.galaxy, rname.strip()))
for role in roles_left:
self.display.debug('Installing role %s ' % role.name)
display.debug('Installing role %s ' % role.name)
# query the galaxy API for the role data
role_data = None
if role.install_info is not None and not force:
self.display.display('- %s is already installed, skipping.' % role.name)
display.display('- %s is already installed, skipping.' % role.name)
continue
try:
installed = role.install()
except AnsibleError as e:
self.display.warning("- %s was NOT installed successfully: %s " % (role.name, str(e)))
display.warning("- %s was NOT installed successfully: %s " % (role.name, str(e)))
self.exit_without_ignore()
continue
@ -362,7 +367,7 @@ class GalaxyCLI(CLI):
if not no_deps and installed:
role_dependencies = role.metadata.get('dependencies') or []
for dep in role_dependencies:
self.display.debug('Installing dep %s' % dep)
display.debug('Installing dep %s' % dep)
dep_req = RoleRequirement()
dep_info = dep_req.role_yaml_parse(dep)
dep_role = GalaxyRole(self.galaxy, **dep_info)
@ -372,15 +377,15 @@ class GalaxyCLI(CLI):
continue
if dep_role.install_info is None or force:
if dep_role not in roles_left:
self.display.display('- adding dependency: %s' % dep_role.name)
display.display('- adding dependency: %s' % dep_role.name)
roles_left.append(dep_role)
else:
self.display.display('- dependency %s already pending installation.' % dep_role.name)
display.display('- dependency %s already pending installation.' % dep_role.name)
else:
self.display.display('- dependency %s is already installed, skipping.' % dep_role.name)
display.display('- dependency %s is already installed, skipping.' % dep_role.name)
if not installed:
self.display.warning("- %s was NOT installed successfully." % role.name)
display.warning("- %s was NOT installed successfully." % role.name)
self.exit_without_ignore()
return 0
@ -398,9 +403,9 @@ class GalaxyCLI(CLI):
role = GalaxyRole(self.galaxy, role_name)
try:
if role.remove():
self.display.display('- successfully removed %s' % role_name)
display.display('- successfully removed %s' % role_name)
else:
self.display.display('- %s is not installed, skipping.' % role_name)
display.display('- %s is not installed, skipping.' % role_name)
except Exception as e:
raise AnsibleError("Failed to remove role %s: %s" % (role_name, str(e)))
@ -429,9 +434,9 @@ class GalaxyCLI(CLI):
if not version:
version = "(unknown version)"
# show some more info about single roles here
self.display.display("- %s, %s" % (name, version))
display.display("- %s, %s" % (name, version))
else:
self.display.display("- the role %s was not found" % name)
display.display("- the role %s was not found" % name)
else:
# show all valid roles in the roles_path directory
roles_path = self.get_opt('roles_path')
@ -450,7 +455,7 @@ class GalaxyCLI(CLI):
version = install_info.get("version", None)
if not version:
version = "(unknown version)"
self.display.display("- %s, %s" % (path_file, version))
display.display("- %s, %s" % (path_file, version))
return 0
def execute_search(self):
@ -464,7 +469,7 @@ class GalaxyCLI(CLI):
response = self.api.search_roles(search, self.options.platforms, self.options.tags)
if 'count' in response:
self.galaxy.display.display("Found %d roles matching your search:\n" % response['count'])
display.display("Found %d roles matching your search:\n" % response['count'])
data = ''
if 'results' in response:

@ -33,6 +33,14 @@ from ansible.parsing.dataloader import DataLoader
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 PlaybookCLI(CLI):
@ -73,7 +81,7 @@ class PlaybookCLI(CLI):
if len(self.args) == 0:
raise AnsibleOptionsError("You must specify a playbook file to run")
self.display.verbosity = self.options.verbosity
display.verbosity = self.options.verbosity
self.validate_conflicts(runas_opts=True, vault_opts=True, fork_opts=True)
def run(self):
@ -129,7 +137,7 @@ class PlaybookCLI(CLI):
no_hosts = False
if len(inventory.list_hosts()) == 0:
# Empty inventory
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
inventory.subset(self.options.subset)
if len(inventory.list_hosts()) == 0 and no_hosts is False:
@ -137,14 +145,14 @@ class PlaybookCLI(CLI):
raise AnsibleError("Specified --limit does not match any hosts")
# create the playbook executor, which manages running the plays via a task queue manager
pbex = PlaybookExecutor(playbooks=self.args, inventory=inventory, variable_manager=variable_manager, loader=loader, display=self.display, options=self.options, passwords=passwords)
pbex = PlaybookExecutor(playbooks=self.args, inventory=inventory, variable_manager=variable_manager, loader=loader, options=self.options, passwords=passwords)
results = pbex.run()
if isinstance(results, list):
for p in results:
self.display.display('\nplaybook: %s' % p['playbook'])
display.display('\nplaybook: %s' % p['playbook'])
i = 1
for play in p['plays']:
if play.name:
@ -164,7 +172,7 @@ class PlaybookCLI(CLI):
for host in playhosts:
msg += "\n %s" % host
self.display.display(msg)
display.display(msg)
if self.options.listtags or self.options.listtasks:
taskmsg = ' tasks:'
@ -180,7 +188,7 @@ class PlaybookCLI(CLI):
taskmsg += " TAGS: [%s]" % ','.join(mytags.union(set(task.tags)))
j = j + 1
self.display.display(taskmsg)
display.display(taskmsg)
i = i + 1
return 0

@ -33,6 +33,14 @@ from ansible.cli import CLI
from ansible.plugins import module_loader
from ansible.utils.cmd_functions import run_cmd
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
########################################################
class PullCLI(CLI):
@ -94,7 +102,7 @@ class PullCLI(CLI):
if self.options.module_name not in self.SUPPORTED_REPO_MODULES:
raise AnsibleOptionsError("Unsuported repo module %s, choices are %s" % (self.options.module_name, ','.join(self.SUPPORTED_REPO_MODULES)))
self.display.verbosity = self.options.verbosity
display.verbosity = self.options.verbosity
self.validate_conflicts(vault_opts=True)
def run(self):
@ -104,8 +112,8 @@ class PullCLI(CLI):
# log command line
now = datetime.datetime.now()
self.display.display(now.strftime("Starting Ansible Pull at %F %T"))
self.display.display(' '.join(sys.argv))
display.display(now.strftime("Starting Ansible Pull at %F %T"))
display.display(' '.join(sys.argv))
# Build Checkout command
# Now construct the ansible command
@ -152,19 +160,19 @@ class PullCLI(CLI):
# Nap?
if self.options.sleep:
self.display.display("Sleeping for %d seconds..." % self.options.sleep)
time.sleep(self.options.sleep);
display.display("Sleeping for %d seconds..." % self.options.sleep)
time.sleep(self.options.sleep)
# RUN the Checkout command
rc, out, err = run_cmd(cmd, live=True)
if rc != 0:
if self.options.force:
self.display.warning("Unable to update repository. Continuing with (forced) run of playbook.")
display.warning("Unable to update repository. Continuing with (forced) run of playbook.")
else:
return rc
elif self.options.ifchanged and '"changed": true' not in out:
self.display.display("Repository has not changed, quitting.")
display.display("Repository has not changed, quitting.")
return 0
playbook = self.select_playbook(path)
@ -197,11 +205,10 @@ class PullCLI(CLI):
try:
shutil.rmtree(self.options.dest)
except Exception as e:
self.display.error("Failed to remove %s: %s" % (self.options.dest, str(e)))
display.error("Failed to remove %s: %s" % (self.options.dest, str(e)))
return rc
def try_playbook(self, path):
if not os.path.exists(path):
return 1
@ -215,7 +222,7 @@ class PullCLI(CLI):
playbook = os.path.join(path, self.args[0])
rc = self.try_playbook(playbook)
if rc != 0:
self.display.warning("%s: %s" % (playbook, self.PLAYBOOK_ERRORS[rc]))
display.warning("%s: %s" % (playbook, self.PLAYBOOK_ERRORS[rc]))
return None
return playbook
else:
@ -232,5 +239,5 @@ class PullCLI(CLI):
else:
errors.append("%s: %s" % (pb, self.PLAYBOOK_ERRORS[rc]))
if playbook is None:
self.display.warning("\n".join(errors))
display.warning("\n".join(errors))
return playbook

@ -27,16 +27,24 @@ from ansible.parsing.dataloader import DataLoader
from ansible.parsing.vault import VaultEditor
from ansible.cli import CLI
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
class VaultCLI(CLI):
""" Vault command line class """
VALID_ACTIONS = ("create", "decrypt", "edit", "encrypt", "rekey", "view")
def __init__(self, args, display=None):
def __init__(self, args):
self.vault_pass = None
self.new_vault_pass = None
super(VaultCLI, self).__init__(args, display)
super(VaultCLI, self).__init__(args)
def parse(self):
@ -63,7 +71,7 @@ class VaultCLI(CLI):
self.parser.set_usage("usage: %prog rekey [options] file_name")
self.options, self.args = self.parser.parse_args()
self.display.verbosity = self.options.verbosity
display.verbosity = self.options.verbosity
can_output = ['encrypt', 'decrypt']
@ -117,24 +125,24 @@ class VaultCLI(CLI):
def execute_encrypt(self):
if len(self.args) == 0 and sys.stdin.isatty():
self.display.display("Reading plaintext input from stdin", stderr=True)
display.display("Reading plaintext input from stdin", stderr=True)
for f in self.args or ['-']:
self.editor.encrypt_file(f, output_file=self.options.output_file)
if sys.stdout.isatty():
self.display.display("Encryption successful", stderr=True)
display.display("Encryption successful", stderr=True)
def execute_decrypt(self):
if len(self.args) == 0 and sys.stdin.isatty():
self.display.display("Reading ciphertext input from stdin", stderr=True)
display.display("Reading ciphertext input from stdin", stderr=True)
for f in self.args or ['-']:
self.editor.decrypt_file(f, output_file=self.options.output_file)
if sys.stdout.isatty():
self.display.display("Decryption successful", stderr=True)
display.display("Decryption successful", stderr=True)
def execute_create(self):
@ -160,4 +168,4 @@ class VaultCLI(CLI):
for f in self.args:
self.editor.rekey_file(f, self.new_vault_pass)
self.display.display("Rekey successful", stderr=True)
display.display("Rekey successful", stderr=True)

@ -27,7 +27,6 @@ import sys
from ansible.compat.six import string_types
from ansible import constants as C
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.playbook import Playbook
from ansible.template import Templar
@ -36,6 +35,14 @@ from ansible.utils.color import colorize, hostcolor
from ansible.utils.encrypt import do_encrypt
from ansible.utils.unicode import to_unicode
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
class PlaybookExecutor:
'''
@ -43,12 +50,11 @@ class PlaybookExecutor:
basis for bin/ansible-playbook operation.
'''
def __init__(self, playbooks, inventory, variable_manager, loader, display, options, passwords):
def __init__(self, playbooks, inventory, variable_manager, loader, options, passwords):
self._playbooks = playbooks
self._inventory = inventory
self._variable_manager = variable_manager
self._loader = loader
self._display = display
self._options = options
self.passwords = passwords
self._unreachable_hosts = dict()
@ -56,7 +62,7 @@ class PlaybookExecutor:
if options.listhosts or options.listtasks or options.listtags or options.syntax:
self._tqm = None
else:
self._tqm = TaskQueueManager(inventory=inventory, variable_manager=variable_manager, loader=loader, display=display, options=options, passwords=self.passwords)
self._tqm = TaskQueueManager(inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=self.passwords)
def run(self):
@ -81,7 +87,7 @@ class PlaybookExecutor:
i = 1
plays = pb.get_plays()
self._display.vv('%d plays in %s' % (len(plays), playbook_path))
display.vv('%d plays in %s' % (len(plays), playbook_path))
for play in plays:
if play._included_path is not None:
@ -178,18 +184,18 @@ class PlaybookExecutor:
self._cleanup()
if self._options.syntax:
self.display.display("No issues encountered")
display.display("No issues encountered")
return result
# TODO: this stat summary stuff should be cleaned up and moved
# to a new method, if it even belongs here...
self._display.banner("PLAY RECAP")
display.banner("PLAY RECAP")
hosts = sorted(self._tqm._stats.processed.keys())
for h in hosts:
t = self._tqm._stats.summarize(h)
self._display.display(u"%s : %s %s %s %s" % (
display.display(u"%s : %s %s %s %s" % (
hostcolor(h, t),
colorize(u'ok', t['ok'], 'green'),
colorize(u'changed', t['changed'], 'yellow'),
@ -198,7 +204,7 @@ class PlaybookExecutor:
screen_only=True
)
self._display.display(u"%s : %s %s %s %s" % (
display.display(u"%s : %s %s %s %s" % (
hostcolor(h, t, False),
colorize(u'ok', t['ok'], None),
colorize(u'changed', t['changed'], None),
@ -207,7 +213,7 @@ class PlaybookExecutor:
log_only=True
)
self._display.display("", screen_only=True)
display.display("", screen_only=True)
# END STATS STUFF
return result
@ -281,12 +287,12 @@ class PlaybookExecutor:
second = do_prompt("confirm " + msg, private)
if result == second:
break
self._display.display("***** VALUES ENTERED DO NOT MATCH ****")
display.display("***** VALUES ENTERED DO NOT MATCH ****")
else:
result = do_prompt(msg, private)
else:
result = None
self._display.warning("Not prompting as we are not in interactive mode")
display.warning("Not prompting as we are not in interactive mode")
# if result is false and default is not None
if not result and default is not None:
@ -298,5 +304,3 @@ class PlaybookExecutor:
# handle utf-8 chars
result = to_unicode(result, errors='strict')
return result

@ -21,7 +21,6 @@ __metaclass__ = type
import multiprocessing
import os
import socket
import tempfile
from ansible import constants as C
@ -34,8 +33,16 @@ from ansible.playbook.play_context import PlayContext
from ansible.plugins import callback_loader, strategy_loader, module_loader
from ansible.template import Templar
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
__all__ = ['TaskQueueManager']
class TaskQueueManager:
'''
@ -48,12 +55,11 @@ class TaskQueueManager:
which dispatches the Play's tasks to hosts.
'''
def __init__(self, inventory, variable_manager, loader, display, options, passwords, stdout_callback=None):
def __init__(self, inventory, variable_manager, loader, options, passwords, stdout_callback=None):
self._inventory = inventory
self._variable_manager = variable_manager
self._loader = loader
self._display = display
self._options = options
self._stats = AggregateStats()
self.passwords = passwords
@ -155,7 +161,9 @@ class TaskQueueManager:
elif callback_needs_whitelist and (C.DEFAULT_CALLBACK_WHITELIST is None or callback_name not in C.DEFAULT_CALLBACK_WHITELIST):
continue
self._callback_plugins.append(callback_plugin(self._display))
# is it too late to change the API for v2 callback plugins?
# display is not necessary.
self._callback_plugins.append(callback_plugin(display))
else:
self._callback_plugins.append(callback_plugin())
@ -221,7 +229,7 @@ class TaskQueueManager:
return play_return
def cleanup(self):
self._display.debug("RUNNING CLEANUP")
display.debug("RUNNING CLEANUP")
self.terminate()
self._final_q.close()
self._cleanup_processes()
@ -275,4 +283,4 @@ class TaskQueueManager:
v1_method = method.replace('v2_','')
v1_method(*args, **kwargs)
except Exception:
self._display.warning('Error when using %s: %s' % (method, str(e)))
display.warning('Error when using %s: %s' % (method, str(e)))

@ -28,7 +28,6 @@ import os
from ansible.compat.six import string_types
from ansible.errors import AnsibleError
from ansible.utils.display import Display
# default_readme_template
# default_meta_template
@ -37,12 +36,7 @@ from ansible.utils.display import Display
class Galaxy(object):
''' Keeps global galaxy info '''
def __init__(self, options, display=None):
if display is None:
self.display = Display()
else:
self.display = display
def __init__(self, options):
self.options = options
roles_paths = getattr(self.options, 'roles_path', [])
@ -65,11 +59,9 @@ class Galaxy(object):
def remove_role(self, role_name):
del self.roles[role_name]
def _str_from_data_file(self, filename):
myfile = os.path.join(self.DATA_PATH, filename)
try:
return open(myfile).read()
except Exception as e:
raise AnsibleError("Could not open %s: %s" % (filename, str(e)))

@ -61,7 +61,6 @@ class TestPlayIterator(unittest.TestCase):
})
mock_inventory = MagicMock()
mock_display = MagicMock()
mock_var_manager = MagicMock()
# fake out options to use the syntax CLI switch, which will ensure
@ -74,7 +73,6 @@ class TestPlayIterator(unittest.TestCase):
inventory=mock_inventory,
variable_manager=mock_var_manager,
loader=fake_loader,
display=mock_display,
options=mock_options,
passwords=[],
)

Loading…
Cancel
Save