Migrate cli and dependencies to use global display
This commit is contained in:
parent
1b7d3f2898
commit
318bfbb207
12 changed files with 167 additions and 131 deletions
|
@ -79,7 +79,7 @@ if __name__ == '__main__':
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
cli = mycli(sys.argv, display=display)
|
cli = mycli(sys.argv)
|
||||||
cli.parse()
|
cli.parse()
|
||||||
sys.exit(cli.run())
|
sys.exit(cli.run())
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,14 @@ from ansible import __version__
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.errors import AnsibleError, AnsibleOptionsError
|
from ansible.errors import AnsibleError, AnsibleOptionsError
|
||||||
from ansible.utils.unicode import to_bytes
|
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):
|
class SortedOptParser(optparse.OptionParser):
|
||||||
'''Optparser which sorts the options by opt before outputting --help'''
|
'''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'))
|
self.option_list.sort(key=operator.methodcaller('get_opt_string'))
|
||||||
return optparse.OptionParser.format_help(self, formatter=None)
|
return optparse.OptionParser.format_help(self, formatter=None)
|
||||||
|
|
||||||
|
|
||||||
class CLI(object):
|
class CLI(object):
|
||||||
''' code behind bin/ansible* programs '''
|
''' 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)
|
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)
|
# -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
|
Base init method for all command line programs
|
||||||
"""
|
"""
|
||||||
|
@ -69,11 +77,6 @@ class CLI(object):
|
||||||
self.parser = None
|
self.parser = None
|
||||||
self.action = None
|
self.action = None
|
||||||
|
|
||||||
if display is None:
|
|
||||||
self.display = Display()
|
|
||||||
else:
|
|
||||||
self.display = display
|
|
||||||
|
|
||||||
def set_action(self):
|
def set_action(self):
|
||||||
"""
|
"""
|
||||||
Get the action the user wants to execute from the sys argv list.
|
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 self.options.verbosity > 0:
|
||||||
if C.CONFIG_FILE:
|
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:
|
else:
|
||||||
self.display.display("No config file found; using defaults")
|
display.display("No config file found; using defaults")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def ask_vault_passwords(ask_new_vault_pass=False, rekey=False):
|
def ask_vault_passwords(ask_new_vault_pass=False, rekey=False):
|
||||||
|
@ -135,7 +138,6 @@ class CLI(object):
|
||||||
|
|
||||||
return vault_pass, new_vault_pass
|
return vault_pass, new_vault_pass
|
||||||
|
|
||||||
|
|
||||||
def ask_passwords(self):
|
def ask_passwords(self):
|
||||||
''' prompt for connection and become passwords if needed '''
|
''' prompt for connection and become passwords if needed '''
|
||||||
|
|
||||||
|
@ -164,7 +166,6 @@ class CLI(object):
|
||||||
|
|
||||||
return (sshpass, becomepass)
|
return (sshpass, becomepass)
|
||||||
|
|
||||||
|
|
||||||
def normalize_become_options(self):
|
def normalize_become_options(self):
|
||||||
''' this keeps backwards compatibility with sudo/su self.options '''
|
''' 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
|
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 = True
|
||||||
self.options.become_method = 'su'
|
self.options.become_method = 'su'
|
||||||
|
|
||||||
|
|
||||||
def validate_conflicts(self, vault_opts=False, runas_opts=False, fork_opts=False):
|
def validate_conflicts(self, vault_opts=False, runas_opts=False, fork_opts=False):
|
||||||
''' check for conflicting options '''
|
''' check for conflicting options '''
|
||||||
|
|
||||||
|
@ -190,7 +190,6 @@ class CLI(object):
|
||||||
if (op.ask_vault_pass and op.vault_password_file):
|
if (op.ask_vault_pass and op.vault_password_file):
|
||||||
self.parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive")
|
self.parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive")
|
||||||
|
|
||||||
|
|
||||||
if runas_opts:
|
if runas_opts:
|
||||||
# Check for privilege escalation conflicts
|
# Check for privilege escalation conflicts
|
||||||
if (op.su or op.su_user or op.ask_su_pass) and \
|
if (op.su or op.su_user or op.ask_su_pass) and \
|
||||||
|
@ -215,7 +214,7 @@ class CLI(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def base_parser(usage="", output_opts=False, runas_opts=False, meta_opts=False, runtask_opts=False, vault_opts=False, module_opts=False,
|
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 '''
|
''' create an options parser for most ansible scripts '''
|
||||||
|
|
||||||
# TODO: implement epilog parsing
|
# TODO: implement epilog parsing
|
||||||
|
@ -257,7 +256,6 @@ class CLI(object):
|
||||||
parser.add_option('--output', default=None, dest='output_file',
|
parser.add_option('--output', default=None, dest='output_file',
|
||||||
help='output file name for encrypt or decrypt; use - for stdout')
|
help='output file name for encrypt or decrypt; use - for stdout')
|
||||||
|
|
||||||
|
|
||||||
if subset_opts:
|
if subset_opts:
|
||||||
parser.add_option('-t', '--tags', dest='tags', default='all',
|
parser.add_option('-t', '--tags', dest='tags', default='all',
|
||||||
help="only run plays and tasks tagged with these values")
|
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',
|
parser.add_option('--ask-become-pass', default=False, dest='become_ask_pass', action='store_true',
|
||||||
help='ask for privilege escalation password')
|
help='ask for privilege escalation password')
|
||||||
|
|
||||||
|
|
||||||
if connect_opts:
|
if connect_opts:
|
||||||
parser.add_option('-k', '--ask-pass', default=C.DEFAULT_ASK_PASS, dest='ask_pass', action='store_true',
|
parser.add_option('-k', '--ask-pass', default=C.DEFAULT_ASK_PASS, dest='ask_pass', action='store_true',
|
||||||
help='ask for connection password')
|
help='ask for connection password')
|
||||||
|
@ -427,7 +424,7 @@ class CLI(object):
|
||||||
result = CLI._git_repo_info(repo_path)
|
result = CLI._git_repo_info(repo_path)
|
||||||
submodules = os.path.join(basedir, '.gitmodules')
|
submodules = os.path.join(basedir, '.gitmodules')
|
||||||
if not os.path.exists(submodules):
|
if not os.path.exists(submodules):
|
||||||
return result
|
return result
|
||||||
f = open(submodules)
|
f = open(submodules)
|
||||||
for line in f:
|
for line in f:
|
||||||
tokens = line.strip().split(' ')
|
tokens = line.strip().split(' ')
|
||||||
|
@ -440,21 +437,20 @@ class CLI(object):
|
||||||
f.close()
|
f.close()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def pager(self, text):
|
def pager(self, text):
|
||||||
''' find reasonable way to display text '''
|
''' find reasonable way to display text '''
|
||||||
# this is a much simpler form of what is in pydoc.py
|
# this is a much simpler form of what is in pydoc.py
|
||||||
if not sys.stdout.isatty():
|
if not sys.stdout.isatty():
|
||||||
self.display.display(text)
|
display.display(text)
|
||||||
elif 'PAGER' in os.environ:
|
elif 'PAGER' in os.environ:
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
self.display.display(text)
|
display.display(text)
|
||||||
else:
|
else:
|
||||||
self.pager_pipe(text, os.environ['PAGER'])
|
self.pager_pipe(text, os.environ['PAGER'])
|
||||||
elif subprocess.call('(less --version) 2> /dev/null', shell = True) == 0:
|
elif subprocess.call('(less --version) 2> /dev/null', shell = True) == 0:
|
||||||
self.pager_pipe(text, 'less')
|
self.pager_pipe(text, 'less')
|
||||||
else:
|
else:
|
||||||
self.display.display(text)
|
display.display(text)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def pager_pipe(text, cmd):
|
def pager_pipe(text, cmd):
|
||||||
|
@ -521,4 +517,3 @@ class CLI(object):
|
||||||
if os.pathsep in data:
|
if os.pathsep in data:
|
||||||
data = data.split(os.pathsep)[0]
|
data = data.split(os.pathsep)[0]
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,14 @@ from ansible.plugins import get_all_plugin_loaders
|
||||||
from ansible.utils.vars import load_extra_vars
|
from ansible.utils.vars import load_extra_vars
|
||||||
from ansible.vars import VariableManager
|
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):
|
class AdHocCLI(CLI):
|
||||||
|
@ -68,7 +76,7 @@ class AdHocCLI(CLI):
|
||||||
if len(self.args) != 1:
|
if len(self.args) != 1:
|
||||||
raise AnsibleOptionsError("Missing target hosts")
|
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)
|
self.validate_conflicts(runas_opts=True, vault_opts=True, fork_opts=True)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -86,7 +94,6 @@ class AdHocCLI(CLI):
|
||||||
|
|
||||||
super(AdHocCLI, self).run()
|
super(AdHocCLI, self).run()
|
||||||
|
|
||||||
|
|
||||||
# only thing left should be host pattern
|
# only thing left should be host pattern
|
||||||
pattern = self.args[0]
|
pattern = self.args[0]
|
||||||
|
|
||||||
|
@ -121,7 +128,7 @@ class AdHocCLI(CLI):
|
||||||
hosts = inventory.list_hosts(pattern)
|
hosts = inventory.list_hosts(pattern)
|
||||||
no_hosts = False
|
no_hosts = False
|
||||||
if len(hosts) == 0:
|
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
|
no_hosts = True
|
||||||
|
|
||||||
if self.options.subset:
|
if self.options.subset:
|
||||||
|
@ -131,9 +138,9 @@ class AdHocCLI(CLI):
|
||||||
raise AnsibleError("Specified --limit does not match any hosts")
|
raise AnsibleError("Specified --limit does not match any hosts")
|
||||||
|
|
||||||
if self.options.listhosts:
|
if self.options.listhosts:
|
||||||
self.display.display(' hosts (%d):' % len(hosts))
|
display.display(' hosts (%d):' % len(hosts))
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
self.display.display(' %s' % host)
|
display.display(' %s' % host)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if self.options.module_name in C.MODULE_REQUIRE_ARGS and not self.options.module_args:
|
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,
|
inventory=inventory,
|
||||||
variable_manager=variable_manager,
|
variable_manager=variable_manager,
|
||||||
loader=loader,
|
loader=loader,
|
||||||
display=self.display,
|
|
||||||
options=self.options,
|
options=self.options,
|
||||||
passwords=passwords,
|
passwords=passwords,
|
||||||
stdout_callback=cb,
|
stdout_callback=cb,
|
||||||
|
|
|
@ -31,15 +31,23 @@ from ansible.plugins import module_loader
|
||||||
from ansible.cli import CLI
|
from ansible.cli import CLI
|
||||||
from ansible.utils import module_docs
|
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):
|
class DocCLI(CLI):
|
||||||
""" Vault command line class """
|
""" Vault command line class """
|
||||||
|
|
||||||
BLACKLIST_EXTS = ('.pyc', '.swp', '.bak', '~', '.rpm', '.md', '.txt')
|
BLACKLIST_EXTS = ('.pyc', '.swp', '.bak', '~', '.rpm', '.md', '.txt')
|
||||||
IGNORE_FILES = [ "COPYING", "CONTRIBUTING", "LICENSE", "README", "VERSION", "GUIDELINES", "test-docs.sh"]
|
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 = []
|
self.module_list = []
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
|
@ -56,8 +64,7 @@ class DocCLI(CLI):
|
||||||
help='Show playbook snippet for specified module(s)')
|
help='Show playbook snippet for specified module(s)')
|
||||||
|
|
||||||
self.options, self.args = self.parser.parse_args()
|
self.options, self.args = self.parser.parse_args()
|
||||||
self.display.verbosity = self.options.verbosity
|
display.verbosity = self.options.verbosity
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
|
@ -86,7 +93,7 @@ class DocCLI(CLI):
|
||||||
try:
|
try:
|
||||||
filename = module_loader.find_plugin(module)
|
filename = module_loader.find_plugin(module)
|
||||||
if filename is None:
|
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
|
continue
|
||||||
|
|
||||||
if any(filename.endswith(x) for x in self.BLACKLIST_EXTS):
|
if any(filename.endswith(x) for x in self.BLACKLIST_EXTS):
|
||||||
|
@ -95,8 +102,8 @@ class DocCLI(CLI):
|
||||||
try:
|
try:
|
||||||
doc, plainexamples, returndocs = module_docs.get_docstring(filename, verbose=(self.options.verbosity > 0))
|
doc, plainexamples, returndocs = module_docs.get_docstring(filename, verbose=(self.options.verbosity > 0))
|
||||||
except:
|
except:
|
||||||
self.display.vvv(traceback.print_exc())
|
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.error("module %s has a documentation error formatting or is missing documentation\nTo see exact traceback use -vvv" % module)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if doc is not None:
|
if doc is not None:
|
||||||
|
@ -122,7 +129,7 @@ class DocCLI(CLI):
|
||||||
# probably a quoting issue.
|
# probably a quoting issue.
|
||||||
raise AnsibleError("Parsing produced an empty object.")
|
raise AnsibleError("Parsing produced an empty object.")
|
||||||
except Exception as e:
|
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)))
|
raise AnsibleError("module %s missing documentation (or could not parse documentation): %s\n" % (module, str(e)))
|
||||||
|
|
||||||
self.pager(text)
|
self.pager(text)
|
||||||
|
@ -150,9 +157,8 @@ class DocCLI(CLI):
|
||||||
module = os.path.splitext(module)[0] # removes the extension
|
module = os.path.splitext(module)[0] # removes the extension
|
||||||
self.module_list.append(module)
|
self.module_list.append(module)
|
||||||
|
|
||||||
|
|
||||||
def get_module_list_text(self):
|
def get_module_list_text(self):
|
||||||
columns = self.display.columns
|
columns = display.columns
|
||||||
displace = max(len(x) for x in self.module_list)
|
displace = max(len(x) for x in self.module_list)
|
||||||
linelimit = columns - displace - 5
|
linelimit = columns - displace - 5
|
||||||
text = []
|
text = []
|
||||||
|
@ -189,7 +195,6 @@ class DocCLI(CLI):
|
||||||
text.extend(deprecated)
|
text.extend(deprecated)
|
||||||
return "\n".join(text)
|
return "\n".join(text)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def print_paths(finder):
|
def print_paths(finder):
|
||||||
''' Returns a string suitable for printing of the search path '''
|
''' Returns a string suitable for printing of the search path '''
|
||||||
|
@ -209,7 +214,7 @@ class DocCLI(CLI):
|
||||||
text.append(" action: %s" % (doc['module']))
|
text.append(" action: %s" % (doc['module']))
|
||||||
pad = 31
|
pad = 31
|
||||||
subdent = ''.join([" " for a in xrange(pad)])
|
subdent = ''.join([" " for a in xrange(pad)])
|
||||||
limit = self.display.columns - pad
|
limit = display.columns - pad
|
||||||
|
|
||||||
for o in sorted(doc['options'].keys()):
|
for o in sorted(doc['options'].keys()):
|
||||||
opt = doc['options'][o]
|
opt = doc['options'][o]
|
||||||
|
@ -229,8 +234,8 @@ class DocCLI(CLI):
|
||||||
opt_indent=" "
|
opt_indent=" "
|
||||||
text = []
|
text = []
|
||||||
text.append("> %s\n" % doc['module'].upper())
|
text.append("> %s\n" % doc['module'].upper())
|
||||||
pad = self.display.columns * 0.20
|
pad = display.columns * 0.20
|
||||||
limit = max(self.display.columns - int(pad), 70)
|
limit = max(display.columns - int(pad), 70)
|
||||||
|
|
||||||
if isinstance(doc['description'], list):
|
if isinstance(doc['description'], list):
|
||||||
desc = " ".join(doc['description'])
|
desc = " ".join(doc['description'])
|
||||||
|
|
|
@ -28,7 +28,6 @@ import sys
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from distutils.version import LooseVersion
|
|
||||||
from jinja2 import Environment
|
from jinja2 import Environment
|
||||||
|
|
||||||
import ansible.constants as C
|
import ansible.constants as C
|
||||||
|
@ -39,16 +38,24 @@ from ansible.galaxy.api import GalaxyAPI
|
||||||
from ansible.galaxy.role import GalaxyRole
|
from ansible.galaxy.role import GalaxyRole
|
||||||
from ansible.playbook.role.requirement import RoleRequirement
|
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):
|
class GalaxyCLI(CLI):
|
||||||
|
|
||||||
VALID_ACTIONS = ("init", "info", "install", "list", "remove", "search")
|
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" )
|
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.api = None
|
||||||
self.galaxy = None
|
self.galaxy = None
|
||||||
super(GalaxyCLI, self).__init__(args, display)
|
super(GalaxyCLI, self).__init__(args)
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
''' create an options parser for bin/ansible '''
|
''' 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])
|
epilog = "\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
self.set_action()
|
self.set_action()
|
||||||
|
|
||||||
# options specific to actions
|
# options specific to actions
|
||||||
|
@ -109,8 +115,8 @@ class GalaxyCLI(CLI):
|
||||||
|
|
||||||
# get options, args and galaxy object
|
# get options, args and galaxy object
|
||||||
self.options, self.args =self.parser.parse_args()
|
self.options, self.args =self.parser.parse_args()
|
||||||
self.display.verbosity = self.options.verbosity
|
display.verbosity = self.options.verbosity
|
||||||
self.galaxy = Galaxy(self.options, self.display)
|
self.galaxy = Galaxy(self.options)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -178,10 +184,10 @@ class GalaxyCLI(CLI):
|
||||||
if os.path.isfile(role_path):
|
if os.path.isfile(role_path):
|
||||||
raise AnsibleError("- the path %s already exists, but is a file - aborting" % role_path)
|
raise AnsibleError("- the path %s already exists, but is a file - aborting" % role_path)
|
||||||
elif not force:
|
elif not force:
|
||||||
raise AnsibleError("- the directory %s already exists." % role_path + \
|
raise AnsibleError("- the directory %s already exists."
|
||||||
"you can use --force to re-initialize this directory,\n" + \
|
"you can use --force to re-initialize this directory,\n"
|
||||||
"however it will reset any main.yml files that may have\n" + \
|
"however it will reset any main.yml files that may have\n"
|
||||||
"been modified there already.")
|
"been modified there already." % role_path)
|
||||||
|
|
||||||
# create the default README.md
|
# create the default README.md
|
||||||
if not os.path.exists(role_path):
|
if not os.path.exists(role_path):
|
||||||
|
@ -234,7 +240,7 @@ class GalaxyCLI(CLI):
|
||||||
f = open(main_yml_path, 'w')
|
f = open(main_yml_path, 'w')
|
||||||
f.write('---\n# %s file for %s\n' % (dir,role_name))
|
f.write('---\n# %s file for %s\n' % (dir,role_name))
|
||||||
f.close()
|
f.close()
|
||||||
self.display.display("- %s was created successfully" % role_name)
|
display.display("- %s was created successfully" % role_name)
|
||||||
|
|
||||||
def execute_info(self):
|
def execute_info(self):
|
||||||
"""
|
"""
|
||||||
|
@ -297,7 +303,7 @@ class GalaxyCLI(CLI):
|
||||||
# the user needs to specify one of either --role-file
|
# the user needs to specify one of either --role-file
|
||||||
# or specify a single user/role name
|
# or specify a single user/role name
|
||||||
raise AnsibleOptionsError("- you must specify a user/role name or a roles file")
|
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
|
# using a role file is mutually exclusive of specifying
|
||||||
# the role name on the command line
|
# the role name on the command line
|
||||||
raise AnsibleOptionsError("- please specify a user/role name, or a roles file, but not both")
|
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:
|
for role in required_roles:
|
||||||
role = RoleRequirement.role_yaml_parse(role)
|
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:
|
if 'name' not in role and 'scm' not in role:
|
||||||
raise AnsibleError("Must specify name or src for role")
|
raise AnsibleError("Must specify name or src for role")
|
||||||
roles_left.append(GalaxyRole(self.galaxy, **role))
|
roles_left.append(GalaxyRole(self.galaxy, **role))
|
||||||
else:
|
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
|
# roles listed in a file, one per line
|
||||||
for rline in f.readlines():
|
for rline in f.readlines():
|
||||||
if rline.startswith("#") or rline.strip() == '':
|
if rline.startswith("#") or rline.strip() == '':
|
||||||
continue
|
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())
|
role = RoleRequirement.role_yaml_parse(rline.strip())
|
||||||
roles_left.append(GalaxyRole(self.galaxy, **role))
|
roles_left.append(GalaxyRole(self.galaxy, **role))
|
||||||
f.close()
|
f.close()
|
||||||
except (IOError, OSError) as e:
|
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:
|
else:
|
||||||
# roles were specified directly, so we'll just go out grab them
|
# roles were specified directly, so we'll just go out grab them
|
||||||
# (and their dependencies, unless the user doesn't want us to).
|
# (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()))
|
roles_left.append(GalaxyRole(self.galaxy, rname.strip()))
|
||||||
|
|
||||||
for role in roles_left:
|
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
|
# query the galaxy API for the role data
|
||||||
role_data = None
|
|
||||||
|
|
||||||
if role.install_info is not None and not force:
|
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
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
installed = role.install()
|
installed = role.install()
|
||||||
except AnsibleError as e:
|
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()
|
self.exit_without_ignore()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -362,7 +367,7 @@ class GalaxyCLI(CLI):
|
||||||
if not no_deps and installed:
|
if not no_deps and installed:
|
||||||
role_dependencies = role.metadata.get('dependencies') or []
|
role_dependencies = role.metadata.get('dependencies') or []
|
||||||
for dep in role_dependencies:
|
for dep in role_dependencies:
|
||||||
self.display.debug('Installing dep %s' % dep)
|
display.debug('Installing dep %s' % dep)
|
||||||
dep_req = RoleRequirement()
|
dep_req = RoleRequirement()
|
||||||
dep_info = dep_req.role_yaml_parse(dep)
|
dep_info = dep_req.role_yaml_parse(dep)
|
||||||
dep_role = GalaxyRole(self.galaxy, **dep_info)
|
dep_role = GalaxyRole(self.galaxy, **dep_info)
|
||||||
|
@ -372,15 +377,15 @@ class GalaxyCLI(CLI):
|
||||||
continue
|
continue
|
||||||
if dep_role.install_info is None or force:
|
if dep_role.install_info is None or force:
|
||||||
if dep_role not in roles_left:
|
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)
|
roles_left.append(dep_role)
|
||||||
else:
|
else:
|
||||||
self.display.display('- dependency %s already pending installation.' % dep_role.name)
|
display.display('- dependency %s already pending installation.' % dep_role.name)
|
||||||
else:
|
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:
|
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()
|
self.exit_without_ignore()
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
@ -398,9 +403,9 @@ class GalaxyCLI(CLI):
|
||||||
role = GalaxyRole(self.galaxy, role_name)
|
role = GalaxyRole(self.galaxy, role_name)
|
||||||
try:
|
try:
|
||||||
if role.remove():
|
if role.remove():
|
||||||
self.display.display('- successfully removed %s' % role_name)
|
display.display('- successfully removed %s' % role_name)
|
||||||
else:
|
else:
|
||||||
self.display.display('- %s is not installed, skipping.' % role_name)
|
display.display('- %s is not installed, skipping.' % role_name)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise AnsibleError("Failed to remove role %s: %s" % (role_name, str(e)))
|
raise AnsibleError("Failed to remove role %s: %s" % (role_name, str(e)))
|
||||||
|
|
||||||
|
@ -429,9 +434,9 @@ class GalaxyCLI(CLI):
|
||||||
if not version:
|
if not version:
|
||||||
version = "(unknown version)"
|
version = "(unknown version)"
|
||||||
# show some more info about single roles here
|
# show some more info about single roles here
|
||||||
self.display.display("- %s, %s" % (name, version))
|
display.display("- %s, %s" % (name, version))
|
||||||
else:
|
else:
|
||||||
self.display.display("- the role %s was not found" % name)
|
display.display("- the role %s was not found" % name)
|
||||||
else:
|
else:
|
||||||
# show all valid roles in the roles_path directory
|
# show all valid roles in the roles_path directory
|
||||||
roles_path = self.get_opt('roles_path')
|
roles_path = self.get_opt('roles_path')
|
||||||
|
@ -450,7 +455,7 @@ class GalaxyCLI(CLI):
|
||||||
version = install_info.get("version", None)
|
version = install_info.get("version", None)
|
||||||
if not version:
|
if not version:
|
||||||
version = "(unknown version)"
|
version = "(unknown version)"
|
||||||
self.display.display("- %s, %s" % (path_file, version))
|
display.display("- %s, %s" % (path_file, version))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def execute_search(self):
|
def execute_search(self):
|
||||||
|
@ -464,7 +469,7 @@ class GalaxyCLI(CLI):
|
||||||
response = self.api.search_roles(search, self.options.platforms, self.options.tags)
|
response = self.api.search_roles(search, self.options.platforms, self.options.tags)
|
||||||
|
|
||||||
if 'count' in response:
|
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 = ''
|
data = ''
|
||||||
if 'results' in response:
|
if 'results' in response:
|
||||||
|
|
|
@ -33,6 +33,14 @@ from ansible.parsing.dataloader import DataLoader
|
||||||
from ansible.utils.vars import load_extra_vars
|
from ansible.utils.vars import load_extra_vars
|
||||||
from ansible.vars import VariableManager
|
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):
|
class PlaybookCLI(CLI):
|
||||||
|
@ -73,7 +81,7 @@ class PlaybookCLI(CLI):
|
||||||
if len(self.args) == 0:
|
if len(self.args) == 0:
|
||||||
raise AnsibleOptionsError("You must specify a playbook file to run")
|
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)
|
self.validate_conflicts(runas_opts=True, vault_opts=True, fork_opts=True)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -129,7 +137,7 @@ class PlaybookCLI(CLI):
|
||||||
no_hosts = False
|
no_hosts = False
|
||||||
if len(inventory.list_hosts()) == 0:
|
if len(inventory.list_hosts()) == 0:
|
||||||
# Empty inventory
|
# 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
|
no_hosts = True
|
||||||
inventory.subset(self.options.subset)
|
inventory.subset(self.options.subset)
|
||||||
if len(inventory.list_hosts()) == 0 and no_hosts is False:
|
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")
|
raise AnsibleError("Specified --limit does not match any hosts")
|
||||||
|
|
||||||
# create the playbook executor, which manages running the plays via a task queue manager
|
# 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()
|
results = pbex.run()
|
||||||
|
|
||||||
if isinstance(results, list):
|
if isinstance(results, list):
|
||||||
for p in results:
|
for p in results:
|
||||||
|
|
||||||
self.display.display('\nplaybook: %s' % p['playbook'])
|
display.display('\nplaybook: %s' % p['playbook'])
|
||||||
i = 1
|
i = 1
|
||||||
for play in p['plays']:
|
for play in p['plays']:
|
||||||
if play.name:
|
if play.name:
|
||||||
|
@ -164,7 +172,7 @@ class PlaybookCLI(CLI):
|
||||||
for host in playhosts:
|
for host in playhosts:
|
||||||
msg += "\n %s" % host
|
msg += "\n %s" % host
|
||||||
|
|
||||||
self.display.display(msg)
|
display.display(msg)
|
||||||
|
|
||||||
if self.options.listtags or self.options.listtasks:
|
if self.options.listtags or self.options.listtasks:
|
||||||
taskmsg = ' tasks:'
|
taskmsg = ' tasks:'
|
||||||
|
@ -180,7 +188,7 @@ class PlaybookCLI(CLI):
|
||||||
taskmsg += " TAGS: [%s]" % ','.join(mytags.union(set(task.tags)))
|
taskmsg += " TAGS: [%s]" % ','.join(mytags.union(set(task.tags)))
|
||||||
j = j + 1
|
j = j + 1
|
||||||
|
|
||||||
self.display.display(taskmsg)
|
display.display(taskmsg)
|
||||||
|
|
||||||
i = i + 1
|
i = i + 1
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -33,6 +33,14 @@ from ansible.cli import CLI
|
||||||
from ansible.plugins import module_loader
|
from ansible.plugins import module_loader
|
||||||
from ansible.utils.cmd_functions import run_cmd
|
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):
|
class PullCLI(CLI):
|
||||||
|
@ -94,7 +102,7 @@ class PullCLI(CLI):
|
||||||
if self.options.module_name not in self.SUPPORTED_REPO_MODULES:
|
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)))
|
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)
|
self.validate_conflicts(vault_opts=True)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -104,8 +112,8 @@ class PullCLI(CLI):
|
||||||
|
|
||||||
# log command line
|
# log command line
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
self.display.display(now.strftime("Starting Ansible Pull at %F %T"))
|
display.display(now.strftime("Starting Ansible Pull at %F %T"))
|
||||||
self.display.display(' '.join(sys.argv))
|
display.display(' '.join(sys.argv))
|
||||||
|
|
||||||
# Build Checkout command
|
# Build Checkout command
|
||||||
# Now construct the ansible command
|
# Now construct the ansible command
|
||||||
|
@ -152,19 +160,19 @@ class PullCLI(CLI):
|
||||||
|
|
||||||
# Nap?
|
# Nap?
|
||||||
if self.options.sleep:
|
if self.options.sleep:
|
||||||
self.display.display("Sleeping for %d seconds..." % self.options.sleep)
|
display.display("Sleeping for %d seconds..." % self.options.sleep)
|
||||||
time.sleep(self.options.sleep);
|
time.sleep(self.options.sleep)
|
||||||
|
|
||||||
# RUN the Checkout command
|
# RUN the Checkout command
|
||||||
rc, out, err = run_cmd(cmd, live=True)
|
rc, out, err = run_cmd(cmd, live=True)
|
||||||
|
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
if self.options.force:
|
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:
|
else:
|
||||||
return rc
|
return rc
|
||||||
elif self.options.ifchanged and '"changed": true' not in out:
|
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
|
return 0
|
||||||
|
|
||||||
playbook = self.select_playbook(path)
|
playbook = self.select_playbook(path)
|
||||||
|
@ -197,11 +205,10 @@ class PullCLI(CLI):
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(self.options.dest)
|
shutil.rmtree(self.options.dest)
|
||||||
except Exception as e:
|
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
|
return rc
|
||||||
|
|
||||||
|
|
||||||
def try_playbook(self, path):
|
def try_playbook(self, path):
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
return 1
|
return 1
|
||||||
|
@ -215,7 +222,7 @@ class PullCLI(CLI):
|
||||||
playbook = os.path.join(path, self.args[0])
|
playbook = os.path.join(path, self.args[0])
|
||||||
rc = self.try_playbook(playbook)
|
rc = self.try_playbook(playbook)
|
||||||
if rc != 0:
|
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 None
|
||||||
return playbook
|
return playbook
|
||||||
else:
|
else:
|
||||||
|
@ -232,5 +239,5 @@ class PullCLI(CLI):
|
||||||
else:
|
else:
|
||||||
errors.append("%s: %s" % (pb, self.PLAYBOOK_ERRORS[rc]))
|
errors.append("%s: %s" % (pb, self.PLAYBOOK_ERRORS[rc]))
|
||||||
if playbook is None:
|
if playbook is None:
|
||||||
self.display.warning("\n".join(errors))
|
display.warning("\n".join(errors))
|
||||||
return playbook
|
return playbook
|
||||||
|
|
|
@ -27,16 +27,24 @@ from ansible.parsing.dataloader import DataLoader
|
||||||
from ansible.parsing.vault import VaultEditor
|
from ansible.parsing.vault import VaultEditor
|
||||||
from ansible.cli import CLI
|
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):
|
class VaultCLI(CLI):
|
||||||
""" Vault command line class """
|
""" Vault command line class """
|
||||||
|
|
||||||
VALID_ACTIONS = ("create", "decrypt", "edit", "encrypt", "rekey", "view")
|
VALID_ACTIONS = ("create", "decrypt", "edit", "encrypt", "rekey", "view")
|
||||||
|
|
||||||
def __init__(self, args, display=None):
|
def __init__(self, args):
|
||||||
|
|
||||||
self.vault_pass = None
|
self.vault_pass = None
|
||||||
self.new_vault_pass = None
|
self.new_vault_pass = None
|
||||||
super(VaultCLI, self).__init__(args, display)
|
super(VaultCLI, self).__init__(args)
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
|
|
||||||
|
@ -63,7 +71,7 @@ class VaultCLI(CLI):
|
||||||
self.parser.set_usage("usage: %prog rekey [options] file_name")
|
self.parser.set_usage("usage: %prog rekey [options] file_name")
|
||||||
|
|
||||||
self.options, self.args = self.parser.parse_args()
|
self.options, self.args = self.parser.parse_args()
|
||||||
self.display.verbosity = self.options.verbosity
|
display.verbosity = self.options.verbosity
|
||||||
|
|
||||||
can_output = ['encrypt', 'decrypt']
|
can_output = ['encrypt', 'decrypt']
|
||||||
|
|
||||||
|
@ -117,24 +125,24 @@ class VaultCLI(CLI):
|
||||||
def execute_encrypt(self):
|
def execute_encrypt(self):
|
||||||
|
|
||||||
if len(self.args) == 0 and sys.stdin.isatty():
|
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 ['-']:
|
for f in self.args or ['-']:
|
||||||
self.editor.encrypt_file(f, output_file=self.options.output_file)
|
self.editor.encrypt_file(f, output_file=self.options.output_file)
|
||||||
|
|
||||||
if sys.stdout.isatty():
|
if sys.stdout.isatty():
|
||||||
self.display.display("Encryption successful", stderr=True)
|
display.display("Encryption successful", stderr=True)
|
||||||
|
|
||||||
def execute_decrypt(self):
|
def execute_decrypt(self):
|
||||||
|
|
||||||
if len(self.args) == 0 and sys.stdin.isatty():
|
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 ['-']:
|
for f in self.args or ['-']:
|
||||||
self.editor.decrypt_file(f, output_file=self.options.output_file)
|
self.editor.decrypt_file(f, output_file=self.options.output_file)
|
||||||
|
|
||||||
if sys.stdout.isatty():
|
if sys.stdout.isatty():
|
||||||
self.display.display("Decryption successful", stderr=True)
|
display.display("Decryption successful", stderr=True)
|
||||||
|
|
||||||
def execute_create(self):
|
def execute_create(self):
|
||||||
|
|
||||||
|
@ -160,4 +168,4 @@ class VaultCLI(CLI):
|
||||||
for f in self.args:
|
for f in self.args:
|
||||||
self.editor.rekey_file(f, self.new_vault_pass)
|
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.compat.six import string_types
|
||||||
|
|
||||||
from ansible import constants as C
|
|
||||||
from ansible.executor.task_queue_manager import TaskQueueManager
|
from ansible.executor.task_queue_manager import TaskQueueManager
|
||||||
from ansible.playbook import Playbook
|
from ansible.playbook import Playbook
|
||||||
from ansible.template import Templar
|
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.encrypt import do_encrypt
|
||||||
from ansible.utils.unicode import to_unicode
|
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:
|
class PlaybookExecutor:
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
@ -43,12 +50,11 @@ class PlaybookExecutor:
|
||||||
basis for bin/ansible-playbook operation.
|
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._playbooks = playbooks
|
||||||
self._inventory = inventory
|
self._inventory = inventory
|
||||||
self._variable_manager = variable_manager
|
self._variable_manager = variable_manager
|
||||||
self._loader = loader
|
self._loader = loader
|
||||||
self._display = display
|
|
||||||
self._options = options
|
self._options = options
|
||||||
self.passwords = passwords
|
self.passwords = passwords
|
||||||
self._unreachable_hosts = dict()
|
self._unreachable_hosts = dict()
|
||||||
|
@ -56,7 +62,7 @@ class PlaybookExecutor:
|
||||||
if options.listhosts or options.listtasks or options.listtags or options.syntax:
|
if options.listhosts or options.listtasks or options.listtags or options.syntax:
|
||||||
self._tqm = None
|
self._tqm = None
|
||||||
else:
|
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):
|
def run(self):
|
||||||
|
|
||||||
|
@ -81,7 +87,7 @@ class PlaybookExecutor:
|
||||||
|
|
||||||
i = 1
|
i = 1
|
||||||
plays = pb.get_plays()
|
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:
|
for play in plays:
|
||||||
if play._included_path is not None:
|
if play._included_path is not None:
|
||||||
|
@ -178,18 +184,18 @@ class PlaybookExecutor:
|
||||||
self._cleanup()
|
self._cleanup()
|
||||||
|
|
||||||
if self._options.syntax:
|
if self._options.syntax:
|
||||||
self.display.display("No issues encountered")
|
display.display("No issues encountered")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# TODO: this stat summary stuff should be cleaned up and moved
|
# TODO: this stat summary stuff should be cleaned up and moved
|
||||||
# to a new method, if it even belongs here...
|
# 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())
|
hosts = sorted(self._tqm._stats.processed.keys())
|
||||||
for h in hosts:
|
for h in hosts:
|
||||||
t = self._tqm._stats.summarize(h)
|
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),
|
hostcolor(h, t),
|
||||||
colorize(u'ok', t['ok'], 'green'),
|
colorize(u'ok', t['ok'], 'green'),
|
||||||
colorize(u'changed', t['changed'], 'yellow'),
|
colorize(u'changed', t['changed'], 'yellow'),
|
||||||
|
@ -198,7 +204,7 @@ class PlaybookExecutor:
|
||||||
screen_only=True
|
screen_only=True
|
||||||
)
|
)
|
||||||
|
|
||||||
self._display.display(u"%s : %s %s %s %s" % (
|
display.display(u"%s : %s %s %s %s" % (
|
||||||
hostcolor(h, t, False),
|
hostcolor(h, t, False),
|
||||||
colorize(u'ok', t['ok'], None),
|
colorize(u'ok', t['ok'], None),
|
||||||
colorize(u'changed', t['changed'], None),
|
colorize(u'changed', t['changed'], None),
|
||||||
|
@ -207,7 +213,7 @@ class PlaybookExecutor:
|
||||||
log_only=True
|
log_only=True
|
||||||
)
|
)
|
||||||
|
|
||||||
self._display.display("", screen_only=True)
|
display.display("", screen_only=True)
|
||||||
# END STATS STUFF
|
# END STATS STUFF
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -230,7 +236,7 @@ class PlaybookExecutor:
|
||||||
serial_pct = int(play.serial.replace("%",""))
|
serial_pct = int(play.serial.replace("%",""))
|
||||||
serial = int((serial_pct/100.0) * len(all_hosts))
|
serial = int((serial_pct/100.0) * len(all_hosts))
|
||||||
else:
|
else:
|
||||||
if play.serial is None:
|
if play.serial is None:
|
||||||
serial = -1
|
serial = -1
|
||||||
else:
|
else:
|
||||||
serial = int(play.serial)
|
serial = int(play.serial)
|
||||||
|
@ -281,12 +287,12 @@ class PlaybookExecutor:
|
||||||
second = do_prompt("confirm " + msg, private)
|
second = do_prompt("confirm " + msg, private)
|
||||||
if result == second:
|
if result == second:
|
||||||
break
|
break
|
||||||
self._display.display("***** VALUES ENTERED DO NOT MATCH ****")
|
display.display("***** VALUES ENTERED DO NOT MATCH ****")
|
||||||
else:
|
else:
|
||||||
result = do_prompt(msg, private)
|
result = do_prompt(msg, private)
|
||||||
else:
|
else:
|
||||||
result = None
|
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 result is false and default is not None
|
||||||
if not result and default is not None:
|
if not result and default is not None:
|
||||||
|
@ -298,5 +304,3 @@ class PlaybookExecutor:
|
||||||
# handle utf-8 chars
|
# handle utf-8 chars
|
||||||
result = to_unicode(result, errors='strict')
|
result = to_unicode(result, errors='strict')
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ __metaclass__ = type
|
||||||
|
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import os
|
import os
|
||||||
import socket
|
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from ansible import constants as C
|
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.plugins import callback_loader, strategy_loader, module_loader
|
||||||
from ansible.template import Templar
|
from ansible.template import Templar
|
||||||
|
|
||||||
|
try:
|
||||||
|
from __main__ import display
|
||||||
|
display = display
|
||||||
|
except ImportError:
|
||||||
|
from ansible.utils.display import Display
|
||||||
|
display = Display()
|
||||||
|
|
||||||
__all__ = ['TaskQueueManager']
|
__all__ = ['TaskQueueManager']
|
||||||
|
|
||||||
|
|
||||||
class TaskQueueManager:
|
class TaskQueueManager:
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
@ -48,12 +55,11 @@ class TaskQueueManager:
|
||||||
which dispatches the Play's tasks to hosts.
|
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._inventory = inventory
|
||||||
self._variable_manager = variable_manager
|
self._variable_manager = variable_manager
|
||||||
self._loader = loader
|
self._loader = loader
|
||||||
self._display = display
|
|
||||||
self._options = options
|
self._options = options
|
||||||
self._stats = AggregateStats()
|
self._stats = AggregateStats()
|
||||||
self.passwords = passwords
|
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):
|
elif callback_needs_whitelist and (C.DEFAULT_CALLBACK_WHITELIST is None or callback_name not in C.DEFAULT_CALLBACK_WHITELIST):
|
||||||
continue
|
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:
|
else:
|
||||||
self._callback_plugins.append(callback_plugin())
|
self._callback_plugins.append(callback_plugin())
|
||||||
|
|
||||||
|
@ -221,7 +229,7 @@ class TaskQueueManager:
|
||||||
return play_return
|
return play_return
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
self._display.debug("RUNNING CLEANUP")
|
display.debug("RUNNING CLEANUP")
|
||||||
self.terminate()
|
self.terminate()
|
||||||
self._final_q.close()
|
self._final_q.close()
|
||||||
self._cleanup_processes()
|
self._cleanup_processes()
|
||||||
|
@ -275,4 +283,4 @@ class TaskQueueManager:
|
||||||
v1_method = method.replace('v2_','')
|
v1_method = method.replace('v2_','')
|
||||||
v1_method(*args, **kwargs)
|
v1_method(*args, **kwargs)
|
||||||
except Exception:
|
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.compat.six import string_types
|
||||||
|
|
||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
from ansible.utils.display import Display
|
|
||||||
|
|
||||||
# default_readme_template
|
# default_readme_template
|
||||||
# default_meta_template
|
# default_meta_template
|
||||||
|
@ -37,12 +36,7 @@ from ansible.utils.display import Display
|
||||||
class Galaxy(object):
|
class Galaxy(object):
|
||||||
''' Keeps global galaxy info '''
|
''' Keeps global galaxy info '''
|
||||||
|
|
||||||
def __init__(self, options, display=None):
|
def __init__(self, options):
|
||||||
|
|
||||||
if display is None:
|
|
||||||
self.display = Display()
|
|
||||||
else:
|
|
||||||
self.display = display
|
|
||||||
|
|
||||||
self.options = options
|
self.options = options
|
||||||
roles_paths = getattr(self.options, 'roles_path', [])
|
roles_paths = getattr(self.options, 'roles_path', [])
|
||||||
|
@ -65,11 +59,9 @@ class Galaxy(object):
|
||||||
def remove_role(self, role_name):
|
def remove_role(self, role_name):
|
||||||
del self.roles[role_name]
|
del self.roles[role_name]
|
||||||
|
|
||||||
|
|
||||||
def _str_from_data_file(self, filename):
|
def _str_from_data_file(self, filename):
|
||||||
myfile = os.path.join(self.DATA_PATH, filename)
|
myfile = os.path.join(self.DATA_PATH, filename)
|
||||||
try:
|
try:
|
||||||
return open(myfile).read()
|
return open(myfile).read()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise AnsibleError("Could not open %s: %s" % (filename, str(e)))
|
raise AnsibleError("Could not open %s: %s" % (filename, str(e)))
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,6 @@ class TestPlayIterator(unittest.TestCase):
|
||||||
})
|
})
|
||||||
|
|
||||||
mock_inventory = MagicMock()
|
mock_inventory = MagicMock()
|
||||||
mock_display = MagicMock()
|
|
||||||
mock_var_manager = MagicMock()
|
mock_var_manager = MagicMock()
|
||||||
|
|
||||||
# fake out options to use the syntax CLI switch, which will ensure
|
# fake out options to use the syntax CLI switch, which will ensure
|
||||||
|
@ -74,7 +73,6 @@ class TestPlayIterator(unittest.TestCase):
|
||||||
inventory=mock_inventory,
|
inventory=mock_inventory,
|
||||||
variable_manager=mock_var_manager,
|
variable_manager=mock_var_manager,
|
||||||
loader=fake_loader,
|
loader=fake_loader,
|
||||||
display=mock_display,
|
|
||||||
options=mock_options,
|
options=mock_options,
|
||||||
passwords=[],
|
passwords=[],
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue