mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-06-14 04:09:11 -07:00
Save the command line arguments into a global context
* Once cli args are parsed, they're constant. So, save the parsed args into the global context for everyone else to use them from now on. * Port cli scripts to use the CLIARGS in the context * Refactor call to parse cli args into the run() method * Fix unittests for changes to the internals of CLI arg parsing * Port callback plugins to use context.CLIARGS * Got rid of the private self._options attribute * Use context.CLIARGS in the individual callback plugins instead. * Also output positional arguments in default and unixy plugins * Code has been simplified since we're now dealing with a dict rather than Optparse.Value
This commit is contained in:
parent
c18da65089
commit
afdbb0d9d5
36 changed files with 1033 additions and 868 deletions
|
@ -1,19 +1,6 @@
|
|||
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
|
||||
#
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
# Copyright: (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
|
||||
# Copyright: (c) 2018, Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
@ -27,8 +14,9 @@ import socket
|
|||
import sys
|
||||
import time
|
||||
|
||||
from ansible.cli import CLI
|
||||
from ansible import constants as C
|
||||
from ansible import context
|
||||
from ansible.cli import CLI
|
||||
from ansible.errors import AnsibleOptionsError
|
||||
from ansible.module_utils._text import to_native, to_text
|
||||
from ansible.plugins.loader import module_loader
|
||||
|
@ -68,8 +56,8 @@ class PullCLI(CLI):
|
|||
def _get_inv_cli(self):
|
||||
|
||||
inv_opts = ''
|
||||
if getattr(self.options, 'inventory'):
|
||||
for inv in self.options.inventory:
|
||||
if context.CLIARGS.get('inventory', False):
|
||||
for inv in context.CLIARGS['inventory']:
|
||||
if isinstance(inv, list):
|
||||
inv_opts += " -i '%s' " % ','.join(inv)
|
||||
elif ',' in inv or os.path.exists(inv):
|
||||
|
@ -77,10 +65,10 @@ class PullCLI(CLI):
|
|||
|
||||
return inv_opts
|
||||
|
||||
def parse(self):
|
||||
def init_parser(self):
|
||||
''' create an options parser for bin/ansible '''
|
||||
|
||||
self.parser = CLI.base_parser(
|
||||
self.parser = super(PullCLI, self).init_parser(
|
||||
usage='%prog -U <repository> [options] [<playbook.yml>]',
|
||||
connect_opts=True,
|
||||
vault_opts=True,
|
||||
|
@ -126,32 +114,37 @@ class PullCLI(CLI):
|
|||
self.parser.add_option("--diff", default=C.DIFF_ALWAYS, dest='diff', action='store_true',
|
||||
help="when changing (small) files and templates, show the differences in those files; works great with --check")
|
||||
|
||||
super(PullCLI, self).parse()
|
||||
return self.parser
|
||||
|
||||
if not self.options.dest:
|
||||
def post_process_args(self, options, args):
|
||||
options, args = super(PullCLI, self).post_process_args(options, args)
|
||||
|
||||
if not options.dest:
|
||||
hostname = socket.getfqdn()
|
||||
# use a hostname dependent directory, in case of $HOME on nfs
|
||||
self.options.dest = os.path.join('~/.ansible/pull', hostname)
|
||||
self.options.dest = os.path.expandvars(os.path.expanduser(self.options.dest))
|
||||
options.dest = os.path.join('~/.ansible/pull', hostname)
|
||||
options.dest = os.path.expandvars(os.path.expanduser(options.dest))
|
||||
|
||||
if os.path.exists(self.options.dest) and not os.path.isdir(self.options.dest):
|
||||
raise AnsibleOptionsError("%s is not a valid or accessible directory." % self.options.dest)
|
||||
if os.path.exists(options.dest) and not os.path.isdir(options.dest):
|
||||
raise AnsibleOptionsError("%s is not a valid or accessible directory." % options.dest)
|
||||
|
||||
if self.options.sleep:
|
||||
if options.sleep:
|
||||
try:
|
||||
secs = random.randint(0, int(self.options.sleep))
|
||||
self.options.sleep = secs
|
||||
secs = random.randint(0, int(options.sleep))
|
||||
options.sleep = secs
|
||||
except ValueError:
|
||||
raise AnsibleOptionsError("%s is not a number." % self.options.sleep)
|
||||
raise AnsibleOptionsError("%s is not a number." % options.sleep)
|
||||
|
||||
if not self.options.url:
|
||||
if not options.url:
|
||||
raise AnsibleOptionsError("URL for repository not specified, use -h for help")
|
||||
|
||||
if self.options.module_name not in self.SUPPORTED_REPO_MODULES:
|
||||
raise AnsibleOptionsError("Unsupported repo module %s, choices are %s" % (self.options.module_name, ','.join(self.SUPPORTED_REPO_MODULES)))
|
||||
if options.module_name not in self.SUPPORTED_REPO_MODULES:
|
||||
raise AnsibleOptionsError("Unsupported repo module %s, choices are %s" % (options.module_name, ','.join(self.SUPPORTED_REPO_MODULES)))
|
||||
|
||||
display.verbosity = self.options.verbosity
|
||||
self.validate_conflicts(vault_opts=True)
|
||||
display.verbosity = options.verbosity
|
||||
self.validate_conflicts(options, vault_opts=True)
|
||||
|
||||
return options, args
|
||||
|
||||
def run(self):
|
||||
''' use Runner lib to do SSH things '''
|
||||
|
@ -169,8 +162,8 @@ class PullCLI(CLI):
|
|||
host = socket.getfqdn()
|
||||
limit_opts = 'localhost,%s,127.0.0.1' % ','.join(set([host, node, host.split('.')[0], node.split('.')[0]]))
|
||||
base_opts = '-c local '
|
||||
if self.options.verbosity > 0:
|
||||
base_opts += ' -%s' % ''.join(["v" for x in range(0, self.options.verbosity)])
|
||||
if context.CLIARGS['verbosity'] > 0:
|
||||
base_opts += ' -%s' % ''.join(["v" for x in range(0, context.CLIARGS['verbosity'])])
|
||||
|
||||
# Attempt to use the inventory passed in as an argument
|
||||
# It might not yet have been downloaded so use localhost as default
|
||||
|
@ -179,61 +172,65 @@ class PullCLI(CLI):
|
|||
inv_opts = " -i localhost, "
|
||||
|
||||
# SCM specific options
|
||||
if self.options.module_name == 'git':
|
||||
repo_opts = "name=%s dest=%s" % (self.options.url, self.options.dest)
|
||||
if self.options.checkout:
|
||||
repo_opts += ' version=%s' % self.options.checkout
|
||||
if context.CLIARGS['module_name'] == 'git':
|
||||
repo_opts = "name=%s dest=%s" % (context.CLIARGS['url'], context.CLIARGS['dest'])
|
||||
if context.CLIARGS['checkout']:
|
||||
repo_opts += ' version=%s' % context.CLIARGS['checkout']
|
||||
|
||||
if self.options.accept_host_key:
|
||||
if context.CLIARGS['accept_host_key']:
|
||||
repo_opts += ' accept_hostkey=yes'
|
||||
|
||||
if self.options.private_key_file:
|
||||
repo_opts += ' key_file=%s' % self.options.private_key_file
|
||||
if context.CLIARGS['private_key_file']:
|
||||
repo_opts += ' key_file=%s' % context.CLIARGS['private_key_file']
|
||||
|
||||
if self.options.verify:
|
||||
if context.CLIARGS['verify']:
|
||||
repo_opts += ' verify_commit=yes'
|
||||
|
||||
if self.options.tracksubs:
|
||||
if context.CLIARGS['tracksubs']:
|
||||
repo_opts += ' track_submodules=yes'
|
||||
|
||||
if not self.options.fullclone:
|
||||
if not context.CLIARGS['fullclone']:
|
||||
repo_opts += ' depth=1'
|
||||
elif self.options.module_name == 'subversion':
|
||||
repo_opts = "repo=%s dest=%s" % (self.options.url, self.options.dest)
|
||||
if self.options.checkout:
|
||||
repo_opts += ' revision=%s' % self.options.checkout
|
||||
if not self.options.fullclone:
|
||||
elif context.CLIARGS['module_name'] == 'subversion':
|
||||
repo_opts = "repo=%s dest=%s" % (context.CLIARGS['url'], context.CLIARGS['dest'])
|
||||
if context.CLIARGS['checkout']:
|
||||
repo_opts += ' revision=%s' % context.CLIARGS['checkout']
|
||||
if not context.CLIARGS['fullclone']:
|
||||
repo_opts += ' export=yes'
|
||||
elif self.options.module_name == 'hg':
|
||||
repo_opts = "repo=%s dest=%s" % (self.options.url, self.options.dest)
|
||||
if self.options.checkout:
|
||||
repo_opts += ' revision=%s' % self.options.checkout
|
||||
elif self.options.module_name == 'bzr':
|
||||
repo_opts = "name=%s dest=%s" % (self.options.url, self.options.dest)
|
||||
if self.options.checkout:
|
||||
repo_opts += ' version=%s' % self.options.checkout
|
||||
elif context.CLIARGS['module_name'] == 'hg':
|
||||
repo_opts = "repo=%s dest=%s" % (context.CLIARGS['url'], context.CLIARGS['dest'])
|
||||
if context.CLIARGS['checkout']:
|
||||
repo_opts += ' revision=%s' % context.CLIARGS['checkout']
|
||||
elif context.CLIARGS['module_name'] == 'bzr':
|
||||
repo_opts = "name=%s dest=%s" % (context.CLIARGS['url'], context.CLIARGS['dest'])
|
||||
if context.CLIARGS['checkout']:
|
||||
repo_opts += ' version=%s' % context.CLIARGS['checkout']
|
||||
else:
|
||||
raise AnsibleOptionsError('Unsupported (%s) SCM module for pull, choices are: %s' % (self.options.module_name, ','.join(self.REPO_CHOICES)))
|
||||
raise AnsibleOptionsError('Unsupported (%s) SCM module for pull, choices are: %s'
|
||||
% (context.CLIARGS['module_name'],
|
||||
','.join(self.REPO_CHOICES)))
|
||||
|
||||
# options common to all supported SCMS
|
||||
if self.options.clean:
|
||||
if context.CLIARGS['clean']:
|
||||
repo_opts += ' force=yes'
|
||||
|
||||
path = module_loader.find_plugin(self.options.module_name)
|
||||
path = module_loader.find_plugin(context.CLIARGS['module_name'])
|
||||
if path is None:
|
||||
raise AnsibleOptionsError(("module '%s' not found.\n" % self.options.module_name))
|
||||
raise AnsibleOptionsError(("module '%s' not found.\n" % context.CLIARGS['module_name']))
|
||||
|
||||
bin_path = os.path.dirname(os.path.abspath(sys.argv[0]))
|
||||
# hardcode local and inventory/host as this is just meant to fetch the repo
|
||||
cmd = '%s/ansible %s %s -m %s -a "%s" all -l "%s"' % (bin_path, inv_opts, base_opts, self.options.module_name, repo_opts, limit_opts)
|
||||
cmd = '%s/ansible %s %s -m %s -a "%s" all -l "%s"' % (bin_path, inv_opts, base_opts,
|
||||
context.CLIARGS['module_name'],
|
||||
repo_opts, limit_opts)
|
||||
|
||||
for ev in self.options.extra_vars:
|
||||
for ev in context.CLIARGS['extra_vars']:
|
||||
cmd += ' -e "%s"' % ev
|
||||
|
||||
# Nap?
|
||||
if self.options.sleep:
|
||||
display.display("Sleeping for %d seconds..." % self.options.sleep)
|
||||
time.sleep(self.options.sleep)
|
||||
if context.CLIARGS['sleep']:
|
||||
display.display("Sleeping for %d seconds..." % context.CLIARGS['sleep'])
|
||||
time.sleep(context.CLIARGS['sleep'])
|
||||
|
||||
# RUN the Checkout command
|
||||
display.debug("running ansible with VCS module to checkout repo")
|
||||
|
@ -241,45 +238,45 @@ class PullCLI(CLI):
|
|||
rc, b_out, b_err = run_cmd(cmd, live=True)
|
||||
|
||||
if rc != 0:
|
||||
if self.options.force:
|
||||
if context.CLIARGS['force']:
|
||||
display.warning("Unable to update repository. Continuing with (forced) run of playbook.")
|
||||
else:
|
||||
return rc
|
||||
elif self.options.ifchanged and b'"changed": true' not in b_out:
|
||||
elif context.CLIARGS['ifchanged'] and b'"changed": true' not in b_out:
|
||||
display.display("Repository has not changed, quitting.")
|
||||
return 0
|
||||
|
||||
playbook = self.select_playbook(self.options.dest)
|
||||
playbook = self.select_playbook(context.CLIARGS['dest'])
|
||||
if playbook is None:
|
||||
raise AnsibleOptionsError("Could not find a playbook to run.")
|
||||
|
||||
# Build playbook command
|
||||
cmd = '%s/ansible-playbook %s %s' % (bin_path, base_opts, playbook)
|
||||
if self.options.vault_password_files:
|
||||
for vault_password_file in self.options.vault_password_files:
|
||||
if context.CLIARGS['vault_password_files']:
|
||||
for vault_password_file in context.CLIARGS['vault_password_files']:
|
||||
cmd += " --vault-password-file=%s" % vault_password_file
|
||||
if self.options.vault_ids:
|
||||
for vault_id in self.options.vault_ids:
|
||||
if context.CLIARGS['vault_ids']:
|
||||
for vault_id in context.CLIARGS['vault_ids']:
|
||||
cmd += " --vault-id=%s" % vault_id
|
||||
|
||||
for ev in self.options.extra_vars:
|
||||
for ev in context.CLIARGS['extra_vars']:
|
||||
cmd += ' -e "%s"' % ev
|
||||
if self.options.ask_sudo_pass or self.options.ask_su_pass or self.options.become_ask_pass:
|
||||
if context.CLIARGS['ask_sudo_pass'] or context.CLIARGS['ask_su_pass'] or context.CLIARGS['become_ask_pass']:
|
||||
cmd += ' --ask-become-pass'
|
||||
if self.options.skip_tags:
|
||||
cmd += ' --skip-tags "%s"' % to_native(u','.join(self.options.skip_tags))
|
||||
if self.options.tags:
|
||||
cmd += ' -t "%s"' % to_native(u','.join(self.options.tags))
|
||||
if self.options.subset:
|
||||
cmd += ' -l "%s"' % self.options.subset
|
||||
if context.CLIARGS['skip_tags']:
|
||||
cmd += ' --skip-tags "%s"' % to_native(u','.join(context.CLIARGS['skip_tags']))
|
||||
if context.CLIARGS['tags']:
|
||||
cmd += ' -t "%s"' % to_native(u','.join(context.CLIARGS['tags']))
|
||||
if context.CLIARGS['subset']:
|
||||
cmd += ' -l "%s"' % context.CLIARGS['subset']
|
||||
else:
|
||||
cmd += ' -l "%s"' % limit_opts
|
||||
if self.options.check:
|
||||
if context.CLIARGS['check']:
|
||||
cmd += ' -C'
|
||||
if self.options.diff:
|
||||
if context.CLIARGS['diff']:
|
||||
cmd += ' -D'
|
||||
|
||||
os.chdir(self.options.dest)
|
||||
os.chdir(context.CLIARGS['dest'])
|
||||
|
||||
# redo inventory options as new files might exist now
|
||||
inv_opts = self._get_inv_cli()
|
||||
|
@ -291,12 +288,12 @@ class PullCLI(CLI):
|
|||
display.debug('EXEC: %s' % cmd)
|
||||
rc, b_out, b_err = run_cmd(cmd, live=True)
|
||||
|
||||
if self.options.purge:
|
||||
if context.CLIARGS['purge']:
|
||||
os.chdir('/')
|
||||
try:
|
||||
shutil.rmtree(self.options.dest)
|
||||
shutil.rmtree(context.CLIARGS['dest'])
|
||||
except Exception as e:
|
||||
display.error(u"Failed to remove %s: %s" % (self.options.dest, to_text(e)))
|
||||
display.error(u"Failed to remove %s: %s" % (context.CLIARGS['dest'], to_text(e)))
|
||||
|
||||
return rc
|
||||
|
||||
|
@ -309,8 +306,8 @@ class PullCLI(CLI):
|
|||
|
||||
def select_playbook(self, path):
|
||||
playbook = None
|
||||
if len(self.args) > 0 and self.args[0] is not None:
|
||||
playbook = os.path.join(path, self.args[0])
|
||||
if context.CLIARGS['args'] and context.CLIARGS['args'][0] is not None:
|
||||
playbook = os.path.join(path, context.CLIARGS['args'][0])
|
||||
rc = self.try_playbook(playbook)
|
||||
if rc != 0:
|
||||
display.warning("%s: %s" % (playbook, self.PLAYBOOK_ERRORS[rc]))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue