Collated PEP8 fixes (#25293)

- Make PEP8 compliant
This commit is contained in:
Dag Wieers 2017-06-02 13:14:11 +02:00 committed by John R Barker
commit 5553b20828
206 changed files with 1853 additions and 1870 deletions

View file

@ -20,25 +20,26 @@
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
import getpass
import operator import operator
import optparse import optparse
import os import os
import subprocess
import re
import sys import sys
import time import time
import yaml import yaml
import re
import getpass
import subprocess
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
import ansible import ansible
from ansible.release 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.inventory.manager import InventoryManager from ansible.inventory.manager import InventoryManager
from ansible.module_utils.six import with_metaclass, string_types from ansible.module_utils.six import with_metaclass, string_types
from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils._text import to_bytes, to_text
from ansible.parsing.dataloader import DataLoader from ansible.parsing.dataloader import DataLoader
from ansible.release import __version__
from ansible.utils.path import unfrackpath from ansible.utils.path import unfrackpath
from ansible.utils.vars import load_extra_vars, load_options_vars from ansible.utils.vars import load_extra_vars, load_options_vars
from ansible.vars.manager import VariableManager from ansible.vars.manager import VariableManager
@ -79,7 +80,7 @@ class InvalidOptsParser(SortedOptParser):
add_help_option=False, add_help_option=False,
prog=parser.prog, prog=parser.prog,
epilog=parser.epilog) epilog=parser.epilog)
self.version=parser.version self.version = parser.version
def _process_long_opt(self, rargs, values): def _process_long_opt(self, rargs, values):
try: try:
@ -93,18 +94,19 @@ class InvalidOptsParser(SortedOptParser):
except optparse.BadOptionError: except optparse.BadOptionError:
pass pass
class CLI(with_metaclass(ABCMeta, object)): class CLI(with_metaclass(ABCMeta, object)):
''' code behind bin/ansible* programs ''' ''' code behind bin/ansible* programs '''
VALID_ACTIONS = [] VALID_ACTIONS = []
_ITALIC = re.compile(r"I\(([^)]+)\)") _ITALIC = re.compile(r"I\(([^)]+)\)")
_BOLD = re.compile(r"B\(([^)]+)\)") _BOLD = re.compile(r"B\(([^)]+)\)")
_MODULE = re.compile(r"M\(([^)]+)\)") _MODULE = re.compile(r"M\(([^)]+)\)")
_URL = re.compile(r"U\(([^)]+)\)") _URL = re.compile(r"U\(([^)]+)\)")
_CONST = re.compile(r"C\(([^)]+)\)") _CONST = re.compile(r"C\(([^)]+)\)")
PAGER = 'less' PAGER = 'less'
# -F (quit-if-one-screen) -R (allow raw ansi control chars) # -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)
@ -229,7 +231,7 @@ class CLI(with_metaclass(ABCMeta, object)):
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
self.options.become_user = self.options.become_user or self.options.sudo_user or self.options.su_user or C.DEFAULT_BECOME_USER self.options.become_user = self.options.become_user or self.options.sudo_user or self.options.su_user or C.DEFAULT_BECOME_USER
if self.options.become: if self.options.become:
pass pass
@ -287,78 +289,79 @@ class CLI(with_metaclass(ABCMeta, 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,
runas_prompt_opts=False, desc=None): runas_prompt_opts=False, desc=None):
''' create an options parser for most ansible scripts ''' ''' create an options parser for most ansible scripts '''
# base opts # base opts
parser = SortedOptParser(usage, version=CLI.version("%prog"), description=desc, epilog=epilog) parser = SortedOptParser(usage, version=CLI.version("%prog"), description=desc, epilog=epilog)
parser.add_option('-v','--verbose', dest='verbosity', default=C.DEFAULT_VERBOSITY, action="count", parser.add_option('-v', '--verbose', dest='verbosity', default=C.DEFAULT_VERBOSITY, action="count",
help="verbose mode (-vvv for more, -vvvv to enable connection debugging)") help="verbose mode (-vvv for more, -vvvv to enable connection debugging)")
if inventory_opts: if inventory_opts:
parser.add_option('-i', '--inventory', '--inventory-file', dest='inventory', action="append", parser.add_option('-i', '--inventory', '--inventory-file', dest='inventory', action="append",
help="specify inventory host path (default=[%s]) or comma separated host list. --inventory-file is deprecated" % C.DEFAULT_HOST_LIST) help="specify inventory host path (default=[%s]) or comma separated host list. "
"--inventory-file is deprecated" % C.DEFAULT_HOST_LIST)
parser.add_option('--list-hosts', dest='listhosts', action='store_true', parser.add_option('--list-hosts', dest='listhosts', action='store_true',
help='outputs a list of matching hosts; does not execute anything else') help='outputs a list of matching hosts; does not execute anything else')
parser.add_option('-l', '--limit', default=C.DEFAULT_SUBSET, dest='subset', parser.add_option('-l', '--limit', default=C.DEFAULT_SUBSET, dest='subset',
help='further limit selected hosts to an additional pattern') help='further limit selected hosts to an additional pattern')
if module_opts: if module_opts:
parser.add_option('-M', '--module-path', dest='module_path', default=None, parser.add_option('-M', '--module-path', dest='module_path', default=None,
help="prepend path(s) to module library (default=%s)" % C.DEFAULT_MODULE_PATH, help="prepend path(s) to module library (default=%s)" % C.DEFAULT_MODULE_PATH,
action="callback", callback=CLI.expand_tilde, type=str) action="callback", callback=CLI.expand_tilde, type=str)
if runtask_opts: if runtask_opts:
parser.add_option('-e', '--extra-vars', dest="extra_vars", action="append", parser.add_option('-e', '--extra-vars', dest="extra_vars", action="append",
help="set additional variables as key=value or YAML/JSON", default=[]) help="set additional variables as key=value or YAML/JSON", default=[])
if fork_opts: if fork_opts:
parser.add_option('-f','--forks', dest='forks', default=C.DEFAULT_FORKS, type='int', parser.add_option('-f', '--forks', dest='forks', default=C.DEFAULT_FORKS, type='int',
help="specify number of parallel processes to use (default=%s)" % C.DEFAULT_FORKS) help="specify number of parallel processes to use (default=%s)" % C.DEFAULT_FORKS)
if vault_opts: if vault_opts:
parser.add_option('--ask-vault-pass', default=C.DEFAULT_ASK_VAULT_PASS, dest='ask_vault_pass', action='store_true', parser.add_option('--ask-vault-pass', default=C.DEFAULT_ASK_VAULT_PASS, dest='ask_vault_pass', action='store_true',
help='ask for vault password') help='ask for vault password')
parser.add_option('--vault-password-file', default=C.DEFAULT_VAULT_PASSWORD_FILE, dest='vault_password_file', parser.add_option('--vault-password-file', default=C.DEFAULT_VAULT_PASSWORD_FILE, dest='vault_password_file',
help="vault password file", action="callback", callback=CLI.unfrack_path, type='string') help="vault password file", action="callback", callback=CLI.unfrack_path, type='string')
parser.add_option('--new-vault-password-file', dest='new_vault_password_file', parser.add_option('--new-vault-password-file', dest='new_vault_password_file',
help="new vault password file for rekey", action="callback", callback=CLI.unfrack_path, type='string') help="new vault password file for rekey", action="callback", callback=CLI.unfrack_path, type='string')
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',
action="callback", callback=CLI.unfrack_path, type='string') action="callback", callback=CLI.unfrack_path, type='string')
if subset_opts: if subset_opts:
parser.add_option('-t', '--tags', dest='tags', default=[], action='append', parser.add_option('-t', '--tags', dest='tags', default=[], action='append',
help="only run plays and tasks tagged with these values") help="only run plays and tasks tagged with these values")
parser.add_option('--skip-tags', dest='skip_tags', default=[], action='append', parser.add_option('--skip-tags', dest='skip_tags', default=[], action='append',
help="only run plays and tasks whose tags do not match these values") help="only run plays and tasks whose tags do not match these values")
if output_opts: if output_opts:
parser.add_option('-o', '--one-line', dest='one_line', action='store_true', parser.add_option('-o', '--one-line', dest='one_line', action='store_true',
help='condense output') help='condense output')
parser.add_option('-t', '--tree', dest='tree', default=None, parser.add_option('-t', '--tree', dest='tree', default=None,
help='log output to this directory') help='log output to this directory')
if connect_opts: if connect_opts:
connect_group = optparse.OptionGroup(parser, "Connection Options", "control as whom and how to connect to hosts") connect_group = optparse.OptionGroup(parser, "Connection Options", "control as whom and how to connect to hosts")
connect_group.add_option('-k', '--ask-pass', default=C.DEFAULT_ASK_PASS, dest='ask_pass', action='store_true', connect_group.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')
connect_group.add_option('--private-key','--key-file', default=C.DEFAULT_PRIVATE_KEY_FILE, dest='private_key_file', connect_group.add_option('--private-key', '--key-file', default=C.DEFAULT_PRIVATE_KEY_FILE, dest='private_key_file',
help='use this file to authenticate the connection', action="callback", callback=CLI.unfrack_path, type='string') help='use this file to authenticate the connection', action="callback", callback=CLI.unfrack_path, type='string')
connect_group.add_option('-u', '--user', default=C.DEFAULT_REMOTE_USER, dest='remote_user', connect_group.add_option('-u', '--user', default=C.DEFAULT_REMOTE_USER, dest='remote_user',
help='connect as this user (default=%s)' % C.DEFAULT_REMOTE_USER) help='connect as this user (default=%s)' % C.DEFAULT_REMOTE_USER)
connect_group.add_option('-c', '--connection', dest='connection', default=C.DEFAULT_TRANSPORT, connect_group.add_option('-c', '--connection', dest='connection', default=C.DEFAULT_TRANSPORT,
help="connection type to use (default=%s)" % C.DEFAULT_TRANSPORT) help="connection type to use (default=%s)" % C.DEFAULT_TRANSPORT)
connect_group.add_option('-T', '--timeout', default=C.DEFAULT_TIMEOUT, type='int', dest='timeout', connect_group.add_option('-T', '--timeout', default=C.DEFAULT_TIMEOUT, type='int', dest='timeout',
help="override the connection timeout in seconds (default=%s)" % C.DEFAULT_TIMEOUT) help="override the connection timeout in seconds (default=%s)" % C.DEFAULT_TIMEOUT)
connect_group.add_option('--ssh-common-args', default='', dest='ssh_common_args', connect_group.add_option('--ssh-common-args', default='', dest='ssh_common_args',
help="specify common arguments to pass to sftp/scp/ssh (e.g. ProxyCommand)") help="specify common arguments to pass to sftp/scp/ssh (e.g. ProxyCommand)")
connect_group.add_option('--sftp-extra-args', default='', dest='sftp_extra_args', connect_group.add_option('--sftp-extra-args', default='', dest='sftp_extra_args',
help="specify extra arguments to pass to sftp only (e.g. -f, -l)") help="specify extra arguments to pass to sftp only (e.g. -f, -l)")
connect_group.add_option('--scp-extra-args', default='', dest='scp_extra_args', connect_group.add_option('--scp-extra-args', default='', dest='scp_extra_args',
help="specify extra arguments to pass to scp only (e.g. -l)") help="specify extra arguments to pass to scp only (e.g. -l)")
connect_group.add_option('--ssh-extra-args', default='', dest='ssh_extra_args', connect_group.add_option('--ssh-extra-args', default='', dest='ssh_extra_args',
help="specify extra arguments to pass to ssh only (e.g. -R)") help="specify extra arguments to pass to ssh only (e.g. -R)")
parser.add_option_group(connect_group) parser.add_option_group(connect_group)
@ -368,54 +371,55 @@ class CLI(with_metaclass(ABCMeta, object)):
runas_group = rg runas_group = rg
# priv user defaults to root later on to enable detecting when this option was given here # priv user defaults to root later on to enable detecting when this option was given here
runas_group.add_option("-s", "--sudo", default=C.DEFAULT_SUDO, action="store_true", dest='sudo', runas_group.add_option("-s", "--sudo", default=C.DEFAULT_SUDO, action="store_true", dest='sudo',
help="run operations with sudo (nopasswd) (deprecated, use become)") help="run operations with sudo (nopasswd) (deprecated, use become)")
runas_group.add_option('-U', '--sudo-user', dest='sudo_user', default=None, runas_group.add_option('-U', '--sudo-user', dest='sudo_user', default=None,
help='desired sudo user (default=root) (deprecated, use become)') help='desired sudo user (default=root) (deprecated, use become)')
runas_group.add_option('-S', '--su', default=C.DEFAULT_SU, action='store_true', runas_group.add_option('-S', '--su', default=C.DEFAULT_SU, action='store_true',
help='run operations with su (deprecated, use become)') help='run operations with su (deprecated, use become)')
runas_group.add_option('-R', '--su-user', default=None, runas_group.add_option('-R', '--su-user', default=None,
help='run operations with su as this user (default=%s) (deprecated, use become)' % C.DEFAULT_SU_USER) help='run operations with su as this user (default=%s) (deprecated, use become)' % C.DEFAULT_SU_USER)
# consolidated privilege escalation (become) # consolidated privilege escalation (become)
runas_group.add_option("-b", "--become", default=C.DEFAULT_BECOME, action="store_true", dest='become', runas_group.add_option("-b", "--become", default=C.DEFAULT_BECOME, action="store_true", dest='become',
help="run operations with become (does not imply password prompting)") help="run operations with become (does not imply password prompting)")
runas_group.add_option('--become-method', dest='become_method', default=C.DEFAULT_BECOME_METHOD, type='choice', choices=C.BECOME_METHODS, runas_group.add_option('--become-method', dest='become_method', default=C.DEFAULT_BECOME_METHOD, type='choice', choices=C.BECOME_METHODS,
help="privilege escalation method to use (default=%s), valid choices: [ %s ]" % (C.DEFAULT_BECOME_METHOD, ' | '.join(C.BECOME_METHODS))) help="privilege escalation method to use (default=%s), valid choices: [ %s ]" %
(C.DEFAULT_BECOME_METHOD, ' | '.join(C.BECOME_METHODS)))
runas_group.add_option('--become-user', default=None, dest='become_user', type='string', runas_group.add_option('--become-user', default=None, dest='become_user', type='string',
help='run operations as this user (default=%s)' % C.DEFAULT_BECOME_USER) help='run operations as this user (default=%s)' % C.DEFAULT_BECOME_USER)
if runas_opts or runas_prompt_opts: if runas_opts or runas_prompt_opts:
if not runas_group: if not runas_group:
runas_group = rg runas_group = rg
runas_group.add_option('--ask-sudo-pass', default=C.DEFAULT_ASK_SUDO_PASS, dest='ask_sudo_pass', action='store_true', runas_group.add_option('--ask-sudo-pass', default=C.DEFAULT_ASK_SUDO_PASS, dest='ask_sudo_pass', action='store_true',
help='ask for sudo password (deprecated, use become)') help='ask for sudo password (deprecated, use become)')
runas_group.add_option('--ask-su-pass', default=C.DEFAULT_ASK_SU_PASS, dest='ask_su_pass', action='store_true', runas_group.add_option('--ask-su-pass', default=C.DEFAULT_ASK_SU_PASS, dest='ask_su_pass', action='store_true',
help='ask for su password (deprecated, use become)') help='ask for su password (deprecated, use become)')
runas_group.add_option('-K', '--ask-become-pass', default=False, dest='become_ask_pass', action='store_true', runas_group.add_option('-K', '--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 runas_group: if runas_group:
parser.add_option_group(runas_group) parser.add_option_group(runas_group)
if async_opts: if async_opts:
parser.add_option('-P', '--poll', default=C.DEFAULT_POLL_INTERVAL, type='int', dest='poll_interval', parser.add_option('-P', '--poll', default=C.DEFAULT_POLL_INTERVAL, type='int', dest='poll_interval',
help="set the poll interval if using -B (default=%s)" % C.DEFAULT_POLL_INTERVAL) help="set the poll interval if using -B (default=%s)" % C.DEFAULT_POLL_INTERVAL)
parser.add_option('-B', '--background', dest='seconds', type='int', default=0, parser.add_option('-B', '--background', dest='seconds', type='int', default=0,
help='run asynchronously, failing after X seconds (default=N/A)') help='run asynchronously, failing after X seconds (default=N/A)')
if check_opts: if check_opts:
parser.add_option("-C", "--check", default=False, dest='check', action='store_true', parser.add_option("-C", "--check", default=False, dest='check', action='store_true',
help="don't make any changes; instead, try to predict some of the changes that may occur") help="don't make any changes; instead, try to predict some of the changes that may occur")
parser.add_option('--syntax-check', dest='syntax', action='store_true', parser.add_option('--syntax-check', dest='syntax', action='store_true',
help="perform a syntax check on the playbook, but do not execute it") help="perform a syntax check on the playbook, but do not execute it")
parser.add_option("-D", "--diff", default=False, dest='diff', action='store_true', parser.add_option("-D", "--diff", default=False, dest='diff', action='store_true',
help="when changing (small) files and templates, show the differences in those files; works great with --check") help="when changing (small) files and templates, show the differences in those files; works great with --check")
if meta_opts: if meta_opts:
parser.add_option('--force-handlers', default=C.DEFAULT_FORCE_HANDLERS, dest='force_handlers', action='store_true', parser.add_option('--force-handlers', default=C.DEFAULT_FORCE_HANDLERS, dest='force_handlers', action='store_true',
help="run handlers even if a task fails") help="run handlers even if a task fails")
parser.add_option('--flush-cache', dest='flush_cache', action='store_true', parser.add_option('--flush-cache', dest='flush_cache', action='store_true',
help="clear the fact cache") help="clear the fact cache")
return parser return parser
@ -491,7 +495,7 @@ class CLI(with_metaclass(ABCMeta, object)):
else: else:
# set default if it exists # set default if it exists
if os.path.exists(C.DEFAULT_HOST_LIST): if os.path.exists(C.DEFAULT_HOST_LIST):
self.options.inventory = [ C.DEFAULT_HOST_LIST ] self.options.inventory = [C.DEFAULT_HOST_LIST]
@staticmethod @staticmethod
def version(prog): def version(prog):
@ -531,11 +535,11 @@ class CLI(with_metaclass(ABCMeta, object)):
if len(ansible_versions) < 3: if len(ansible_versions) < 3:
for counter in range(len(ansible_versions), 3): for counter in range(len(ansible_versions), 3):
ansible_versions.append(0) ansible_versions.append(0)
return {'string': ansible_version_string.strip(), return {'string': ansible_version_string.strip(),
'full': ansible_version, 'full': ansible_version,
'major': ansible_versions[0], 'major': ansible_versions[0],
'minor': ansible_versions[1], 'minor': ansible_versions[1],
'revision': ansible_versions[2]} 'revision': ansible_versions[2]}
@staticmethod @staticmethod
def _git_repo_info(repo_path): def _git_repo_info(repo_path):
@ -576,8 +580,7 @@ class CLI(with_metaclass(ABCMeta, object)):
offset = time.timezone offset = time.timezone
else: else:
offset = time.altzone offset = time.altzone
result = "({0} {1}) last updated {2} (GMT {3:+04d})".format(branch, commit, result = "({0} {1}) last updated {2} (GMT {3:+04d})".format(branch, commit, time.strftime("%Y/%m/%d %H:%M:%S", date), int(offset / -36))
time.strftime("%Y/%m/%d %H:%M:%S", date), int(offset / -36))
else: else:
result = '' result = ''
return result return result
@ -669,7 +672,7 @@ class CLI(with_metaclass(ABCMeta, object)):
else: else:
try: try:
f = open(this_path, "rb") f = open(this_path, "rb")
vault_pass=f.read().strip() vault_pass = f.read().strip()
f.close() f.close()
except (OSError, IOError) as e: except (OSError, IOError) as e:
raise AnsibleError("Could not read vault password file %s: %s" % (this_path, e)) raise AnsibleError("Could not read vault password file %s: %s" % (this_path, e))
@ -705,4 +708,3 @@ class CLI(with_metaclass(ABCMeta, object)):
variable_manager.options_vars = load_options_vars(options, CLI.version_info(gitinfo=False)) variable_manager.options_vars = load_options_vars(options, CLI.version_info(gitinfo=False))
return loader, inventory, variable_manager return loader, inventory, variable_manager

View file

@ -66,10 +66,10 @@ class AdHocCLI(CLI):
# options unique to ansible ad-hoc # options unique to ansible ad-hoc
self.parser.add_option('-a', '--args', dest='module_args', self.parser.add_option('-a', '--args', dest='module_args',
help="module arguments", default=C.DEFAULT_MODULE_ARGS) help="module arguments", default=C.DEFAULT_MODULE_ARGS)
self.parser.add_option('-m', '--module-name', dest='module_name', self.parser.add_option('-m', '--module-name', dest='module_name',
help="module name to execute (default=%s)" % C.DEFAULT_MODULE_NAME, help="module name to execute (default=%s)" % C.DEFAULT_MODULE_NAME,
default=C.DEFAULT_MODULE_NAME) default=C.DEFAULT_MODULE_NAME)
super(AdHocCLI, self).parse() super(AdHocCLI, self).parse()
@ -84,10 +84,10 @@ class AdHocCLI(CLI):
def _play_ds(self, pattern, async, poll): def _play_ds(self, pattern, async, poll):
check_raw = self.options.module_name in ('command', 'win_command', 'shell', 'win_shell', 'script', 'raw') check_raw = self.options.module_name in ('command', 'win_command', 'shell', 'win_shell', 'script', 'raw')
return dict( return dict(
name = "Ansible Ad-Hoc", name="Ansible Ad-Hoc",
hosts = pattern, hosts=pattern,
gather_facts = 'no', gather_facts='no',
tasks = [ dict(action=dict(module=self.options.module_name, args=parse_kv(self.options.module_args, check_raw=check_raw)), async=async, poll=poll) ] tasks=[dict(action=dict(module=self.options.module_name, args=parse_kv(self.options.module_args, check_raw=check_raw)), async=async, poll=poll)]
) )
def run(self): def run(self):
@ -98,12 +98,12 @@ class AdHocCLI(CLI):
# only thing left should be host pattern # only thing left should be host pattern
pattern = to_text(self.args[0], errors='surrogate_or_strict') pattern = to_text(self.args[0], errors='surrogate_or_strict')
sshpass = None sshpass = None
becomepass = None becomepass = None
self.normalize_become_options() self.normalize_become_options()
(sshpass, becomepass) = self.ask_passwords() (sshpass, becomepass) = self.ask_passwords()
passwords = { 'conn_pass': sshpass, 'become_pass': becomepass } passwords = {'conn_pass': sshpass, 'become_pass': becomepass}
loader, inventory, variable_manager = self._play_prereqs(self.options) loader, inventory, variable_manager = self._play_prereqs(self.options)
@ -155,11 +155,11 @@ class AdHocCLI(CLI):
else: else:
cb = 'minimal' cb = 'minimal'
run_tree=False run_tree = False
if self.options.tree: if self.options.tree:
C.DEFAULT_CALLBACK_WHITELIST.append('tree') C.DEFAULT_CALLBACK_WHITELIST.append('tree')
C.TREE_DIR = self.options.tree C.TREE_DIR = self.options.tree
run_tree=True run_tree = True
# now create a task queue manager to execute the play # now create a task queue manager to execute the play
self._tqm = None self._tqm = None

View file

@ -58,8 +58,8 @@ class ConsoleCLI(CLI, cmd.Cmd):
''' a REPL that allows for running ad-hoc tasks against a chosen inventory (based on dominis' ansible-shell).''' ''' a REPL that allows for running ad-hoc tasks against a chosen inventory (based on dominis' ansible-shell).'''
modules = [] modules = []
ARGUMENTS = { 'host-pattern': 'A name of a group in the inventory, a shell-like glob ' ARGUMENTS = {'host-pattern': 'A name of a group in the inventory, a shell-like glob '
'selecting hosts in inventory or any combination of the two separated by commas.', } 'selecting hosts in inventory or any combination of the two separated by commas.'}
def __init__(self, args): def __init__(self, args):
@ -93,7 +93,7 @@ class ConsoleCLI(CLI, cmd.Cmd):
# options unique to shell # options unique to shell
self.parser.add_option('--step', dest='step', action='store_true', self.parser.add_option('--step', dest='step', action='store_true',
help="one-step-at-a-time: confirm each task before running") help="one-step-at-a-time: confirm each task before running")
self.parser.set_defaults(cwd='*') self.parser.set_defaults(cwd='*')
@ -150,7 +150,7 @@ class ConsoleCLI(CLI, cmd.Cmd):
elif module in C.IGNORE_FILES: elif module in C.IGNORE_FILES:
continue continue
elif module.startswith('_'): elif module.startswith('_'):
fullpath = '/'.join([path,module]) fullpath = '/'.join([path, module])
if os.path.islink(fullpath): # avoids aliases if os.path.islink(fullpath): # avoids aliases
continue continue
module = module.replace('_', '', 1) module = module.replace('_', '', 1)
@ -184,10 +184,10 @@ class ConsoleCLI(CLI, cmd.Cmd):
try: try:
check_raw = self.options.module_name in ('command', 'shell', 'script', 'raw') check_raw = self.options.module_name in ('command', 'shell', 'script', 'raw')
play_ds = dict( play_ds = dict(
name = "Ansible Shell", name="Ansible Shell",
hosts = self.options.cwd, hosts=self.options.cwd,
gather_facts = 'no', gather_facts='no',
tasks = [ dict(action=dict(module=module, args=parse_kv(module_args, check_raw=check_raw)))] tasks=[dict(action=dict(module=module, args=parse_kv(module_args, check_raw=check_raw)))]
) )
play = Play().load(play_ds, variable_manager=self.variable_manager, loader=self.loader) play = Play().load(play_ds, variable_manager=self.variable_manager, loader=self.loader)
except Exception as e: except Exception as e:
@ -368,7 +368,7 @@ class ConsoleCLI(CLI, cmd.Cmd):
mline = line.partition(' ')[2] mline = line.partition(' ')[2]
offs = len(mline) - len(text) offs = len(mline) - len(text)
if self.options.cwd in ('all','*','\\'): if self.options.cwd in ('all', '*', '\\'):
completions = self.hosts + self.groups completions = self.hosts + self.groups
else: else:
completions = [x.name for x in self.inventory.list_hosts(self.options.cwd)] completions = [x.name for x in self.inventory.list_hosts(self.options.cwd)]
@ -392,7 +392,7 @@ class ConsoleCLI(CLI, cmd.Cmd):
super(ConsoleCLI, self).run() super(ConsoleCLI, self).run()
sshpass = None sshpass = None
becomepass = None becomepass = None
# hosts # hosts
@ -410,7 +410,7 @@ class ConsoleCLI(CLI, cmd.Cmd):
self.normalize_become_options() self.normalize_become_options()
(sshpass, becomepass) = self.ask_passwords() (sshpass, becomepass) = self.ask_passwords()
self.passwords = { 'conn_pass': sshpass, 'become_pass': becomepass } self.passwords = {'conn_pass': sshpass, 'become_pass': becomepass}
self.loader, self.inventory, self.variable_manager = self._play_prereqs(self.options) self.loader, self.inventory, self.variable_manager = self._play_prereqs(self.options)

View file

@ -21,8 +21,8 @@ __metaclass__ = type
import datetime import datetime
import os import os
import traceback
import textwrap import textwrap
import traceback
import yaml import yaml
from ansible import constants as C from ansible import constants as C
@ -60,13 +60,13 @@ class DocCLI(CLI):
) )
self.parser.add_option("-l", "--list", action="store_true", default=False, dest='list_dir', self.parser.add_option("-l", "--list", action="store_true", default=False, dest='list_dir',
help='List available plugins') help='List available plugins')
self.parser.add_option("-s", "--snippet", action="store_true", default=False, dest='show_snippet', self.parser.add_option("-s", "--snippet", action="store_true", default=False, dest='show_snippet',
help='Show playbook snippet for specified plugin(s)') help='Show playbook snippet for specified plugin(s)')
self.parser.add_option("-a", "--all", action="store_true", default=False, dest='all_plugins', self.parser.add_option("-a", "--all", action="store_true", default=False, dest='all_plugins',
help='Show documentation for all plugins') help='Show documentation for all plugins')
self.parser.add_option("-t", "--type", action="store", default='module', dest='type', type='choice', self.parser.add_option("-t", "--type", action="store", default='module', dest='type', type='choice',
help='Choose which plugin type', choices=['module','cache', 'connection', 'callback', 'lookup', 'strategy', 'inventory']) help='Choose which plugin type', choices=['cache', 'callback', 'connection', 'inventory', 'lookup', 'module', 'strategy'])
super(DocCLI, self).parse() super(DocCLI, self).parse()
@ -90,7 +90,7 @@ class DocCLI(CLI):
elif plugin_type == 'strategy': elif plugin_type == 'strategy':
loader = strategy_loader loader = strategy_loader
elif plugin_type == 'inventory': elif plugin_type == 'inventory':
loader = PluginLoader( 'InventoryModule', 'ansible.plugins.inventory', 'inventory_plugins', 'inventory_plugins') loader = PluginLoader('InventoryModule', 'ansible.plugins.inventory', 'inventory_plugins', 'inventory_plugins')
else: else:
loader = module_loader loader = module_loader
@ -141,9 +141,9 @@ class DocCLI(CLI):
if doc is not None: if doc is not None:
# assign from other sections # assign from other sections
doc['plainexamples'] = plainexamples doc['plainexamples'] = plainexamples
doc['returndocs'] = returndocs doc['returndocs'] = returndocs
doc['metadata'] = metadata doc['metadata'] = metadata
# generate extra data # generate extra data
if plugin_type == 'module': if plugin_type == 'module':
@ -152,9 +152,9 @@ class DocCLI(CLI):
doc['action'] = True doc['action'] = True
else: else:
doc['action'] = False doc['action'] = False
doc['filename'] = filename doc['filename'] = filename
doc['now_date'] = datetime.date.today().strftime('%Y-%m-%d') doc['now_date'] = datetime.date.today().strftime('%Y-%m-%d')
doc['docuri'] = doc[plugin_type].replace('_', '-') doc['docuri'] = doc[plugin_type].replace('_', '-')
if self.options.show_snippet and plugin_type == 'module': if self.options.show_snippet and plugin_type == 'module':
text += self.get_snippet_text(doc) text += self.get_snippet_text(doc)
@ -238,7 +238,7 @@ class DocCLI(CLI):
if len(desc) > linelimit: if len(desc) > linelimit:
desc = desc[:linelimit] + '...' desc = desc[:linelimit] + '...'
if plugin.startswith('_'): # Handle deprecated if plugin.startswith('_'): # Handle deprecated
deprecated.append("%-*s %-*.*s" % (displace, plugin[1:], linelimit, len(desc), desc)) deprecated.append("%-*s %-*.*s" % (displace, plugin[1:], linelimit, len(desc), desc))
else: else:
text.append("%-*s %-*.*s" % (displace, plugin, linelimit, len(desc), desc)) text.append("%-*s %-*.*s" % (displace, plugin, linelimit, len(desc), desc))
@ -309,7 +309,7 @@ class DocCLI(CLI):
text.append(textwrap.fill(CLI.tty_ify(opt['description']), limit, initial_indent=opt_indent, subsequent_indent=opt_indent)) text.append(textwrap.fill(CLI.tty_ify(opt['description']), limit, initial_indent=opt_indent, subsequent_indent=opt_indent))
del opt['description'] del opt['description']
aliases= '' aliases = ''
if 'aliases' in opt: if 'aliases' in opt:
choices = "(Aliases: " + ", ".join(str(i) for i in opt['aliases']) + ")" choices = "(Aliases: " + ", ".join(str(i) for i in opt['aliases']) + ")"
del opt['aliases'] del opt['aliases']
@ -319,7 +319,7 @@ class DocCLI(CLI):
del opt['choices'] del opt['choices']
default = '' default = ''
if 'default' in opt or not required: if 'default' in opt or not required:
default = "[Default: " + str(opt.pop('default', '(null)')) + "]" default = "[Default: " + str(opt.pop('default', '(null)')) + "]"
text.append(textwrap.fill(CLI.tty_ify(aliases + choices + default), limit, initial_indent=opt_indent, subsequent_indent=opt_indent)) text.append(textwrap.fill(CLI.tty_ify(aliases + choices + default), limit, initial_indent=opt_indent, subsequent_indent=opt_indent))
if 'options' in opt: if 'options' in opt:
@ -361,7 +361,7 @@ class DocCLI(CLI):
display.vv("Skipping %s key cuase we don't know how to handle eet" % k) display.vv("Skipping %s key cuase we don't know how to handle eet" % k)
def get_man_text(self, doc): def get_man_text(self, doc):
opt_indent=" " opt_indent = " "
text = [] text = []
text.append("> %s (%s)\n" % (doc[self.options.type].upper(), doc['filename'])) text.append("> %s (%s)\n" % (doc[self.options.type].upper(), doc['filename']))
pad = display.columns * 0.20 pad = display.columns * 0.20
@ -388,11 +388,11 @@ class DocCLI(CLI):
if 'notes' in doc and doc['notes'] and len(doc['notes']) > 0: if 'notes' in doc and doc['notes'] and len(doc['notes']) > 0:
text.append("Notes:") text.append("Notes:")
for note in doc['notes']: for note in doc['notes']:
text.append(textwrap.fill(CLI.tty_ify(note), limit-6, initial_indent=" * ", subsequent_indent=opt_indent)) text.append(textwrap.fill(CLI.tty_ify(note), limit - 6, initial_indent=" * ", subsequent_indent=opt_indent))
if 'requirements' in doc and doc['requirements'] is not None and len(doc['requirements']) > 0: if 'requirements' in doc and doc['requirements'] is not None and len(doc['requirements']) > 0:
req = ", ".join(doc['requirements']) req = ", ".join(doc['requirements'])
text.append("Requirements:%s\n" % textwrap.fill(CLI.tty_ify(req), limit-16, initial_indent=" ", subsequent_indent=opt_indent)) text.append("Requirements:%s\n" % textwrap.fill(CLI.tty_ify(req), limit - 16, initial_indent=" ", subsequent_indent=opt_indent))
if 'examples' in doc and len(doc['examples']) > 0: if 'examples' in doc and len(doc['examples']) > 0:
text.append("Example%s:\n" % ('' if len(doc['examples']) < 2 else 's')) text.append("Example%s:\n" % ('' if len(doc['examples']) < 2 else 's'))

View file

@ -23,11 +23,11 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
import os.path import os.path
import sys
import yaml
import time
import re import re
import shutil import shutil
import sys
import time
import yaml
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
@ -36,11 +36,11 @@ from ansible.cli import CLI
from ansible.errors import AnsibleError, AnsibleOptionsError from ansible.errors import AnsibleError, AnsibleOptionsError
from ansible.galaxy import Galaxy from ansible.galaxy import Galaxy
from ansible.galaxy.api import GalaxyAPI from ansible.galaxy.api import GalaxyAPI
from ansible.galaxy.role import GalaxyRole
from ansible.galaxy.login import GalaxyLogin from ansible.galaxy.login import GalaxyLogin
from ansible.galaxy.role import GalaxyRole
from ansible.galaxy.token import GalaxyToken from ansible.galaxy.token import GalaxyToken
from ansible.playbook.role.requirement import RoleRequirement
from ansible.module_utils._text import to_text from ansible.module_utils._text import to_text
from ansible.playbook.role.requirement import RoleRequirement
try: try:
from __main__ import display from __main__ import display
@ -52,7 +52,7 @@ except ImportError:
class GalaxyCLI(CLI): class GalaxyCLI(CLI):
'''command to manage Ansible roles in shared repostories, the default of which is Ansible Galaxy *https://galaxy.ansible.com*.''' '''command to manage Ansible roles in shared repostories, the default of which is Ansible Galaxy *https://galaxy.ansible.com*.'''
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")
VALID_ACTIONS = ("delete", "import", "info", "init", "install", "list", "login", "remove", "search", "setup") VALID_ACTIONS = ("delete", "import", "info", "init", "install", "list", "login", "remove", "search", "setup")
def __init__(self, args): def __init__(self, args):
@ -64,7 +64,6 @@ class GalaxyCLI(CLI):
super(GalaxyCLI, self).set_action() super(GalaxyCLI, self).set_action()
# specific to actions # specific to actions
if self.action == "delete": if self.action == "delete":
self.parser.set_usage("usage: %prog delete [options] github_user github_repo") self.parser.set_usage("usage: %prog delete [options] github_user github_repo")
@ -113,9 +112,9 @@ class GalaxyCLI(CLI):
# options that apply to more than one action # options that apply to more than one action
if self.action in ['init', 'info']: if self.action in ['init', 'info']:
self.parser.add_option( '--offline', dest='offline', default=False, action='store_true', help="Don't query the galaxy API when creating roles") self.parser.add_option('--offline', dest='offline', default=False, action='store_true', help="Don't query the galaxy API when creating roles")
if self.action not in ("delete","import","init","login","setup"): if self.action not in ("delete", "import", "init", "login", "setup"):
# NOTE: while the option type=str, the default is a list, and the # NOTE: while the option type=str, the default is a list, and the
# callback will set the value to a list. # callback will set the value to a list.
self.parser.add_option('-p', '--roles-path', dest='roles_path', action="callback", callback=CLI.expand_paths, type=str, self.parser.add_option('-p', '--roles-path', dest='roles_path', action="callback", callback=CLI.expand_paths, type=str,
@ -123,15 +122,15 @@ class GalaxyCLI(CLI):
help='The path to the directory containing your roles. The default is the roles_path configured in your ansible.cfg ' help='The path to the directory containing your roles. The default is the roles_path configured in your ansible.cfg '
'file (/etc/ansible/roles if not configured)') 'file (/etc/ansible/roles if not configured)')
if self.action in ("init","install"): if self.action in ("init", "install"):
self.parser.add_option('-f', '--force', dest='force', action='store_true', default=False, help='Force overwriting an existing role') self.parser.add_option('-f', '--force', dest='force', action='store_true', default=False, help='Force overwriting an existing role')
def parse(self): def parse(self):
''' create an options parser for bin/ansible ''' ''' create an options parser for bin/ansible '''
self.parser = CLI.base_parser( self.parser = CLI.base_parser(
usage = "usage: %%prog [%s] [--help] [options] ..." % "|".join(self.VALID_ACTIONS), usage="usage: %%prog [%s] [--help] [options] ..." % "|".join(self.VALID_ACTIONS),
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])
) )
# common # common
@ -190,8 +189,8 @@ class GalaxyCLI(CLI):
creates the skeleton framework of a role that complies with the galaxy metadata format. creates the skeleton framework of a role that complies with the galaxy metadata format.
""" """
init_path = self.get_opt('init_path', './') init_path = self.get_opt('init_path', './')
force = self.get_opt('force', False) force = self.get_opt('force', False)
role_skeleton = self.get_opt('role_skeleton', C.GALAXY_ROLE_SKELETON) role_skeleton = self.get_opt('role_skeleton', C.GALAXY_ROLE_SKELETON)
role_name = self.args.pop(0).strip() if self.args else None role_name = self.args.pop(0).strip() if self.args else None
@ -203,9 +202,9 @@ class GalaxyCLI(CLI):
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." 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." % role_path) "been modified there already." % role_path)
inject_data = dict( inject_data = dict(
role_name=role_name, role_name=role_name,
@ -292,12 +291,12 @@ class GalaxyCLI(CLI):
role_info.update(gr.metadata) role_info.update(gr.metadata)
req = RoleRequirement() req = RoleRequirement()
role_spec= req.role_yaml_parse({'role': role}) role_spec = req.role_yaml_parse({'role': role})
if role_spec: if role_spec:
role_info.update(role_spec) role_info.update(role_spec)
data = self._display_role_info(role_info) data = self._display_role_info(role_info)
### FIXME: This is broken in both 1.9 and 2.0 as # FIXME: This is broken in both 1.9 and 2.0 as
# _display_role_info() always returns something # _display_role_info() always returns something
if not data: if not data:
data = u"\n- the role %s was not found" % role data = u"\n- the role %s was not found" % role
@ -310,7 +309,7 @@ class GalaxyCLI(CLI):
can be a name (which will be downloaded via the galaxy API and github), or it can be a local .tar.gz file. can be a name (which will be downloaded via the galaxy API and github), or it can be a local .tar.gz file.
""" """
role_file = self.get_opt("role_file", None) role_file = self.get_opt("role_file", None)
if len(self.args) == 0 and role_file is None: if len(self.args) == 0 and role_file is None:
# the user needs to specify one of either --role-file # the user needs to specify one of either --role-file
@ -321,8 +320,8 @@ class GalaxyCLI(CLI):
# 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")
no_deps = self.get_opt("no_deps", False) no_deps = self.get_opt("no_deps", False)
force = self.get_opt('force', False) force = self.get_opt('force', False)
roles_left = [] roles_left = []
if role_file: if role_file:
@ -511,7 +510,7 @@ class GalaxyCLI(CLI):
raise AnsibleError("Invalid query. At least one search term, platform, galaxy tag or author must be provided.") raise AnsibleError("Invalid query. At least one search term, platform, galaxy tag or author must be provided.")
response = self.api.search_roles(search, platforms=self.options.platforms, response = self.api.search_roles(search, platforms=self.options.platforms,
tags=self.options.galaxy_tags, author=self.options.author, page_size=page_size) tags=self.options.galaxy_tags, author=self.options.author, page_size=page_size)
if response['count'] == 0: if response['count'] == 0:
display.display("No roles match your search.", color=C.COLOR_ERROR) display.display("No roles match your search.", color=C.COLOR_ERROR)
@ -568,9 +567,9 @@ class GalaxyCLI(CLI):
""" used to import a role into Ansible Galaxy """ """ used to import a role into Ansible Galaxy """
colors = { colors = {
'INFO': 'normal', 'INFO': 'normal',
'WARNING': C.COLOR_WARN, 'WARNING': C.COLOR_WARN,
'ERROR': C.COLOR_ERROR, 'ERROR': C.COLOR_ERROR,
'SUCCESS': C.COLOR_OK, 'SUCCESS': C.COLOR_OK,
'FAILED': C.COLOR_ERROR, 'FAILED': C.COLOR_ERROR,
} }
@ -589,19 +588,19 @@ class GalaxyCLI(CLI):
if len(task) > 1: if len(task) > 1:
# found multiple roles associated with github_user/github_repo # found multiple roles associated with github_user/github_repo
display.display("WARNING: More than one Galaxy role associated with Github repo %s/%s." % (github_user,github_repo), display.display("WARNING: More than one Galaxy role associated with Github repo %s/%s." % (github_user, github_repo),
color='yellow') color='yellow')
display.display("The following Galaxy roles are being updated:" + u'\n', color=C.COLOR_CHANGED) display.display("The following Galaxy roles are being updated:" + u'\n', color=C.COLOR_CHANGED)
for t in task: for t in task:
display.display('%s.%s' % (t['summary_fields']['role']['namespace'],t['summary_fields']['role']['name']), color=C.COLOR_CHANGED) display.display('%s.%s' % (t['summary_fields']['role']['namespace'], t['summary_fields']['role']['name']), color=C.COLOR_CHANGED)
display.display(u'\nTo properly namespace this role, remove each of the above and re-import %s/%s from scratch' % (github_user, github_repo), display.display(u'\nTo properly namespace this role, remove each of the above and re-import %s/%s from scratch' % (github_user, github_repo),
color=C.COLOR_CHANGED) color=C.COLOR_CHANGED)
return 0 return 0
# found a single role as expected # found a single role as expected
display.display("Successfully submitted import request %d" % task[0]['id']) display.display("Successfully submitted import request %d" % task[0]['id'])
if not self.options.wait: if not self.options.wait:
display.display("Role name: %s" % task[0]['summary_fields']['role']['name']) display.display("Role name: %s" % task[0]['summary_fields']['role']['name'])
display.display("Repo: %s/%s" % (task[0]['github_user'],task[0]['github_repo'])) display.display("Repo: %s/%s" % (task[0]['github_user'], task[0]['github_repo']))
if self.options.check_status or self.options.wait: if self.options.check_status or self.options.wait:
# Get the status of the import # Get the status of the import
@ -634,7 +633,7 @@ class GalaxyCLI(CLI):
display.display("---------- ---------- ----------", color=C.COLOR_OK) display.display("---------- ---------- ----------", color=C.COLOR_OK)
for secret in secrets: for secret in secrets:
display.display("%-10s %-10s %s/%s" % (secret['id'], secret['source'], secret['github_user'], display.display("%-10s %-10s %s/%s" % (secret['id'], secret['source'], secret['github_user'],
secret['github_repo']),color=C.COLOR_OK) secret['github_repo']), color=C.COLOR_OK)
return 0 return 0
if self.options.remove_id: if self.options.remove_id:
@ -672,7 +671,7 @@ class GalaxyCLI(CLI):
display.display("ID User Name") display.display("ID User Name")
display.display("------ --------------- ----------") display.display("------ --------------- ----------")
for role in resp['deleted_roles']: for role in resp['deleted_roles']:
display.display("%-8s %-15s %s" % (role.id,role.namespace,role.name)) display.display("%-8s %-15s %s" % (role.id, role.namespace, role.name))
display.display(resp['status']) display.display(resp['status'])
@ -692,4 +691,3 @@ class GalaxyCLI(CLI):
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

View file

@ -36,18 +36,15 @@ except ImportError:
display = Display() display = Display()
#---------------------------------------------------------------------------------------------------
class PlaybookCLI(CLI): class PlaybookCLI(CLI):
''' the tool to run *Ansible playbooks*, which are a configuration and multinode deployment system. ''' the tool to run *Ansible playbooks*, which are a configuration and multinode deployment system.
See the project home page (https://docs.ansible.com) for more information. ''' See the project home page (https://docs.ansible.com) for more information. '''
def parse(self): def parse(self):
# create parser for CLI options # create parser for CLI options
parser = CLI.base_parser( parser = CLI.base_parser(
usage = "%prog [options] playbook.yml [playbook2 ...]", usage="%prog [options] playbook.yml [playbook2 ...]",
connect_opts=True, connect_opts=True,
meta_opts=True, meta_opts=True,
runas_opts=True, runas_opts=True,
@ -63,13 +60,13 @@ class PlaybookCLI(CLI):
# ansible playbook specific opts # ansible playbook specific opts
parser.add_option('--list-tasks', dest='listtasks', action='store_true', parser.add_option('--list-tasks', dest='listtasks', action='store_true',
help="list all tasks that would be executed") help="list all tasks that would be executed")
parser.add_option('--list-tags', dest='listtags', action='store_true', parser.add_option('--list-tags', dest='listtags', action='store_true',
help="list all available tags") help="list all available tags")
parser.add_option('--step', dest='step', action='store_true', parser.add_option('--step', dest='step', action='store_true',
help="one-step-at-a-time: confirm each task before running") help="one-step-at-a-time: confirm each task before running")
parser.add_option('--start-at-task', dest='start_at_task', parser.add_option('--start-at-task', dest='start_at_task',
help="start the playbook at the task matching this name") help="start the playbook at the task matching this name")
self.parser = parser self.parser = parser
super(PlaybookCLI, self).parse() super(PlaybookCLI, self).parse()
@ -86,8 +83,8 @@ class PlaybookCLI(CLI):
# Note: slightly wrong, this is written so that implicit localhost # Note: slightly wrong, this is written so that implicit localhost
# Manage passwords # Manage passwords
sshpass = None sshpass = None
becomepass = None becomepass = None
passwords = {} passwords = {}
# initial error check, to make sure all specified playbooks are accessible # initial error check, to make sure all specified playbooks are accessible
@ -102,7 +99,7 @@ class PlaybookCLI(CLI):
if not self.options.listhosts and not self.options.listtasks and not self.options.listtags and not self.options.syntax: if not self.options.listhosts and not self.options.listtasks and not self.options.listtags and not self.options.syntax:
self.normalize_become_options() self.normalize_become_options()
(sshpass, becomepass) = self.ask_passwords() (sshpass, becomepass) = self.ask_passwords()
passwords = { 'conn_pass': sshpass, 'become_pass': becomepass } passwords = {'conn_pass': sshpass, 'become_pass': becomepass}
loader, inventory, variable_manager = self._play_prereqs(self.options) loader, inventory, variable_manager = self._play_prereqs(self.options)
@ -122,7 +119,6 @@ class PlaybookCLI(CLI):
# Invalid limit # Invalid limit
raise AnsibleError("Specified --limit does not match any hosts") raise AnsibleError("Specified --limit does not match any hosts")
# flush fact cache if requested # flush fact cache if requested
if self.options.flush_cache: if self.options.flush_cache:
self._flush_cache(inventory, variable_manager) self._flush_cache(inventory, variable_manager)

View file

@ -28,8 +28,8 @@ import socket
import sys import sys
import time import time
from ansible.errors import AnsibleOptionsError
from ansible.cli import CLI from ansible.cli import CLI
from ansible.errors import AnsibleOptionsError
from ansible.module_utils._text import to_native from ansible.module_utils._text import to_native
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
@ -59,10 +59,10 @@ class PullCLI(CLI):
DEFAULT_PLAYBOOK = 'local.yml' DEFAULT_PLAYBOOK = 'local.yml'
PLAYBOOK_ERRORS = { PLAYBOOK_ERRORS = {
1: 'File does not exist', 1: 'File does not exist',
2: 'File is not readable' 2: 'File is not readable',
} }
SUPPORTED_REPO_MODULES = ['git'] SUPPORTED_REPO_MODULES = ['git']
ARGUMENTS = { 'playbook.yml': 'The name of one the YAML format files to run as an Ansible playbook.' ARGUMENTS = {'playbook.yml': 'The name of one the YAML format files to run as an Ansible playbook.'
'This can be a relative path within the checkout. By default, Ansible will' 'This can be a relative path within the checkout. By default, Ansible will'
"look for a playbook based on the host's fully-qualified domain name," "look for a playbook based on the host's fully-qualified domain name,"
'on the host hostname and finally a playbook named *local.yml*.', } 'on the host hostname and finally a playbook named *local.yml*.', }
@ -85,27 +85,28 @@ class PullCLI(CLI):
# options unique to pull # options unique to pull
self.parser.add_option('--purge', default=False, action='store_true', help='purge checkout after playbook run') self.parser.add_option('--purge', default=False, action='store_true', help='purge checkout after playbook run')
self.parser.add_option('-o', '--only-if-changed', dest='ifchanged', default=False, action='store_true', self.parser.add_option('-o', '--only-if-changed', dest='ifchanged', default=False, action='store_true',
help='only run the playbook if the repository has been updated') help='only run the playbook if the repository has been updated')
self.parser.add_option('-s', '--sleep', dest='sleep', default=None, self.parser.add_option('-s', '--sleep', dest='sleep', default=None,
help='sleep for random interval (between 0 and n number of seconds) before starting. This is a useful way to disperse git requests') help='sleep for random interval (between 0 and n number of seconds) before starting. '
'This is a useful way to disperse git requests')
self.parser.add_option('-f', '--force', dest='force', default=False, action='store_true', self.parser.add_option('-f', '--force', dest='force', default=False, action='store_true',
help='run the playbook even if the repository could not be updated') help='run the playbook even if the repository could not be updated')
self.parser.add_option('-d', '--directory', dest='dest', default=None, help='directory to checkout repository to') self.parser.add_option('-d', '--directory', dest='dest', default=None, help='directory to checkout repository to')
self.parser.add_option('-U', '--url', dest='url', default=None, help='URL of the playbook repository') self.parser.add_option('-U', '--url', dest='url', default=None, help='URL of the playbook repository')
self.parser.add_option('--full', dest='fullclone', action='store_true', help='Do a full clone, instead of a shallow one.') self.parser.add_option('--full', dest='fullclone', action='store_true', help='Do a full clone, instead of a shallow one.')
self.parser.add_option('-C', '--checkout', dest='checkout', self.parser.add_option('-C', '--checkout', dest='checkout',
help='branch/tag/commit to checkout. Defaults to behavior of repository module.') help='branch/tag/commit to checkout. Defaults to behavior of repository module.')
self.parser.add_option('--accept-host-key', default=False, dest='accept_host_key', action='store_true', self.parser.add_option('--accept-host-key', default=False, dest='accept_host_key', action='store_true',
help='adds the hostkey for the repo url if not already added') help='adds the hostkey for the repo url if not already added')
self.parser.add_option('-m', '--module-name', dest='module_name', default=self.DEFAULT_REPO_TYPE, self.parser.add_option('-m', '--module-name', dest='module_name', default=self.DEFAULT_REPO_TYPE,
help='Repository module name, which ansible will use to check out the repo. Default is %s.' % self.DEFAULT_REPO_TYPE) help='Repository module name, which ansible will use to check out the repo. Default is %s.' % self.DEFAULT_REPO_TYPE)
self.parser.add_option('--verify-commit', dest='verify', default=False, action='store_true', self.parser.add_option('--verify-commit', dest='verify', default=False, action='store_true',
help='verify GPG signature of checked out commit, if it fails abort running the playbook.' help='verify GPG signature of checked out commit, if it fails abort running the playbook. '
' This needs the corresponding VCS module to support such an operation') 'This needs the corresponding VCS module to support such an operation')
self.parser.add_option('--clean', dest='clean', default=False, action='store_true', self.parser.add_option('--clean', dest='clean', default=False, action='store_true',
help='modified files in the working repository will be discarded') help='modified files in the working repository will be discarded')
self.parser.add_option('--track-subs', dest='tracksubs', default=False, action='store_true', self.parser.add_option('--track-subs', dest='tracksubs', default=False, action='store_true',
help='submodules will track the latest changes. This is equivalent to specifying the --remote flag to git submodule update') help='submodules will track the latest changes. This is equivalent to specifying the --remote flag to git submodule update')
# for pull we don't want a default # for pull we don't want a default
self.parser.set_defaults(inventory=None) self.parser.set_defaults(inventory=None)
@ -120,7 +121,7 @@ class PullCLI(CLI):
if self.options.sleep: if self.options.sleep:
try: try:
secs = random.randint(0,int(self.options.sleep)) secs = random.randint(0, int(self.options.sleep))
self.options.sleep = secs self.options.sleep = secs
except ValueError: except ValueError:
raise AnsibleOptionsError("%s is not a number." % self.options.sleep) raise AnsibleOptionsError("%s is not a number." % self.options.sleep)
@ -151,7 +152,7 @@ class PullCLI(CLI):
limit_opts = 'localhost,%s,127.0.0.1' % ','.join(set([host, node, host.split('.')[0], node.split('.')[0]])) limit_opts = 'localhost,%s,127.0.0.1' % ','.join(set([host, node, host.split('.')[0], node.split('.')[0]]))
base_opts = '-c local ' base_opts = '-c local '
if self.options.verbosity > 0: if self.options.verbosity > 0:
base_opts += ' -%s' % ''.join([ "v" for x in range(0, self.options.verbosity) ]) base_opts += ' -%s' % ''.join(["v" for x in range(0, self.options.verbosity)])
# Attempt to use the inventory passed in as an argument # Attempt to use the inventory passed in as an argument
# It might not yet have been downloaded so use localhost as default # It might not yet have been downloaded so use localhost as default
@ -165,7 +166,7 @@ class PullCLI(CLI):
else: else:
inv_opts = "-i 'localhost,'" inv_opts = "-i 'localhost,'"
#FIXME: enable more repo modules hg/svn? # FIXME: enable more repo modules hg/svn?
if self.options.module_name == 'git': if self.options.module_name == 'git':
repo_opts = "name=%s dest=%s" % (self.options.url, self.options.dest) repo_opts = "name=%s dest=%s" % (self.options.url, self.options.dest)
if self.options.checkout: if self.options.checkout:

View file

@ -22,11 +22,11 @@ __metaclass__ = type
import os import os
import sys import sys
from ansible.cli import CLI
from ansible.errors import AnsibleError, AnsibleOptionsError from ansible.errors import AnsibleError, AnsibleOptionsError
from ansible.module_utils._text import to_text, to_bytes
from ansible.parsing.dataloader import DataLoader 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.module_utils._text import to_text, to_bytes
try: try:
from __main__ import display from __main__ import display
@ -95,9 +95,9 @@ class VaultCLI(CLI):
self.parser = CLI.base_parser( self.parser = CLI.base_parser(
vault_opts=True, vault_opts=True,
usage = "usage: %%prog [%s] [options] [vaultfile.yml]" % "|".join(self.VALID_ACTIONS), usage="usage: %%prog [%s] [options] [vaultfile.yml]" % "|".join(self.VALID_ACTIONS),
desc = "encryption/decryption utility for Ansbile data files", desc="encryption/decryption utility for Ansbile data files",
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()

View file

@ -30,7 +30,7 @@ from ansible.module_utils._text import to_text
from ansible.parsing.quoting import unquote from ansible.parsing.quoting import unquote
from ansible.utils.path import makedirs_safe from ansible.utils.path import makedirs_safe
BOOL_TRUE = frozenset( [ "true", "t", "y", "1", "yes", "on" ] ) BOOL_TRUE = frozenset(["true", "t", "y", "1", "yes", "on"])
def mk_boolean(value): def mk_boolean(value):
@ -173,48 +173,48 @@ p, CONFIG_FILE = load_config_file()
# non configurable but used as defaults # non configurable but used as defaults
BLACKLIST_EXTS = ('.pyc', '.pyo', '.swp', '.bak', '~', '.rpm', '.md', '.txt') BLACKLIST_EXTS = ('.pyc', '.pyo', '.swp', '.bak', '~', '.rpm', '.md', '.txt')
# the default whitelist for cow stencils # the default whitelist for cow stencils
DEFAULT_COW_WHITELIST = [ 'bud-frogs', 'bunny', 'cheese', 'daemon', 'default', 'dragon', 'elephant-in-snake', 'elephant', DEFAULT_COW_WHITELIST = ['bud-frogs', 'bunny', 'cheese', 'daemon', 'default', 'dragon', 'elephant-in-snake', 'elephant',
'eyes', 'hellokitty', 'kitty', 'luke-koala', 'meow', 'milk', 'moofasa', 'moose', 'ren', 'sheep', 'eyes', 'hellokitty', 'kitty', 'luke-koala', 'meow', 'milk', 'moofasa', 'moose', 'ren', 'sheep',
'small', 'stegosaurus', 'stimpy', 'supermilker', 'three-eyes', 'turkey', 'turtle', 'tux', 'udder', 'small', 'stegosaurus', 'stimpy', 'supermilker', 'three-eyes', 'turkey', 'turtle', 'tux', 'udder',
'vader-koala', 'vader', 'www', ] 'vader-koala', 'vader', 'www']
# sections in config file # sections in config file
DEFAULTS='defaults' DEFAULTS = 'defaults'
#### DEPRECATED VARS ### # FIXME: add deprecation warning when these get set # DEPRECATED VARS # FIXME: add deprecation warning when these get set
#none left now # none left now
#### DEPRECATED FEATURE TOGGLES: these will eventually be removed as it becomes the standard #### # DEPRECATED FEATURE TOGGLES: these will eventually be removed as it becomes the standard
# If --tags or --skip-tags is given multiple times on the CLI and this is True, merge the lists of tags together. # If --tags or --skip-tags is given multiple times on the CLI and this is True, merge the lists of tags together.
# If False, let the last argument overwrite any previous ones. # If False, let the last argument overwrite any previous ones.
# Behaviour is overwrite through 2.2. 2.3 overwrites but prints deprecation. 2.4 the default is to merge. # Behaviour is overwrite through 2.2. 2.3 overwrites but prints deprecation. 2.4 the default is to merge.
MERGE_MULTIPLE_CLI_TAGS = get_config(p, DEFAULTS, 'merge_multiple_cli_tags', 'ANSIBLE_MERGE_MULTIPLE_CLI_TAGS', True, value_type='boolean') MERGE_MULTIPLE_CLI_TAGS = get_config(p, DEFAULTS, 'merge_multiple_cli_tags', 'ANSIBLE_MERGE_MULTIPLE_CLI_TAGS', True, value_type='boolean')
# Controls which 'precedence path' to take, remove when decide on which! # Controls which 'precedence path' to take, remove when decide on which!
SOURCE_OVER_GROUPS = get_config(p, 'vars', 'source_over_groups', 'ANSIBLE_SOURCE_OVER_GROUPS', True, value_type='boolean') SOURCE_OVER_GROUPS = get_config(p, 'vars', 'source_over_groups', 'ANSIBLE_SOURCE_OVER_GROUPS', True, value_type='boolean')
#### GENERALLY CONFIGURABLE THINGS #### # GENERALLY CONFIGURABLE THINGS ####
DEFAULT_DEBUG = get_config(p, DEFAULTS, 'debug', 'ANSIBLE_DEBUG', False, value_type='boolean') DEFAULT_DEBUG = get_config(p, DEFAULTS, 'debug', 'ANSIBLE_DEBUG', False, value_type='boolean')
DEFAULT_VERBOSITY = get_config(p, DEFAULTS, 'verbosity', 'ANSIBLE_VERBOSITY', 0, value_type='integer') DEFAULT_VERBOSITY = get_config(p, DEFAULTS, 'verbosity', 'ANSIBLE_VERBOSITY', 0, value_type='integer')
DEFAULT_ROLES_PATH = get_config(p, DEFAULTS, 'roles_path', 'ANSIBLE_ROLES_PATH', DEFAULT_ROLES_PATH = get_config(p, DEFAULTS, 'roles_path', 'ANSIBLE_ROLES_PATH',
'~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles', value_type='pathlist', expand_relative_paths=True) '~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles', value_type='pathlist', expand_relative_paths=True)
DEFAULT_REMOTE_TMP = get_config(p, DEFAULTS, 'remote_tmp', 'ANSIBLE_REMOTE_TEMP', '~/.ansible/tmp') DEFAULT_REMOTE_TMP = get_config(p, DEFAULTS, 'remote_tmp', 'ANSIBLE_REMOTE_TEMP', '~/.ansible/tmp')
DEFAULT_LOCAL_TMP = get_config(p, DEFAULTS, 'local_tmp', 'ANSIBLE_LOCAL_TEMP', '~/.ansible/tmp', value_type='tmppath') DEFAULT_LOCAL_TMP = get_config(p, DEFAULTS, 'local_tmp', 'ANSIBLE_LOCAL_TEMP', '~/.ansible/tmp', value_type='tmppath')
DEFAULT_MODULE_NAME = get_config(p, DEFAULTS, 'module_name', None, 'command') DEFAULT_MODULE_NAME = get_config(p, DEFAULTS, 'module_name', None, 'command')
DEFAULT_FACT_PATH = get_config(p, DEFAULTS, 'fact_path', 'ANSIBLE_FACT_PATH', None, value_type='path') DEFAULT_FACT_PATH = get_config(p, DEFAULTS, 'fact_path', 'ANSIBLE_FACT_PATH', None, value_type='path')
DEFAULT_FORKS = get_config(p, DEFAULTS, 'forks', 'ANSIBLE_FORKS', 5, value_type='integer') DEFAULT_FORKS = get_config(p, DEFAULTS, 'forks', 'ANSIBLE_FORKS', 5, value_type='integer')
DEFAULT_MODULE_ARGS = get_config(p, DEFAULTS, 'module_args', 'ANSIBLE_MODULE_ARGS', '') DEFAULT_MODULE_ARGS = get_config(p, DEFAULTS, 'module_args', 'ANSIBLE_MODULE_ARGS', '')
DEFAULT_MODULE_LANG = get_config(p, DEFAULTS, 'module_lang', 'ANSIBLE_MODULE_LANG', os.getenv('LANG', 'en_US.UTF-8')) DEFAULT_MODULE_LANG = get_config(p, DEFAULTS, 'module_lang', 'ANSIBLE_MODULE_LANG', os.getenv('LANG', 'en_US.UTF-8'))
DEFAULT_MODULE_SET_LOCALE = get_config(p, DEFAULTS, 'module_set_locale','ANSIBLE_MODULE_SET_LOCALE',False, value_type='boolean') DEFAULT_MODULE_SET_LOCALE = get_config(p, DEFAULTS, 'module_set_locale', 'ANSIBLE_MODULE_SET_LOCALE', False, value_type='boolean')
DEFAULT_MODULE_COMPRESSION= get_config(p, DEFAULTS, 'module_compression', None, 'ZIP_DEFLATED') DEFAULT_MODULE_COMPRESSION = get_config(p, DEFAULTS, 'module_compression', None, 'ZIP_DEFLATED')
DEFAULT_TIMEOUT = get_config(p, DEFAULTS, 'timeout', 'ANSIBLE_TIMEOUT', 10, value_type='integer') DEFAULT_TIMEOUT = get_config(p, DEFAULTS, 'timeout', 'ANSIBLE_TIMEOUT', 10, value_type='integer')
DEFAULT_POLL_INTERVAL = get_config(p, DEFAULTS, 'poll_interval', 'ANSIBLE_POLL_INTERVAL', 15, value_type='integer') DEFAULT_POLL_INTERVAL = get_config(p, DEFAULTS, 'poll_interval', 'ANSIBLE_POLL_INTERVAL', 15, value_type='integer')
DEFAULT_REMOTE_USER = get_config(p, DEFAULTS, 'remote_user', 'ANSIBLE_REMOTE_USER', None) DEFAULT_REMOTE_USER = get_config(p, DEFAULTS, 'remote_user', 'ANSIBLE_REMOTE_USER', None)
DEFAULT_ASK_PASS = get_config(p, DEFAULTS, 'ask_pass', 'ANSIBLE_ASK_PASS', False, value_type='boolean') DEFAULT_ASK_PASS = get_config(p, DEFAULTS, 'ask_pass', 'ANSIBLE_ASK_PASS', False, value_type='boolean')
DEFAULT_PRIVATE_KEY_FILE = get_config(p, DEFAULTS, 'private_key_file', 'ANSIBLE_PRIVATE_KEY_FILE', None, value_type='path') DEFAULT_PRIVATE_KEY_FILE = get_config(p, DEFAULTS, 'private_key_file', 'ANSIBLE_PRIVATE_KEY_FILE', None, value_type='path')
DEFAULT_REMOTE_PORT = get_config(p, DEFAULTS, 'remote_port', 'ANSIBLE_REMOTE_PORT', None, value_type='integer') DEFAULT_REMOTE_PORT = get_config(p, DEFAULTS, 'remote_port', 'ANSIBLE_REMOTE_PORT', None, value_type='integer')
DEFAULT_ASK_VAULT_PASS = get_config(p, DEFAULTS, 'ask_vault_pass', 'ANSIBLE_ASK_VAULT_PASS', False, value_type='boolean') DEFAULT_ASK_VAULT_PASS = get_config(p, DEFAULTS, 'ask_vault_pass', 'ANSIBLE_ASK_VAULT_PASS', False, value_type='boolean')
DEFAULT_VAULT_PASSWORD_FILE = get_config(p, DEFAULTS, 'vault_password_file', 'ANSIBLE_VAULT_PASSWORD_FILE', None, value_type='path') DEFAULT_VAULT_PASSWORD_FILE = get_config(p, DEFAULTS, 'vault_password_file', 'ANSIBLE_VAULT_PASSWORD_FILE', None, value_type='path')
DEFAULT_TRANSPORT = get_config(p, DEFAULTS, 'transport', 'ANSIBLE_TRANSPORT', 'smart') DEFAULT_TRANSPORT = get_config(p, DEFAULTS, 'transport', 'ANSIBLE_TRANSPORT', 'smart')
DEFAULT_SCP_IF_SSH = get_config(p, 'ssh_connection', 'scp_if_ssh', 'ANSIBLE_SCP_IF_SSH', 'smart') DEFAULT_SCP_IF_SSH = get_config(p, 'ssh_connection', 'scp_if_ssh', 'ANSIBLE_SCP_IF_SSH', 'smart')
@ -226,12 +226,12 @@ DEFAULT_KEEP_REMOTE_FILES = get_config(p, DEFAULTS, 'keep_remote_files', 'ANSIBL
DEFAULT_HASH_BEHAVIOUR = get_config(p, DEFAULTS, 'hash_behaviour', 'ANSIBLE_HASH_BEHAVIOUR', 'replace') DEFAULT_HASH_BEHAVIOUR = get_config(p, DEFAULTS, 'hash_behaviour', 'ANSIBLE_HASH_BEHAVIOUR', 'replace')
DEFAULT_PRIVATE_ROLE_VARS = get_config(p, DEFAULTS, 'private_role_vars', 'ANSIBLE_PRIVATE_ROLE_VARS', False, value_type='boolean') DEFAULT_PRIVATE_ROLE_VARS = get_config(p, DEFAULTS, 'private_role_vars', 'ANSIBLE_PRIVATE_ROLE_VARS', False, value_type='boolean')
DEFAULT_JINJA2_EXTENSIONS = get_config(p, DEFAULTS, 'jinja2_extensions', 'ANSIBLE_JINJA2_EXTENSIONS', None) DEFAULT_JINJA2_EXTENSIONS = get_config(p, DEFAULTS, 'jinja2_extensions', 'ANSIBLE_JINJA2_EXTENSIONS', None)
DEFAULT_EXECUTABLE = get_config(p, DEFAULTS, 'executable', 'ANSIBLE_EXECUTABLE', '/bin/sh') DEFAULT_EXECUTABLE = get_config(p, DEFAULTS, 'executable', 'ANSIBLE_EXECUTABLE', '/bin/sh')
DEFAULT_GATHERING = get_config(p, DEFAULTS, 'gathering', 'ANSIBLE_GATHERING', 'implicit').lower() DEFAULT_GATHERING = get_config(p, DEFAULTS, 'gathering', 'ANSIBLE_GATHERING', 'implicit').lower()
DEFAULT_GATHER_SUBSET = get_config(p, DEFAULTS, 'gather_subset', 'ANSIBLE_GATHER_SUBSET', 'all').lower() DEFAULT_GATHER_SUBSET = get_config(p, DEFAULTS, 'gather_subset', 'ANSIBLE_GATHER_SUBSET', 'all').lower()
DEFAULT_GATHER_TIMEOUT = get_config(p, DEFAULTS, 'gather_timeout', 'ANSIBLE_GATHER_TIMEOUT', 10, value_type='integer') DEFAULT_GATHER_TIMEOUT = get_config(p, DEFAULTS, 'gather_timeout', 'ANSIBLE_GATHER_TIMEOUT', 10, value_type='integer')
DEFAULT_LOG_PATH = get_config(p, DEFAULTS, 'log_path', 'ANSIBLE_LOG_PATH', '', value_type='path') DEFAULT_LOG_PATH = get_config(p, DEFAULTS, 'log_path', 'ANSIBLE_LOG_PATH', '', value_type='path')
DEFAULT_FORCE_HANDLERS = get_config(p, DEFAULTS, 'force_handlers', 'ANSIBLE_FORCE_HANDLERS', False, value_type='boolean') DEFAULT_FORCE_HANDLERS = get_config(p, DEFAULTS, 'force_handlers', 'ANSIBLE_FORCE_HANDLERS', False, value_type='boolean')
DEFAULT_VAR_COMPRESSION_LEVEL = get_config(p, DEFAULTS, 'var_compression_level', 'ANSIBLE_VAR_COMPRESSION_LEVEL', 0, value_type='integer') DEFAULT_VAR_COMPRESSION_LEVEL = get_config(p, DEFAULTS, 'var_compression_level', 'ANSIBLE_VAR_COMPRESSION_LEVEL', 0, value_type='integer')
DEFAULT_INTERNAL_POLL_INTERVAL = get_config(p, DEFAULTS, 'internal_poll_interval', None, 0.001, value_type='float') DEFAULT_INTERNAL_POLL_INTERVAL = get_config(p, DEFAULTS, 'internal_poll_interval', None, 0.001, value_type='float')
DEFAULT_ALLOW_UNSAFE_LOOKUPS = get_config(p, DEFAULTS, 'allow_unsafe_lookups', None, False, value_type='boolean') DEFAULT_ALLOW_UNSAFE_LOOKUPS = get_config(p, DEFAULTS, 'allow_unsafe_lookups', None, False, value_type='boolean')
@ -240,16 +240,16 @@ SHOW_CUSTOM_STATS = get_config(p, DEFAULTS, 'show_custom_stats', 'ANSIBLE_SHOW_C
NAMESPACE_FACTS = get_config(p, DEFAULTS, 'restrict_facts_namespace', 'ANSIBLE_RESTRICT_FACTS', False, value_type='boolean') NAMESPACE_FACTS = get_config(p, DEFAULTS, 'restrict_facts_namespace', 'ANSIBLE_RESTRICT_FACTS', False, value_type='boolean')
# Inventory # Inventory
DEFAULT_HOST_LIST = get_config(p, DEFAULTS,'inventory', 'ANSIBLE_INVENTORY', '/etc/ansible/hosts', value_type='path', expand_relative_paths=True) DEFAULT_HOST_LIST = get_config(p, DEFAULTS, 'inventory', 'ANSIBLE_INVENTORY', '/etc/ansible/hosts', value_type='path', expand_relative_paths=True)
INVENTORY_ENABLED = get_config(p, DEFAULTS,'inventory_enabled', 'ANSIBLE_INVENTORY_ENABLED', INVENTORY_ENABLED = get_config(p, DEFAULTS, 'inventory_enabled', 'ANSIBLE_INVENTORY_ENABLED',
[ 'host_list', 'script', 'ini', 'yaml' ], value_type='list') ['host_list', 'script', 'ini', 'yaml'], value_type='list')
INVENTORY_IGNORE_EXTS = get_config(p, DEFAULTS, 'inventory_ignore_extensions', 'ANSIBLE_INVENTORY_IGNORE', INVENTORY_IGNORE_EXTS = get_config(p, DEFAULTS, 'inventory_ignore_extensions', 'ANSIBLE_INVENTORY_IGNORE',
BLACKLIST_EXTS + (".orig", ".ini", ".cfg", ".retry"), value_type='list') BLACKLIST_EXTS + (".orig", ".ini", ".cfg", ".retry"), value_type='list')
INVENTORY_IGNORE_PATTERNS = get_config(p, DEFAULTS, 'inventory_ignore_patterns', 'ANSIBLE_INVENTORY_IGNORE_REGEX', [], value_type='list') INVENTORY_IGNORE_PATTERNS = get_config(p, DEFAULTS, 'inventory_ignore_patterns', 'ANSIBLE_INVENTORY_IGNORE_REGEX', [], value_type='list')
VARIABLE_PRECEDENCE = get_config(p, DEFAULTS, 'precedence', 'ANSIBLE_PRECEDENCE', VARIABLE_PRECEDENCE = get_config(p, DEFAULTS, 'precedence', 'ANSIBLE_PRECEDENCE',
['all_inventory', 'groups_inventory', 'all_plugins_inventory', 'all_plugins_play', ['all_inventory', 'groups_inventory', 'all_plugins_inventory', 'all_plugins_play',
'groups_plugins_inventory', 'groups_plugins_play'], 'groups_plugins_inventory', 'groups_plugins_play'],
value_type='list') value_type='list')
# Static includes # Static includes
DEFAULT_TASK_INCLUDES_STATIC = get_config(p, DEFAULTS, 'task_includes_static', 'ANSIBLE_TASK_INCLUDES_STATIC', False, value_type='boolean') DEFAULT_TASK_INCLUDES_STATIC = get_config(p, DEFAULTS, 'task_includes_static', 'ANSIBLE_TASK_INCLUDES_STATIC', False, value_type='boolean')
DEFAULT_HANDLER_INCLUDES_STATIC = get_config(p, DEFAULTS, 'handler_includes_static', 'ANSIBLE_HANDLER_INCLUDES_STATIC', False, value_type='boolean') DEFAULT_HANDLER_INCLUDES_STATIC = get_config(p, DEFAULTS, 'handler_includes_static', 'ANSIBLE_HANDLER_INCLUDES_STATIC', False, value_type='boolean')
@ -455,4 +455,4 @@ IGNORE_FILES = ["COPYING", "CONTRIBUTING", "LICENSE", "README", "VERSION", "GUID
INTERNAL_RESULT_KEYS = ['add_host', 'add_group'] INTERNAL_RESULT_KEYS = ['add_host', 'add_group']
RESTRICTED_RESULT_KEYS = ['ansible_rsync_path', 'ansible_playbook_python'] RESTRICTED_RESULT_KEYS = ['ansible_rsync_path', 'ansible_playbook_python']
# check all of these extensions when looking for 'variable' files which should be YAML or JSON. # check all of these extensions when looking for 'variable' files which should be YAML or JSON.
YAML_FILENAME_EXTENSIONS = [ ".yml", ".yaml", ".json" ] YAML_FILENAME_EXTENSIONS = [".yml", ".yaml", ".json"]

View file

@ -20,8 +20,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
import os import os
import sys
import re import re
import sys
from ansible import constants as C from ansible import constants as C
from ansible.errors import AnsibleError from ansible.errors import AnsibleError
@ -39,6 +39,7 @@ except ImportError:
from ansible.utils.display import Display from ansible.utils.display import Display
display = Display() display = Display()
class InventoryData(object): class InventoryData(object):
""" """
Holds inventory data (host and group objects). Holds inventory data (host and group objects).
@ -92,8 +93,8 @@ class InventoryData(object):
if not py_interp: if not py_interp:
# sys.executable is not set in some cornercases. #13585 # sys.executable is not set in some cornercases. #13585
py_interp = '/usr/bin/python' py_interp = '/usr/bin/python'
display.warning('Unable to determine python interpreter from sys.executable. Using /usr/bin/python default.' display.warning('Unable to determine python interpreter from sys.executable. Using /usr/bin/python default. '
' You can correct this by setting ansible_python_interpreter for localhost') 'You can correct this by setting ansible_python_interpreter for localhost')
new_host.set_variable("ansible_python_interpreter", py_interp) new_host.set_variable("ansible_python_interpreter", py_interp)
if "ansible_connection" not in new_host.vars: if "ansible_connection" not in new_host.vars:
@ -103,7 +104,6 @@ class InventoryData(object):
return new_host return new_host
def _scan_groups_for_host(self, hostname, localhost=False): def _scan_groups_for_host(self, hostname, localhost=False):
''' in case something did not update inventory correctly, fallback to group scan ''' ''' in case something did not update inventory correctly, fallback to group scan '''
@ -121,7 +121,6 @@ class InventoryData(object):
return found return found
def reconcile_inventory(self): def reconcile_inventory(self):
''' Ensure inventory basic rules, run after updates ''' ''' Ensure inventory basic rules, run after updates '''
@ -190,7 +189,6 @@ class InventoryData(object):
return matching_host return matching_host
def add_group(self, group): def add_group(self, group):
''' adds a group to inventory if not there already ''' ''' adds a group to inventory if not there already '''
@ -215,7 +213,7 @@ class InventoryData(object):
if host not in self.hosts: if host not in self.hosts:
h = Host(host, port) h = Host(host, port)
self.hosts[host] = h self.hosts[host] = h
if self.current_source: # set to 'first source' in which host was encountered if self.current_source: # set to 'first source' in which host was encountered
self.set_variable(host, 'inventory_file', os.path.basename(self.current_source)) self.set_variable(host, 'inventory_file', os.path.basename(self.current_source))
self.set_variable(host, 'inventory_dir', basedir(self.current_source)) self.set_variable(host, 'inventory_dir', basedir(self.current_source))
else: else:
@ -236,8 +234,7 @@ class InventoryData(object):
if g and host not in g.get_hosts(): if g and host not in g.get_hosts():
g.add_host(h) g.add_host(h)
self._groups_dict_cache = {} self._groups_dict_cache = {}
display.debug("Added host %s to group %s" % (host,group)) display.debug("Added host %s to group %s" % (host, group))
def set_variable(self, entity, varname, value): def set_variable(self, entity, varname, value):
''' sets a varible for an inventory object ''' ''' sets a varible for an inventory object '''
@ -252,7 +249,6 @@ class InventoryData(object):
inv_object.set_variable(varname, value) inv_object.set_variable(varname, value)
display.debug('set %s for %s' % (varname, entity)) display.debug('set %s for %s' % (varname, entity))
def add_child(self, group, child): def add_child(self, group, child):
''' Add host or group to group ''' ''' Add host or group to group '''
@ -278,4 +274,3 @@ class InventoryData(object):
self._groups_dict_cache[group_name] = [h.name for h in group.get_hosts()] self._groups_dict_cache[group_name] = [h.name for h in group.get_hosts()]
return self._groups_dict_cache return self._groups_dict_cache

View file

@ -20,10 +20,11 @@ __metaclass__ = type
from ansible.errors import AnsibleError from ansible.errors import AnsibleError
from ansible.utils.vars import combine_vars from ansible.utils.vars import combine_vars
class Group: class Group:
''' a group of ansible hosts ''' ''' a group of ansible hosts '''
#__slots__ = [ 'name', 'hosts', 'vars', 'child_groups', 'parent_groups', 'depth', '_hosts_cache' ] # __slots__ = [ 'name', 'hosts', 'vars', 'child_groups', 'parent_groups', 'depth', '_hosts_cache' ]
def __init__(self, name=None): def __init__(self, name=None):
@ -87,7 +88,7 @@ class Group:
self.child_groups.append(group) self.child_groups.append(group)
# update the depth of the child # update the depth of the child
group.depth = max([self.depth+1, group.depth]) group.depth = max([self.depth + 1, group.depth])
# update the depth of the grandchildren # update the depth of the grandchildren
group._check_children_depth() group._check_children_depth()
@ -105,7 +106,7 @@ class Group:
try: try:
for group in self.child_groups: for group in self.child_groups:
group.depth = max([self.depth+1, group.depth]) group.depth = max([self.depth + 1, group.depth])
group._check_children_depth() group._check_children_depth()
except RuntimeError: except RuntimeError:
raise AnsibleError("The group named '%s' has a recursive dependency loop." % self.name) raise AnsibleError("The group named '%s' has a recursive dependency loop." % self.name)
@ -180,6 +181,5 @@ class Group:
try: try:
self.priority = int(priority) self.priority = int(priority)
except TypeError: except TypeError:
#FIXME: warn about invalid priority # FIXME: warn about invalid priority
pass pass

View file

@ -24,10 +24,11 @@ from ansible.utils.vars import combine_vars, get_unique_id
__all__ = ['Host'] __all__ = ['Host']
class Host: class Host:
''' a single ansible host ''' ''' a single ansible host '''
#__slots__ = [ 'name', 'vars', 'groups' ] # __slots__ = [ 'name', 'vars', 'groups' ]
def __getstate__(self): def __getstate__(self):
return self.serialize() return self.serialize()
@ -69,11 +70,11 @@ class Host:
def deserialize(self, data): def deserialize(self, data):
self.__init__(gen_uuid=False) self.__init__(gen_uuid=False)
self.name = data.get('name') self.name = data.get('name')
self.vars = data.get('vars', dict()) self.vars = data.get('vars', dict())
self.address = data.get('address', '') self.address = data.get('address', '')
self._uuid = data.get('uuid', None) self._uuid = data.get('uuid', None)
self.implicit= data.get('implicit', False) self.implicit = data.get('implicit', False)
groups = data.get('groups', []) groups = data.get('groups', [])
for group_data in groups: for group_data in groups:
@ -100,7 +101,6 @@ class Host:
def get_name(self): def get_name(self):
return self.name return self.name
def populate_ancestors(self): def populate_ancestors(self):
# populate ancestors # populate ancestors
for group in self.groups: for group in self.groups:
@ -131,9 +131,8 @@ class Host:
else: else:
self.remove_group(oldg) self.remove_group(oldg)
def set_variable(self, key, value): def set_variable(self, key, value):
self.vars[key]=value self.vars[key] = value
def get_groups(self): def get_groups(self):
return self.groups return self.groups
@ -142,10 +141,9 @@ class Host:
results = {} results = {}
results['inventory_hostname'] = self.name results['inventory_hostname'] = self.name
results['inventory_hostname_short'] = self.name.split('.')[0] results['inventory_hostname_short'] = self.name.split('.')[0]
results['group_names'] = sorted([ g.name for g in self.get_groups() if g.name != 'all']) results['group_names'] = sorted([g.name for g in self.get_groups() if g.name != 'all'])
return combine_vars(self.vars, results) return combine_vars(self.vars, results)
def get_vars(self): def get_vars(self):
return combine_vars(self.vars, self.get_magic_vars()) return combine_vars(self.vars, self.get_magic_vars())

View file

@ -42,11 +42,12 @@ except ImportError:
HOSTS_PATTERNS_CACHE = {} HOSTS_PATTERNS_CACHE = {}
IGNORED_ALWAYS = [b"^\.", b"^host_vars$", b"^group_vars$", b"^vars_plugins$"] IGNORED_ALWAYS = [b"^\.", b"^host_vars$", b"^group_vars$", b"^vars_plugins$"]
IGNORED_PATTERNS = [ to_bytes(x) for x in C.INVENTORY_IGNORE_PATTERNS ] IGNORED_PATTERNS = [to_bytes(x) for x in C.INVENTORY_IGNORE_PATTERNS]
IGNORED_EXTS = [b'%s$' % to_bytes(re.escape(x)) for x in C.INVENTORY_IGNORE_EXTS] IGNORED_EXTS = [b'%s$' % to_bytes(re.escape(x)) for x in C.INVENTORY_IGNORE_EXTS]
IGNORED = re.compile(b'|'.join(IGNORED_ALWAYS + IGNORED_PATTERNS + IGNORED_EXTS)) IGNORED = re.compile(b'|'.join(IGNORED_ALWAYS + IGNORED_PATTERNS + IGNORED_EXTS))
def order_patterns(patterns): def order_patterns(patterns):
''' takes a list of patterns and reorders them by modifier to apply them consistently ''' ''' takes a list of patterns and reorders them by modifier to apply them consistently '''
@ -114,6 +115,7 @@ def split_host_pattern(pattern):
return [p.strip() for p in patterns] return [p.strip() for p in patterns]
class InventoryManager(object): class InventoryManager(object):
''' Creates and manages inventory ''' ''' Creates and manages inventory '''
@ -135,7 +137,7 @@ class InventoryManager(object):
if sources is None: if sources is None:
self._sources = [] self._sources = []
elif isinstance(sources, string_types): elif isinstance(sources, string_types):
self._sources = [ sources ] self._sources = [sources]
else: else:
self._sources = sources self._sources = sources
@ -175,7 +177,7 @@ class InventoryManager(object):
def _setup_inventory_plugins(self): def _setup_inventory_plugins(self):
''' sets up loaded inventory plugins for usage ''' ''' sets up loaded inventory plugins for usage '''
inventory_loader = PluginLoader( 'InventoryModule', 'ansible.plugins.inventory', 'inventory_plugins', 'inventory_plugins') inventory_loader = PluginLoader('InventoryModule', 'ansible.plugins.inventory', 'inventory_plugins', 'inventory_plugins')
display.vvvv('setting up inventory plugins') display.vvvv('setting up inventory plugins')
for name in C.INVENTORY_ENABLED: for name in C.INVENTORY_ENABLED:
@ -197,7 +199,7 @@ class InventoryManager(object):
if source: if source:
if ',' not in source: if ',' not in source:
source = unfrackpath(source, follow=False) source = unfrackpath(source, follow=False)
parse = self.parse_source(source, cache=cache) parse = self.parse_source(source, cache=cache)
if parse and not parsed: if parse and not parsed:
parsed = True parsed = True
@ -257,7 +259,7 @@ class InventoryManager(object):
display.vvv(u'Parsed %s inventory source with %s plugin' % (to_text(source), plugin_name)) display.vvv(u'Parsed %s inventory source with %s plugin' % (to_text(source), plugin_name))
break break
except AnsibleParserError as e: except AnsibleParserError as e:
failures.append(u'\n* Failed to parse %s with %s inventory plugin: %s\n' %(to_text(source), plugin_name, to_text(e))) failures.append(u'\n* Failed to parse %s with %s inventory plugin: %s\n' % (to_text(source), plugin_name, to_text(e)))
else: else:
display.debug(u'%s did not meet %s requirements' % (to_text(source), plugin_name)) display.debug(u'%s did not meet %s requirements' % (to_text(source), plugin_name))
else: else:
@ -279,7 +281,7 @@ class InventoryManager(object):
global HOSTS_PATTERNS_CACHE global HOSTS_PATTERNS_CACHE
HOSTS_PATTERNS_CACHE = {} HOSTS_PATTERNS_CACHE = {}
self._pattern_cache = {} self._pattern_cache = {}
#FIXME: flush inventory cache # FIXME: flush inventory cache
def refresh_inventory(self): def refresh_inventory(self):
''' recalculate inventory ''' ''' recalculate inventory '''
@ -340,11 +342,11 @@ class InventoryManager(object):
if not ignore_limits and self._subset: if not ignore_limits and self._subset:
# exclude hosts not in a subset, if defined # exclude hosts not in a subset, if defined
subset = self._evaluate_patterns(self._subset) subset = self._evaluate_patterns(self._subset)
hosts = [ h for h in hosts if h in subset ] hosts = [h for h in hosts if h in subset]
if not ignore_restrictions and self._restriction: if not ignore_restrictions and self._restriction:
# exclude hosts mentioned in any restriction (ex: failed hosts) # exclude hosts mentioned in any restriction (ex: failed hosts)
hosts = [ h for h in hosts if h.name in self._restriction ] hosts = [h for h in hosts if h.name in self._restriction]
seen = set() seen = set()
HOSTS_PATTERNS_CACHE[pattern_hash] = [x for x in hosts if x not in seen and not seen.add(x)] HOSTS_PATTERNS_CACHE[pattern_hash] = [x for x in hosts if x not in seen and not seen.add(x)]
@ -365,7 +367,6 @@ class InventoryManager(object):
return hosts return hosts
def _evaluate_patterns(self, patterns): def _evaluate_patterns(self, patterns):
""" """
Takes a list of patterns and returns a list of matching host names, Takes a list of patterns and returns a list of matching host names,
@ -382,11 +383,11 @@ class InventoryManager(object):
else: else:
that = self._match_one_pattern(p) that = self._match_one_pattern(p)
if p.startswith("!"): if p.startswith("!"):
hosts = [ h for h in hosts if h not in that ] hosts = [h for h in hosts if h not in that]
elif p.startswith("&"): elif p.startswith("&"):
hosts = [ h for h in hosts if h in that ] hosts = [h for h in hosts if h in that]
else: else:
to_append = [ h for h in that if h.name not in [ y.name for y in hosts ] ] to_append = [h for h in that if h.name not in [y.name for y in hosts]]
hosts.extend(to_append) hosts.extend(to_append)
return hosts return hosts
@ -500,10 +501,10 @@ class InventoryManager(object):
if end: if end:
if end == -1: if end == -1:
end = len(hosts)-1 end = len(hosts) - 1
return hosts[start:end+1] return hosts[start:end + 1]
else: else:
return [ hosts[start] ] return [hosts[start]]
def _enumerate_matches(self, pattern): def _enumerate_matches(self, pattern):
""" """
@ -539,13 +540,13 @@ class InventoryManager(object):
matched = True matched = True
if not matched: if not matched:
display.warning("Could not match supplied host pattern, ignoring: %s" % pattern) display.warning("Could not match supplied host pattern, ignoring: %s" % pattern)
return results return results
def list_hosts(self, pattern="all"): def list_hosts(self, pattern="all"):
""" return a list of hostnames for a pattern """ """ return a list of hostnames for a pattern """
#FIXME: cache? # FIXME: cache?
result = [ h for h in self.get_hosts(pattern) ] result = [h for h in self.get_hosts(pattern)]
# allow implicit localhost if pattern matches and no other results # allow implicit localhost if pattern matches and no other results
if len(result) == 0 and pattern in C.LOCALHOST: if len(result) == 0 and pattern in C.LOCALHOST:
@ -554,7 +555,7 @@ class InventoryManager(object):
return result return result
def list_groups(self): def list_groups(self):
#FIXME: cache? # FIXME: cache?
return sorted(self._inventory.groups.keys(), key=lambda x: x) return sorted(self._inventory.groups.keys(), key=lambda x: x)
def restrict_to_hosts(self, restriction): def restrict_to_hosts(self, restriction):
@ -566,8 +567,8 @@ class InventoryManager(object):
if restriction is None: if restriction is None:
return return
elif not isinstance(restriction, list): elif not isinstance(restriction, list):
restriction = [ restriction ] restriction = [restriction]
self._restriction = [ h.name for h in restriction ] self._restriction = [h.name for h in restriction]
def subset(self, subset_pattern): def subset(self, subset_pattern):
""" """

View file

@ -45,8 +45,8 @@ except LookupError:
_COMPOSED_ERROR_HANDLERS = frozenset((None, 'surrogate_or_escape', _COMPOSED_ERROR_HANDLERS = frozenset((None, 'surrogate_or_escape',
'surrogate_or_strict', 'surrogate_or_strict',
'surrogate_then_replace')) 'surrogate_then_replace'))
def to_bytes(obj, encoding='utf-8', errors=None, nonstring='simplerepr'): def to_bytes(obj, encoding='utf-8', errors=None, nonstring='simplerepr'):

View file

@ -44,6 +44,7 @@ AXAPI_VPORT_PROTOCOLS = {
'https': 12, 'https': 12,
} }
def a10_argument_spec(): def a10_argument_spec():
return dict( return dict(
host=dict(type='str', required=True), host=dict(type='str', required=True),
@ -52,11 +53,13 @@ def a10_argument_spec():
write_config=dict(type='bool', default=False) write_config=dict(type='bool', default=False)
) )
def axapi_failure(result): def axapi_failure(result):
if 'response' in result and result['response'].get('status') == 'fail': if 'response' in result and result['response'].get('status') == 'fail':
return True return True
return False return False
def axapi_call(module, url, post=None): def axapi_call(module, url, post=None):
''' '''
Returns a datastructure based on the result of the API call Returns a datastructure based on the result of the API call
@ -81,6 +84,7 @@ def axapi_call(module, url, post=None):
rsp.close() rsp.close()
return data return data
def axapi_authenticate(module, base_url, username, password): def axapi_authenticate(module, base_url, username, password):
url = '%s&method=authenticate&username=%s&password=%s' % (base_url, username, password) url = '%s&method=authenticate&username=%s&password=%s' % (base_url, username, password)
result = axapi_call(module, url) result = axapi_call(module, url)
@ -89,6 +93,7 @@ def axapi_authenticate(module, base_url, username, password):
sessid = result['session_id'] sessid = result['session_id']
return base_url + '&session_id=' + sessid return base_url + '&session_id=' + sessid
def axapi_authenticate_v3(module, base_url, username, password): def axapi_authenticate_v3(module, base_url, username, password):
url = base_url url = base_url
auth_payload = {"credentials": {"username": username, "password": password}} auth_payload = {"credentials": {"username": username, "password": password}}
@ -98,6 +103,7 @@ def axapi_authenticate_v3(module, base_url, username, password):
signature = result['authresponse']['signature'] signature = result['authresponse']['signature']
return signature return signature
def axapi_call_v3(module, url, method=None, body=None, signature=None): def axapi_call_v3(module, url, method=None, body=None, signature=None):
''' '''
Returns a datastructure based on the result of the API call Returns a datastructure based on the result of the API call
@ -126,6 +132,7 @@ def axapi_call_v3(module, url, method=None, body=None, signature=None):
rsp.close() rsp.close()
return data return data
def axapi_enabled_disabled(flag): def axapi_enabled_disabled(flag):
''' '''
The axapi uses 0/1 integer values for flags, rather than strings The axapi uses 0/1 integer values for flags, rather than strings
@ -137,8 +144,10 @@ def axapi_enabled_disabled(flag):
else: else:
return 0 return 0
def axapi_get_port_protocol(protocol): def axapi_get_port_protocol(protocol):
return AXAPI_PORT_PROTOCOLS.get(protocol.lower(), None) return AXAPI_PORT_PROTOCOLS.get(protocol.lower(), None)
def axapi_get_vport_protocol(protocol): def axapi_get_vport_protocol(protocol):
return AXAPI_VPORT_PROTOCOLS.get(protocol.lower(), None) return AXAPI_VPORT_PROTOCOLS.get(protocol.lower(), None)

View file

@ -79,9 +79,9 @@ def tower_check_mode(module):
def tower_argument_spec(): def tower_argument_spec():
return dict( return dict(
tower_host = dict(), tower_host=dict(),
tower_username = dict(), tower_username=dict(),
tower_password = dict(no_log=True), tower_password=dict(no_log=True),
tower_verify_ssl = dict(type='bool', default=True), tower_verify_ssl=dict(type='bool', default=True),
tower_config_file = dict(type='path'), tower_config_file=dict(type='path'),
) )

View file

@ -37,8 +37,8 @@ from ansible.module_utils.aos import *
""" """
import json import json
from distutils.version import LooseVersion
from ansible.module_utils.pycompat24 import get_exception from ansible.module_utils.pycompat24 import get_exception
from distutils.version import LooseVersion
try: try:
import yaml import yaml
@ -53,6 +53,7 @@ try:
except ImportError: except ImportError:
HAS_AOS_PYEZ = False HAS_AOS_PYEZ = False
def check_aos_version(module, min=False): def check_aos_version(module, min=False):
""" """
Check if the library aos-pyez is present. Check if the library aos-pyez is present.
@ -71,6 +72,7 @@ def check_aos_version(module, min=False):
return True return True
def get_aos_session(module, auth): def get_aos_session(module, auth):
""" """
Resume an existing session and return an AOS object. Resume an existing session and return an AOS object.
@ -94,6 +96,7 @@ def get_aos_session(module, auth):
return aos return aos
def find_collection_item(collection, item_name=False, item_id=False): def find_collection_item(collection, item_name=False, item_id=False):
""" """
Find collection_item based on name or id from a collection object Find collection_item based on name or id from a collection object
@ -114,6 +117,7 @@ def find_collection_item(collection, item_name=False, item_id=False):
else: else:
return my_dict return my_dict
def content_to_dict(module, content): def content_to_dict(module, content):
""" """
Convert 'content' into a Python Dict based on 'content_format' Convert 'content' into a Python Dict based on 'content_format'
@ -144,12 +148,12 @@ def content_to_dict(module, content):
except: except:
module.fail_json(msg="Unable to convert 'content' to a dict, please check if valid") module.fail_json(msg="Unable to convert 'content' to a dict, please check if valid")
# replace the string with the dict # replace the string with the dict
module.params['content'] = content_dict module.params['content'] = content_dict
return content_dict return content_dict
def do_load_resource(module, collection, name): def do_load_resource(module, collection, name):
""" """
Create a new object (collection.item) by loading a datastructure directly Create a new object (collection.item) by loading a datastructure directly
@ -161,10 +165,7 @@ def do_load_resource(module, collection, name):
module.fail_json(msg="An error occurred while running 'find_collection_item'") module.fail_json(msg="An error occurred while running 'find_collection_item'")
if item.exists: if item.exists:
module.exit_json( changed=False, module.exit_json(changed=False, name=item.name, id=item.id, value=item.value)
name=item.name,
id=item.id,
value=item.value )
# If not in check mode, apply the changes # If not in check mode, apply the changes
if not module.check_mode: if not module.check_mode:
@ -175,7 +176,4 @@ def do_load_resource(module, collection, name):
e = get_exception() e = get_exception()
module.fail_json(msg="Unable to write item content : %r" % e) module.fail_json(msg="Unable to write item content : %r" % e)
module.exit_json( changed=True, module.exit_json(changed=True, name=item.name, id=item.id, value=item.value)
name=item.name,
id=item.id,
value=item.value )

View file

@ -40,6 +40,7 @@ The 'api' module provides the following common argument specs:
""" """
import time import time
def rate_limit_argument_spec(spec=None): def rate_limit_argument_spec(spec=None):
"""Creates an argument spec for working with rate limiting""" """Creates an argument spec for working with rate limiting"""
arg_spec = (dict( arg_spec = (dict(
@ -50,6 +51,7 @@ def rate_limit_argument_spec(spec=None):
arg_spec.update(spec) arg_spec.update(spec)
return arg_spec return arg_spec
def retry_argument_spec(spec=None): def retry_argument_spec(spec=None):
"""Creates an argument spec for working with retrying""" """Creates an argument spec for working with retrying"""
arg_spec = (dict( arg_spec = (dict(
@ -60,41 +62,48 @@ def retry_argument_spec(spec=None):
arg_spec.update(spec) arg_spec.update(spec)
return arg_spec return arg_spec
def basic_auth_argument_spec(spec=None): def basic_auth_argument_spec(spec=None):
arg_spec = (dict( arg_spec = (dict(
api_username=dict(type='str', required=False), api_username=dict(type='str'),
api_password=dict(type='str', required=False, no_log=True), api_password=dict(type='str', no_log=True),
api_url=dict(type='str', required=False), api_url=dict(type='str'),
validate_certs=dict(type='bool', default=True) validate_certs=dict(type='bool', default=True)
)) ))
if spec: if spec:
arg_spec.update(spec) arg_spec.update(spec)
return arg_spec return arg_spec
def rate_limit(rate=None, rate_limit=None): def rate_limit(rate=None, rate_limit=None):
"""rate limiting decorator""" """rate limiting decorator"""
minrate = None minrate = None
if rate is not None and rate_limit is not None: if rate is not None and rate_limit is not None:
minrate = float(rate_limit) / float(rate) minrate = float(rate_limit) / float(rate)
def wrapper(f): def wrapper(f):
last = [0.0] last = [0.0]
def ratelimited(*args,**kwargs):
def ratelimited(*args, **kwargs):
if minrate is not None: if minrate is not None:
elapsed = time.clock() - last[0] elapsed = time.clock() - last[0]
left = minrate - elapsed left = minrate - elapsed
if left > 0: if left > 0:
time.sleep(left) time.sleep(left)
last[0] = time.clock() last[0] = time.clock()
ret = f(*args,**kwargs) ret = f(*args, **kwargs)
return ret return ret
return ratelimited return ratelimited
return wrapper return wrapper
def retry(retries=None, retry_pause=1): def retry(retries=None, retry_pause=1):
"""Retry decorator""" """Retry decorator"""
def wrapper(f): def wrapper(f):
retry_count = 0 retry_count = 0
def retried(*args,**kwargs):
def retried(*args, **kwargs):
if retries is not None: if retries is not None:
ret = None ret = None
while True: while True:
@ -102,13 +111,13 @@ def retry(retries=None, retry_pause=1):
if retry_count >= retries: if retry_count >= retries:
raise Exception("Retry limit exceeded: %d" % retries) raise Exception("Retry limit exceeded: %d" % retries)
try: try:
ret = f(*args,**kwargs) ret = f(*args, **kwargs)
except: except:
pass pass
if ret: if ret:
break break
time.sleep(retry_pause) time.sleep(retry_pause)
return ret return ret
return retried return retried
return wrapper return wrapper

View file

@ -25,7 +25,6 @@
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# This module initially matched the namespace of network module avi. However, # This module initially matched the namespace of network module avi. However,
# that causes namespace import error when other modules from avi namespaces # that causes namespace import error when other modules from avi namespaces
@ -40,8 +39,7 @@ HAS_AVI = True
try: try:
import avi.sdk import avi.sdk
sdk_version = getattr(avi.sdk, '__version__', None) sdk_version = getattr(avi.sdk, '__version__', None)
if ((sdk_version is None) or (sdk_version and if ((sdk_version is None) or (sdk_version and (parse_version(sdk_version) < parse_version('17.1')))):
(parse_version(sdk_version) < parse_version('17.1')))):
# It allows the __version__ to be '' as that value is used in development builds # It allows the __version__ to be '' as that value is used in development builds
raise ImportError raise ImportError
from avi.sdk.utils.ansible_utils import avi_ansible_api from avi.sdk.utils.ansible_utils import avi_ansible_api

View file

@ -1,4 +1,3 @@
#
# Copyright (c) 2016 Matt Davis, <mdavis@ansible.com> # Copyright (c) 2016 Matt Davis, <mdavis@ansible.com>
# Chris Houseknecht, <house@redhat.com> # Chris Houseknecht, <house@redhat.com>
# #
@ -16,7 +15,6 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
import json import json
import os import os
@ -102,6 +100,7 @@ except ImportError as exc:
HAS_AZURE_EXC = exc HAS_AZURE_EXC = exc
HAS_AZURE = False HAS_AZURE = False
def azure_id_to_dict(id): def azure_id_to_dict(id):
pieces = re.sub(r'^\/', '', id).split('/') pieces = re.sub(r'^\/', '', id).split('/')
result = {} result = {}
@ -121,6 +120,7 @@ AZURE_EXPECTED_VERSIONS = dict(
AZURE_MIN_RELEASE = '2.0.0rc5' AZURE_MIN_RELEASE = '2.0.0rc5'
class AzureRMModuleBase(object): class AzureRMModuleBase(object):
def __init__(self, derived_arg_spec, bypass_checks=False, no_log=False, def __init__(self, derived_arg_spec, bypass_checks=False, no_log=False,
@ -202,7 +202,7 @@ class AzureRMModuleBase(object):
if Version(client_version) < Version(expected_version): if Version(client_version) < Version(expected_version):
self.fail("Installed {0} client version is {1}. The supported version is {2}. Try " self.fail("Installed {0} client version is {1}. The supported version is {2}. Try "
"`pip install azure>={3} --upgrade`".format(client_name, client_version, expected_version, "`pip install azure>={3} --upgrade`".format(client_name, client_version, expected_version,
AZURE_MIN_RELEASE)) AZURE_MIN_RELEASE))
def exec_module(self, **kwargs): def exec_module(self, **kwargs):
self.fail("Error: {0} failed to implement exec_module method.".format(self.__class__.__name__)) self.fail("Error: {0} failed to implement exec_module method.".format(self.__class__.__name__))
@ -220,11 +220,11 @@ class AzureRMModuleBase(object):
def log(self, msg, pretty_print=False): def log(self, msg, pretty_print=False):
pass pass
# Use only during module development # Use only during module development
#if self.debug: # if self.debug:
# log_file = open('azure_rm.log', 'a') # log_file = open('azure_rm.log', 'a')
# if pretty_print: # if pretty_print:
# log_file.write(json.dumps(msg, indent=4, sort_keys=True)) # log_file.write(json.dumps(msg, indent=4, sort_keys=True))
# else: # else:
# log_file.write(msg + u'\n') # log_file.write(msg + u'\n')
def validate_tags(self, tags): def validate_tags(self, tags):

View file

@ -32,7 +32,17 @@ BOOLEANS_TRUE = ['y', 'yes', 'on', '1', 'true', 1, True]
BOOLEANS_FALSE = ['n', 'no', 'off', '0', 'false', 0, False] BOOLEANS_FALSE = ['n', 'no', 'off', '0', 'false', 0, False]
BOOLEANS = BOOLEANS_TRUE + BOOLEANS_FALSE BOOLEANS = BOOLEANS_TRUE + BOOLEANS_FALSE
SIZE_RANGES = { 'Y': 1<<80, 'Z': 1<<70, 'E': 1<<60, 'P': 1<<50, 'T': 1<<40, 'G': 1<<30, 'M': 1<<20, 'K': 1<<10, 'B': 1 } SIZE_RANGES = {
'Y': 1 << 80,
'Z': 1 << 70,
'E': 1 << 60,
'P': 1 << 50,
'T': 1 << 40,
'G': 1 << 30,
'M': 1 << 20,
'K': 1 << 10,
'B': 1,
}
FILE_ATTRIBUTES = { FILE_ATTRIBUTES = {
'A': 'noatime', 'A': 'noatime',
@ -83,9 +93,9 @@ from itertools import repeat, chain
try: try:
import syslog import syslog
HAS_SYSLOG=True HAS_SYSLOG = True
except ImportError: except ImportError:
HAS_SYSLOG=False HAS_SYSLOG = False
try: try:
from systemd import journal from systemd import journal
@ -93,10 +103,10 @@ try:
except ImportError: except ImportError:
has_journal = False has_journal = False
HAVE_SELINUX=False HAVE_SELINUX = False
try: try:
import selinux import selinux
HAVE_SELINUX=True HAVE_SELINUX = True
except ImportError: except ImportError:
pass pass
@ -161,8 +171,16 @@ except ImportError:
pass pass
from ansible.module_utils.pycompat24 import get_exception, literal_eval from ansible.module_utils.pycompat24 import get_exception, literal_eval
from ansible.module_utils.six import (PY2, PY3, b, binary_type, integer_types, from ansible.module_utils.six import (
iteritems, text_type, string_types) PY2,
PY3,
b,
binary_type,
integer_types,
iteritems,
string_types,
text_type,
)
from ansible.module_utils.six.moves import map, reduce, shlex_quote from ansible.module_utils.six.moves import map, reduce, shlex_quote
from ansible.module_utils._text import to_native, to_bytes, to_text from ansible.module_utils._text import to_native, to_bytes, to_text
@ -208,33 +226,33 @@ _literal_eval = literal_eval
# is an internal implementation detail # is an internal implementation detail
_ANSIBLE_ARGS = None _ANSIBLE_ARGS = None
FILE_COMMON_ARGUMENTS=dict( FILE_COMMON_ARGUMENTS = dict(
src = dict(), src=dict(),
mode = dict(type='raw'), mode=dict(type='raw'),
owner = dict(), owner=dict(),
group = dict(), group=dict(),
seuser = dict(), seuser=dict(),
serole = dict(), serole=dict(),
selevel = dict(), selevel=dict(),
setype = dict(), setype=dict(),
follow = dict(type='bool', default=False), follow=dict(type='bool', default=False),
# not taken by the file module, but other modules call file so it must ignore them. # not taken by the file module, but other modules call file so it must ignore them.
content = dict(no_log=True), content=dict(no_log=True),
backup = dict(), backup=dict(),
force = dict(), force=dict(),
remote_src = dict(), # used by assemble remote_src=dict(), # used by assemble
regexp = dict(), # used by assemble regexp=dict(), # used by assemble
delimiter = dict(), # used by assemble delimiter=dict(), # used by assemble
directory_mode = dict(), # used by copy directory_mode=dict(), # used by copy
unsafe_writes = dict(type='bool'), # should be available to any module using atomic_move unsafe_writes=dict(type='bool'), # should be available to any module using atomic_move
attributes = dict(aliases=['attr']), attributes=dict(aliases=['attr']),
) )
PASSWD_ARG_RE = re.compile(r'^[-]{0,2}pass[-]?(word|wd)?') PASSWD_ARG_RE = re.compile(r'^[-]{0,2}pass[-]?(word|wd)?')
# Can't use 07777 on Python 3, can't use 0o7777 on Python 2.4 # Can't use 07777 on Python 3, can't use 0o7777 on Python 2.4
PERM_BITS = int('07777', 8) # file mode permission bits PERM_BITS = int('07777', 8) # file mode permission bits
EXEC_PERM_BITS = int('00111', 8) # execute permission bits EXEC_PERM_BITS = int('00111', 8) # execute permission bits
DEFAULT_PERM = int('0666', 8) # default file permission bits DEFAULT_PERM = int('0666', 8) # default file permission bits
@ -242,11 +260,12 @@ def get_platform():
''' what's the platform? example: Linux is a platform. ''' ''' what's the platform? example: Linux is a platform. '''
return platform.system() return platform.system()
def get_distribution(): def get_distribution():
''' return the distribution name ''' ''' return the distribution name '''
if platform.system() == 'Linux': if platform.system() == 'Linux':
try: try:
supported_dists = platform._supported_dists + ('arch','alpine') supported_dists = platform._supported_dists + ('arch', 'alpine')
distribution = platform.linux_distribution(supported_dists=supported_dists)[0].capitalize() distribution = platform.linux_distribution(supported_dists=supported_dists)[0].capitalize()
if not distribution and os.path.isfile('/etc/system-release'): if not distribution and os.path.isfile('/etc/system-release'):
distribution = platform.linux_distribution(supported_dists=['system'])[0].capitalize() distribution = platform.linux_distribution(supported_dists=['system'])[0].capitalize()
@ -261,6 +280,7 @@ def get_distribution():
distribution = None distribution = None
return distribution return distribution
def get_distribution_version(): def get_distribution_version():
''' return the distribution version ''' ''' return the distribution version '''
if platform.system() == 'Linux': if platform.system() == 'Linux':
@ -275,6 +295,7 @@ def get_distribution_version():
distribution_version = None distribution_version = None
return distribution_version return distribution_version
def get_all_subclasses(cls): def get_all_subclasses(cls):
''' '''
used by modules like Hardware or Network fact classes to retrieve all subclasses of a given class. used by modules like Hardware or Network fact classes to retrieve all subclasses of a given class.
@ -338,6 +359,7 @@ def json_dict_unicode_to_bytes(d, encoding='utf-8', errors='surrogate_or_strict'
else: else:
return d return d
def json_dict_bytes_to_unicode(d, encoding='utf-8', errors='surrogate_or_strict'): def json_dict_bytes_to_unicode(d, encoding='utf-8', errors='surrogate_or_strict'):
''' Recursively convert dict keys and values to byte str ''' Recursively convert dict keys and values to byte str
@ -357,6 +379,7 @@ def json_dict_bytes_to_unicode(d, encoding='utf-8', errors='surrogate_or_strict'
else: else:
return d return d
def return_values(obj): def return_values(obj):
""" Return native stringified values from datastructures. """ Return native stringified values from datastructures.
@ -381,6 +404,7 @@ def return_values(obj):
else: else:
raise TypeError('Unknown parameter type: %s, %s' % (type(obj), obj)) raise TypeError('Unknown parameter type: %s, %s' % (type(obj), obj))
def remove_values(value, no_log_strings): def remove_values(value, no_log_strings):
""" Remove strings in no_log_strings from value. If value is a container """ Remove strings in no_log_strings from value. If value is a container
type, then remove a lot more""" type, then remove a lot more"""
@ -489,6 +513,7 @@ def heuristic_log_sanitize(data, no_log_values=None):
output = remove_values(output, no_log_values) output = remove_values(output, no_log_values)
return output return output
def bytes_to_human(size, isbits=False, unit=None): def bytes_to_human(size, isbits=False, unit=None):
base = 'Bytes' base = 'Bytes'
@ -505,7 +530,8 @@ def bytes_to_human(size, isbits=False, unit=None):
else: else:
suffix = base suffix = base
return '%.2f %s' % (float(size)/ limit, suffix) return '%.2f %s' % (float(size) / limit, suffix)
def human_to_bytes(number, default_unit=None, isbits=False): def human_to_bytes(number, default_unit=None, isbits=False):
@ -555,6 +581,7 @@ def human_to_bytes(number, default_unit=None, isbits=False):
return int(round(num * limit)) return int(round(num * limit))
def is_executable(path): def is_executable(path):
'''is the given path executable? '''is the given path executable?
@ -568,6 +595,7 @@ def is_executable(path):
# execute bits are set. # execute bits are set.
return ((stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) & os.stat(path)[stat.ST_MODE]) return ((stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) & os.stat(path)[stat.ST_MODE])
def _load_params(): def _load_params():
''' read the modules parameters and store them globally. ''' read the modules parameters and store them globally.
@ -623,6 +651,7 @@ def _load_params():
'"failed": true}') '"failed": true}')
sys.exit(1) sys.exit(1)
def env_fallback(*args, **kwargs): def env_fallback(*args, **kwargs):
''' Load value from environment ''' ''' Load value from environment '''
for arg in args: for arg in args:
@ -631,6 +660,7 @@ def env_fallback(*args, **kwargs):
else: else:
raise AnsibleFallbackNotFound raise AnsibleFallbackNotFound
def _lenient_lowercase(lst): def _lenient_lowercase(lst):
"""Lowercase elements of a list. """Lowercase elements of a list.
@ -644,6 +674,7 @@ def _lenient_lowercase(lst):
lowered.append(value) lowered.append(value)
return lowered return lowered
def format_attributes(attributes): def format_attributes(attributes):
attribute_list = [] attribute_list = []
for attr in attributes: for attr in attributes:
@ -651,13 +682,15 @@ def format_attributes(attributes):
attribute_list.append(FILE_ATTRIBUTES[attr]) attribute_list.append(FILE_ATTRIBUTES[attr])
return attribute_list return attribute_list
def get_flags_from_attributes(attributes): def get_flags_from_attributes(attributes):
flags = [] flags = []
for key,attr in FILE_ATTRIBUTES.items(): for key, attr in FILE_ATTRIBUTES.items():
if attr in attributes: if attr in attributes:
flags.append(key) flags.append(key)
return ''.join(flags) return ''.join(flags)
class AnsibleFallbackNotFound(Exception): class AnsibleFallbackNotFound(Exception):
pass pass
@ -674,7 +707,7 @@ class AnsibleModule(object):
see library/* for examples see library/* for examples
''' '''
self._name = os.path.basename(__file__) #initialize name until we can parse from options self._name = os.path.basename(__file__) # initialize name until we can parse from options
self.argument_spec = argument_spec self.argument_spec = argument_spec
self.supports_check_mode = supports_check_mode self.supports_check_mode = supports_check_mode
self.check_mode = False self.check_mode = False
@ -808,15 +841,15 @@ class AnsibleModule(object):
b_path = os.path.realpath(b_path) b_path = os.path.realpath(b_path)
path = to_native(b_path) path = to_native(b_path)
mode = params.get('mode', None) mode = params.get('mode', None)
owner = params.get('owner', None) owner = params.get('owner', None)
group = params.get('group', None) group = params.get('group', None)
# selinux related options # selinux related options
seuser = params.get('seuser', None) seuser = params.get('seuser', None)
serole = params.get('serole', None) serole = params.get('serole', None)
setype = params.get('setype', None) setype = params.get('setype', None)
selevel = params.get('selevel', None) selevel = params.get('selevel', None)
secontext = [seuser, serole, setype] secontext = [seuser, serole, setype]
if self.selinux_mls_enabled(): if self.selinux_mls_enabled():
@ -834,7 +867,6 @@ class AnsibleModule(object):
selevel=selevel, secontext=secontext, attributes=attributes, selevel=selevel, secontext=secontext, attributes=attributes,
) )
# Detect whether using selinux that is MLS-aware. # Detect whether using selinux that is MLS-aware.
# While this means you can set the level/range with # While this means you can set the level/range with
# selinux.lsetfilecon(), it may or may not mean that you # selinux.lsetfilecon(), it may or may not mean that you
@ -853,7 +885,7 @@ class AnsibleModule(object):
if not HAVE_SELINUX: if not HAVE_SELINUX:
seenabled = self.get_bin_path('selinuxenabled') seenabled = self.get_bin_path('selinuxenabled')
if seenabled is not None: if seenabled is not None:
(rc,out,err) = self.run_command(seenabled) (rc, out, err) = self.run_command(seenabled)
if rc == 0: if rc == 0:
self.fail_json(msg="Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!") self.fail_json(msg="Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!")
return False return False
@ -1127,7 +1159,7 @@ class AnsibleModule(object):
e = get_exception() e = get_exception()
if os.path.islink(b_path) and e.errno == errno.EPERM: # Can't set mode on symbolic links if os.path.islink(b_path) and e.errno == errno.EPERM: # Can't set mode on symbolic links
pass pass
elif e.errno in (errno.ENOENT, errno.ELOOP): # Can't set mode on broken symbolic links elif e.errno in (errno.ENOENT, errno.ELOOP): # Can't set mode on broken symbolic links
pass pass
else: else:
raise e raise e
@ -1154,7 +1186,7 @@ class AnsibleModule(object):
existing = self.get_file_attributes(b_path) existing = self.get_file_attributes(b_path)
if existing.get('attr_flags','') != attributes: if existing.get('attr_flags', '') != attributes:
attrcmd = self.get_bin_path('chattr') attrcmd = self.get_bin_path('chattr')
if attrcmd: if attrcmd:
attrcmd = [attrcmd, '=%s' % attributes, b_path] attrcmd = [attrcmd, '=%s' % attributes, b_path]
@ -1187,14 +1219,13 @@ class AnsibleModule(object):
rc, out, err = self.run_command(attrcmd) rc, out, err = self.run_command(attrcmd)
if rc == 0: if rc == 0:
res = out.split(' ')[0:2] res = out.split(' ')[0:2]
output['attr_flags'] = res[1].replace('-','').strip() output['attr_flags'] = res[1].replace('-', '').strip()
output['version'] = res[0].strip() output['version'] = res[0].strip()
output['attributes'] = format_attributes(output['attr_flags']) output['attributes'] = format_attributes(output['attr_flags'])
except: except:
pass pass
return output return output
def _symbolic_mode_to_octal(self, path_stat, symbolic_mode): def _symbolic_mode_to_octal(self, path_stat, symbolic_mode):
new_mode = stat.S_IMODE(path_stat.st_mode) new_mode = stat.S_IMODE(path_stat.st_mode)
@ -1217,7 +1248,7 @@ class AnsibleModule(object):
return new_mode return new_mode
def _apply_operation_to_mode(self, user, operator, mode_to_apply, current_mode): def _apply_operation_to_mode(self, user, operator, mode_to_apply, current_mode):
if operator == '=': if operator == '=':
if user == 'u': if user == 'u':
mask = stat.S_IRWXU | stat.S_ISUID mask = stat.S_IRWXU | stat.S_ISUID
elif user == 'g': elif user == 'g':
@ -1247,13 +1278,13 @@ class AnsibleModule(object):
X_perms = { X_perms = {
'u': {'X': stat.S_IXUSR}, 'u': {'X': stat.S_IXUSR},
'g': {'X': stat.S_IXGRP}, 'g': {'X': stat.S_IXGRP},
'o': {'X': stat.S_IXOTH} 'o': {'X': stat.S_IXOTH},
} }
else: else:
X_perms = { X_perms = {
'u': {'X': 0}, 'u': {'X': 0},
'g': {'X': 0}, 'g': {'X': 0},
'o': {'X': 0} 'o': {'X': 0},
} }
user_perms_to_modes = { user_perms_to_modes = {
@ -1265,7 +1296,8 @@ class AnsibleModule(object):
't': 0, 't': 0,
'u': prev_mode & stat.S_IRWXU, 'u': prev_mode & stat.S_IRWXU,
'g': (prev_mode & stat.S_IRWXG) << 3, 'g': (prev_mode & stat.S_IRWXG) << 3,
'o': (prev_mode & stat.S_IRWXO) << 6 }, 'o': (prev_mode & stat.S_IRWXO) << 6,
},
'g': { 'g': {
'r': stat.S_IRGRP, 'r': stat.S_IRGRP,
'w': stat.S_IWGRP, 'w': stat.S_IWGRP,
@ -1274,7 +1306,8 @@ class AnsibleModule(object):
't': 0, 't': 0,
'u': (prev_mode & stat.S_IRWXU) >> 3, 'u': (prev_mode & stat.S_IRWXU) >> 3,
'g': prev_mode & stat.S_IRWXG, 'g': prev_mode & stat.S_IRWXG,
'o': (prev_mode & stat.S_IRWXO) << 3 }, 'o': (prev_mode & stat.S_IRWXO) << 3,
},
'o': { 'o': {
'r': stat.S_IROTH, 'r': stat.S_IROTH,
'w': stat.S_IWOTH, 'w': stat.S_IWOTH,
@ -1283,14 +1316,17 @@ class AnsibleModule(object):
't': stat.S_ISVTX, 't': stat.S_ISVTX,
'u': (prev_mode & stat.S_IRWXU) >> 6, 'u': (prev_mode & stat.S_IRWXU) >> 6,
'g': (prev_mode & stat.S_IRWXG) >> 3, 'g': (prev_mode & stat.S_IRWXG) >> 3,
'o': prev_mode & stat.S_IRWXO } 'o': prev_mode & stat.S_IRWXO,
}
} }
# Insert X_perms into user_perms_to_modes # Insert X_perms into user_perms_to_modes
for key, value in X_perms.items(): for key, value in X_perms.items():
user_perms_to_modes[key].update(value) user_perms_to_modes[key].update(value)
or_reduce = lambda mode, perm: mode | user_perms_to_modes[user][perm] def or_reduce(mode, perm):
return mode | user_perms_to_modes[user][perm]
return reduce(or_reduce, perms, 0) return reduce(or_reduce, perms, 0)
def set_fs_attributes_if_different(self, file_args, changed, diff=None, expand=True): def set_fs_attributes_if_different(self, file_args, changed, diff=None, expand=True):
@ -1383,10 +1419,10 @@ class AnsibleModule(object):
def _handle_aliases(self, spec=None): def _handle_aliases(self, spec=None):
# this uses exceptions as it happens before we can safely call fail_json # this uses exceptions as it happens before we can safely call fail_json
aliases_results = {} #alias:canon aliases_results = {} # alias:canon
if spec is None: if spec is None:
spec = self.argument_spec spec = self.argument_spec
for (k,v) in spec.items(): for (k, v) in spec.items():
self._legal_inputs.append(k) self._legal_inputs.append(k)
aliases = v.get('aliases', None) aliases = v.get('aliases', None)
default = v.get('default', None) default = v.get('default', None)
@ -1409,7 +1445,7 @@ class AnsibleModule(object):
def _check_arguments(self, check_invalid_arguments): def _check_arguments(self, check_invalid_arguments):
self._syslog_facility = 'LOG_USER' self._syslog_facility = 'LOG_USER'
unsupported_parameters = set() unsupported_parameters = set()
for (k,v) in list(self.params.items()): for (k, v) in list(self.params.items()):
if k == '_ansible_check_mode' and v: if k == '_ansible_check_mode' and v:
self.check_mode = True self.check_mode = True
@ -1444,7 +1480,7 @@ class AnsibleModule(object):
elif check_invalid_arguments and k not in self._legal_inputs: elif check_invalid_arguments and k not in self._legal_inputs:
unsupported_parameters.add(k) unsupported_parameters.add(k)
#clean up internal params: # clean up internal params:
if k.startswith('_ansible_'): if k.startswith('_ansible_'):
del self.params[k] del self.params[k]
@ -1482,20 +1518,20 @@ class AnsibleModule(object):
if spec is None: if spec is None:
return return
for check in spec: for check in spec:
counts = [ self._count_terms([field]) for field in check ] counts = [self._count_terms([field]) for field in check]
non_zero = [ c for c in counts if c > 0 ] non_zero = [c for c in counts if c > 0]
if len(non_zero) > 0: if len(non_zero) > 0:
if 0 in counts: if 0 in counts:
self.fail_json(msg="parameters are required together: %s" % (check,)) self.fail_json(msg="parameters are required together: %s" % (check,))
def _check_required_arguments(self, spec=None, param=None ): def _check_required_arguments(self, spec=None, param=None):
''' ensure all required arguments are present ''' ''' ensure all required arguments are present '''
missing = [] missing = []
if spec is None: if spec is None:
spec = self.argument_spec spec = self.argument_spec
if param is None: if param is None:
param = self.params param = self.params
for (k,v) in spec.items(): for (k, v) in spec.items():
required = v.get('required', False) required = v.get('required', False)
if required and k not in param: if required and k not in param:
missing.append(k) missing.append(k)
@ -1534,8 +1570,8 @@ class AnsibleModule(object):
spec = self.argument_spec spec = self.argument_spec
if param is None: if param is None:
param = self.params param = self.params
for (k,v) in spec.items(): for (k, v) in spec.items():
choices = v.get('choices',None) choices = v.get('choices', None)
if choices is None: if choices is None:
continue continue
if isinstance(choices, SEQUENCETYPE) and not isinstance(choices, (binary_type, text_type)): if isinstance(choices, SEQUENCETYPE) and not isinstance(choices, (binary_type, text_type)):
@ -1561,8 +1597,8 @@ class AnsibleModule(object):
(param[k],) = overlap (param[k],) = overlap
if param[k] not in choices: if param[k] not in choices:
choices_str=",".join([to_native(c) for c in choices]) choices_str = ",".join([to_native(c) for c in choices])
msg="value of %s must be one of: %s, got: %s" % (k, choices_str, param[k]) msg = "value of %s must be one of: %s, got: %s" % (k, choices_str, param[k])
self.fail_json(msg=msg) self.fail_json(msg=msg)
else: else:
self.fail_json(msg="internal error: choices for argument %s are not iterable: %s" % (k, choices)) self.fail_json(msg="internal error: choices for argument %s are not iterable: %s" % (k, choices))
@ -1610,7 +1646,7 @@ class AnsibleModule(object):
if isinstance(value, string_types): if isinstance(value, string_types):
return value.split(",") return value.split(",")
elif isinstance(value, int) or isinstance(value, float): elif isinstance(value, int) or isinstance(value, float):
return [ str(value) ] return [str(value)]
raise TypeError('%s cannot be converted to a list' % type(value)) raise TypeError('%s cannot be converted to a list' % type(value))
@ -1703,14 +1739,12 @@ class AnsibleModule(object):
def _check_type_raw(self, value): def _check_type_raw(self, value):
return value return value
def _check_type_bytes(self, value): def _check_type_bytes(self, value):
try: try:
self.human_to_bytes(value) self.human_to_bytes(value)
except ValueError: except ValueError:
raise TypeError('%s cannot be converted to a Byte value' % type(value)) raise TypeError('%s cannot be converted to a Byte value' % type(value))
def _check_type_bits(self, value): def _check_type_bits(self, value):
try: try:
self.human_to_bytes(value, isbits=True) self.human_to_bytes(value, isbits=True)
@ -1761,7 +1795,7 @@ class AnsibleModule(object):
self._check_argument_values(spec, param[k]) self._check_argument_values(spec, param[k])
def _set_defaults(self, pre=True): def _set_defaults(self, pre=True):
for (k,v) in self.argument_spec.items(): for (k, v) in self.argument_spec.items():
default = v.get('default', None) default = v.get('default', None)
if pre is True: if pre is True:
# this prevents setting defaults on required items # this prevents setting defaults on required items
@ -1773,7 +1807,7 @@ class AnsibleModule(object):
self.params[k] = default self.params[k] = default
def _set_fallbacks(self): def _set_fallbacks(self):
for k,v in self.argument_spec.items(): for (k, v) in self.argument_spec.items():
fallback = v.get('fallback', (None,)) fallback = v.get('fallback', (None,))
fallback_strategy = fallback[0] fallback_strategy = fallback[0]
fallback_args = [] fallback_args = []
@ -1856,16 +1890,14 @@ class AnsibleModule(object):
log_args = dict() log_args = dict()
for param in self.params: for param in self.params:
canon = self.aliases.get(param, param) canon = self.aliases.get(param, param)
arg_opts = self.argument_spec.get(canon, {}) arg_opts = self.argument_spec.get(canon, {})
no_log = arg_opts.get('no_log', False) no_log = arg_opts.get('no_log', False)
if self.boolean(no_log): if self.boolean(no_log):
log_args[param] = 'NOT_LOGGING_PARAMETER' log_args[param] = 'NOT_LOGGING_PARAMETER'
# try to capture all passwords/passphrase named fields missed by no_log # try to capture all passwords/passphrase named fields missed by no_log
elif PASSWORD_MATCH.search(param) and \ elif PASSWORD_MATCH.search(param) and arg_opts.get('type', 'str') != 'bool' and not arg_opts.get('choices', False):
arg_opts.get('type', 'str') != 'bool' and \
not arg_opts.get('choices', False):
# skip boolean and enums as they are about 'password' state # skip boolean and enums as they are about 'password' state
log_args[param] = 'NOT_LOGGING_PASSWORD' log_args[param] = 'NOT_LOGGING_PASSWORD'
self.warn('Module did not set no_log for %s' % param) self.warn('Module did not set no_log for %s' % param)
@ -1885,11 +1917,10 @@ class AnsibleModule(object):
self.log(msg, log_args=log_args) self.log(msg, log_args=log_args)
def _set_cwd(self): def _set_cwd(self):
try: try:
cwd = os.getcwd() cwd = os.getcwd()
if not os.access(cwd, os.F_OK|os.R_OK): if not os.access(cwd, os.F_OK | os.R_OK):
raise Exception() raise Exception()
return cwd return cwd
except: except:
@ -1897,7 +1928,7 @@ class AnsibleModule(object):
# Try and move to a neutral location to prevent errors # Try and move to a neutral location to prevent errors
for cwd in [os.path.expandvars('$HOME'), tempfile.gettempdir()]: for cwd in [os.path.expandvars('$HOME'), tempfile.gettempdir()]:
try: try:
if os.access(cwd, os.F_OK|os.R_OK): if os.access(cwd, os.F_OK | os.R_OK):
os.chdir(cwd) os.chdir(cwd)
return cwd return cwd
except: except:
@ -2011,7 +2042,7 @@ class AnsibleModule(object):
def exit_json(self, **kwargs): def exit_json(self, **kwargs):
''' return from the module, without error ''' ''' return from the module, without error '''
if not 'changed' in kwargs: if 'changed' not in kwargs:
kwargs['changed'] = False kwargs['changed'] = False
self.do_cleanup_files() self.do_cleanup_files()
@ -2024,7 +2055,7 @@ class AnsibleModule(object):
assert 'msg' in kwargs, "implementation error -- msg to explain the error is required" assert 'msg' in kwargs, "implementation error -- msg to explain the error is required"
kwargs['failed'] = True kwargs['failed'] = True
if not 'changed' in kwargs: if 'changed' not in kwargs:
kwargs['changed'] = False kwargs['changed'] = False
self.do_cleanup_files() self.do_cleanup_files()
@ -2175,7 +2206,7 @@ class AnsibleModule(object):
native_suffix = os.path.basename(b_dest) native_suffix = os.path.basename(b_dest)
native_prefix = b('.ansible_tmp') native_prefix = b('.ansible_tmp')
try: try:
tmp_dest_fd, tmp_dest_name = tempfile.mkstemp( prefix=native_prefix, dir=native_dest_dir, suffix=native_suffix) tmp_dest_fd, tmp_dest_name = tempfile.mkstemp(prefix=native_prefix, dir=native_dest_dir, suffix=native_suffix)
except (OSError, IOError): except (OSError, IOError):
e = get_exception() e = get_exception()
self.fail_json(msg='The destination directory (%s) is not writable by the current user. Error was: %s' % (os.path.dirname(dest), e)) self.fail_json(msg='The destination directory (%s) is not writable by the current user. Error was: %s' % (os.path.dirname(dest), e))
@ -2261,7 +2292,6 @@ class AnsibleModule(object):
e = get_exception() e = get_exception()
self.fail_json(msg='Could not write data to file (%s) from (%s): %s' % (dest, src, e), exception=traceback.format_exc()) self.fail_json(msg='Could not write data to file (%s) from (%s): %s' % (dest, src, e), exception=traceback.format_exc())
def _read_from_pipes(self, rpipes, rfds, file_descriptor): def _read_from_pipes(self, rpipes, rfds, file_descriptor):
data = b('') data = b('')
if file_descriptor in rfds: if file_descriptor in rfds:
@ -2359,7 +2389,7 @@ class AnsibleModule(object):
# expand things like $HOME and ~ # expand things like $HOME and ~
if not shell: if not shell:
args = [ os.path.expanduser(os.path.expandvars(x)) for x in args if x is not None ] args = [os.path.expanduser(os.path.expandvars(x)) for x in args if x is not None]
rc = 0 rc = 0
msg = None msg = None
@ -2387,9 +2417,9 @@ class AnsibleModule(object):
# Clean out python paths set by ansiballz # Clean out python paths set by ansiballz
if 'PYTHONPATH' in os.environ: if 'PYTHONPATH' in os.environ:
pypaths = os.environ['PYTHONPATH'].split(':') pypaths = os.environ['PYTHONPATH'].split(':')
pypaths = [x for x in pypaths \ pypaths = [x for x in pypaths
if not x.endswith('/ansible_modlib.zip') \ if not x.endswith('/ansible_modlib.zip') and
and not x.endswith('/debug_dir')] not x.endswith('/debug_dir')]
os.environ['PYTHONPATH'] = ':'.join(pypaths) os.environ['PYTHONPATH'] = ':'.join(pypaths)
if not os.environ['PYTHONPATH']: if not os.environ['PYTHONPATH']:
del os.environ['PYTHONPATH'] del os.environ['PYTHONPATH']
@ -2510,7 +2540,7 @@ class AnsibleModule(object):
self.fail_json(rc=e.errno, msg=to_native(e), cmd=clean_args) self.fail_json(rc=e.errno, msg=to_native(e), cmd=clean_args)
except Exception: except Exception:
e = get_exception() e = get_exception()
self.log("Error Executing CMD:%s Exception:%s" % (clean_args,to_native(traceback.format_exc()))) self.log("Error Executing CMD:%s Exception:%s" % (clean_args, to_native(traceback.format_exc())))
self.fail_json(rc=257, msg=to_native(e), exception=traceback.format_exc(), cmd=clean_args) self.fail_json(rc=257, msg=to_native(e), exception=traceback.format_exc(), cmd=clean_args)
# Restore env settings # Restore env settings

View file

@ -25,9 +25,12 @@
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import json import json
from ansible.module_utils.urls import fetch_url from ansible.module_utils.urls import fetch_url
class Response(object): class Response(object):
def __init__(self, resp, info): def __init__(self, resp, info):

View file

@ -25,27 +25,29 @@
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
import signal
import socket import socket
import struct import struct
import signal
from ansible.module_utils.basic import get_exception from ansible.module_utils.basic import get_exception
from ansible.module_utils._text import to_bytes, to_native from ansible.module_utils._text import to_bytes, to_native
def send_data(s, data): def send_data(s, data):
packed_len = struct.pack('!Q',len(data)) packed_len = struct.pack('!Q', len(data))
return s.sendall(packed_len + data) return s.sendall(packed_len + data)
def recv_data(s): def recv_data(s):
header_len = 8 # size of a packed unsigned long long header_len = 8 # size of a packed unsigned long long
data = to_bytes("") data = to_bytes("")
while len(data) < header_len: while len(data) < header_len:
d = s.recv(header_len - len(data)) d = s.recv(header_len - len(data))
if not d: if not d:
return None return None
data += d data += d
data_len = struct.unpack('!Q',data[:header_len])[0] data_len = struct.unpack('!Q', data[:header_len])[0]
data = data[header_len:] data = data[header_len:]
while len(data) < data_len: while len(data) < data_len:
d = s.recv(data_len - len(data)) d = s.recv(data_len - len(data))
@ -54,6 +56,7 @@ def recv_data(s):
data += d data += d
return data return data
def exec_command(module, command): def exec_command(module, command):
try: try:
sf = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sf = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)

View file

@ -26,9 +26,11 @@
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class SQLParseError(Exception): class SQLParseError(Exception):
pass pass
class UnclosedQuoteError(SQLParseError): class UnclosedQuoteError(SQLParseError):
pass pass
@ -38,6 +40,7 @@ class UnclosedQuoteError(SQLParseError):
_PG_IDENTIFIER_TO_DOT_LEVEL = dict(database=1, schema=2, table=3, column=4, role=1) _PG_IDENTIFIER_TO_DOT_LEVEL = dict(database=1, schema=2, table=3, column=4, role=1)
_MYSQL_IDENTIFIER_TO_DOT_LEVEL = dict(database=1, table=2, column=3, role=1, vars=1) _MYSQL_IDENTIFIER_TO_DOT_LEVEL = dict(database=1, table=2, column=3, role=1, vars=1)
def _find_end_quote(identifier, quote_char): def _find_end_quote(identifier, quote_char):
accumulate = 0 accumulate = 0
while True: while True:
@ -47,12 +50,12 @@ def _find_end_quote(identifier, quote_char):
raise UnclosedQuoteError raise UnclosedQuoteError
accumulate = accumulate + quote accumulate = accumulate + quote
try: try:
next_char = identifier[quote+1] next_char = identifier[quote + 1]
except IndexError: except IndexError:
return accumulate return accumulate
if next_char == quote_char: if next_char == quote_char:
try: try:
identifier = identifier[quote+2:] identifier = identifier[quote + 2:]
accumulate = accumulate + 2 accumulate = accumulate + 2
except IndexError: except IndexError:
raise UnclosedQuoteError raise UnclosedQuoteError
@ -73,10 +76,10 @@ def _identifier_parse(identifier, quote_char):
already_quoted = False already_quoted = False
else: else:
if end_quote < len(identifier) - 1: if end_quote < len(identifier) - 1:
if identifier[end_quote+1] == '.': if identifier[end_quote + 1] == '.':
dot = end_quote + 1 dot = end_quote + 1
first_identifier = identifier[:dot] first_identifier = identifier[:dot]
next_identifier = identifier[dot+1:] next_identifier = identifier[dot + 1:]
further_identifiers = _identifier_parse(next_identifier, quote_char) further_identifiers = _identifier_parse(next_identifier, quote_char)
further_identifiers.insert(0, first_identifier) further_identifiers.insert(0, first_identifier)
else: else:
@ -88,19 +91,19 @@ def _identifier_parse(identifier, quote_char):
try: try:
dot = identifier.index('.') dot = identifier.index('.')
except ValueError: except ValueError:
identifier = identifier.replace(quote_char, quote_char*2) identifier = identifier.replace(quote_char, quote_char * 2)
identifier = ''.join((quote_char, identifier, quote_char)) identifier = ''.join((quote_char, identifier, quote_char))
further_identifiers = [identifier] further_identifiers = [identifier]
else: else:
if dot == 0 or dot >= len(identifier) - 1: if dot == 0 or dot >= len(identifier) - 1:
identifier = identifier.replace(quote_char, quote_char*2) identifier = identifier.replace(quote_char, quote_char * 2)
identifier = ''.join((quote_char, identifier, quote_char)) identifier = ''.join((quote_char, identifier, quote_char))
further_identifiers = [identifier] further_identifiers = [identifier]
else: else:
first_identifier = identifier[:dot] first_identifier = identifier[:dot]
next_identifier = identifier[dot+1:] next_identifier = identifier[dot + 1:]
further_identifiers = _identifier_parse(next_identifier, quote_char) further_identifiers = _identifier_parse(next_identifier, quote_char)
first_identifier = first_identifier.replace(quote_char, quote_char*2) first_identifier = first_identifier.replace(quote_char, quote_char * 2)
first_identifier = ''.join((quote_char, first_identifier, quote_char)) first_identifier = ''.join((quote_char, first_identifier, quote_char))
further_identifiers.insert(0, first_identifier) further_identifiers.insert(0, first_identifier)
@ -113,6 +116,7 @@ def pg_quote_identifier(identifier, id_type):
raise SQLParseError('PostgreSQL does not support %s with more than %i dots' % (id_type, _PG_IDENTIFIER_TO_DOT_LEVEL[id_type])) raise SQLParseError('PostgreSQL does not support %s with more than %i dots' % (id_type, _PG_IDENTIFIER_TO_DOT_LEVEL[id_type]))
return '.'.join(identifier_fragments) return '.'.join(identifier_fragments)
def mysql_quote_identifier(identifier, id_type): def mysql_quote_identifier(identifier, id_type):
identifier_fragments = _identifier_parse(identifier, quote_char='`') identifier_fragments = _identifier_parse(identifier, quote_char='`')
if len(identifier_fragments) > _MYSQL_IDENTIFIER_TO_DOT_LEVEL[id_type]: if len(identifier_fragments) > _MYSQL_IDENTIFIER_TO_DOT_LEVEL[id_type]:

View file

@ -217,7 +217,7 @@ class AnsibleDockerClient(Client):
docker_host=self._get_value('docker_host', params['docker_host'], 'DOCKER_HOST', docker_host=self._get_value('docker_host', params['docker_host'], 'DOCKER_HOST',
DEFAULT_DOCKER_HOST), DEFAULT_DOCKER_HOST),
tls_hostname=self._get_value('tls_hostname', params['tls_hostname'], tls_hostname=self._get_value('tls_hostname', params['tls_hostname'],
'DOCKER_TLS_HOSTNAME', 'localhost'), 'DOCKER_TLS_HOSTNAME', 'localhost'),
api_version=self._get_value('api_version', params['api_version'], 'DOCKER_API_VERSION', api_version=self._get_value('api_version', params['api_version'], 'DOCKER_API_VERSION',
'auto'), 'auto'),
cacert_path=self._get_value('cacert_path', params['cacert_path'], 'DOCKER_CERT_PATH', None), cacert_path=self._get_value('cacert_path', params['cacert_path'], 'DOCKER_CERT_PATH', None),
@ -244,7 +244,7 @@ class AnsibleDockerClient(Client):
def _get_tls_config(self, **kwargs): def _get_tls_config(self, **kwargs):
self.log("get_tls_config:") self.log("get_tls_config:")
for key in kwargs: for key in kwargs:
self.log(" %s: %s" % (key, kwargs[key])) self.log(" %s: %s" % (key, kwargs[key]))
try: try:
tls_config = TLSConfig(**kwargs) tls_config = TLSConfig(**kwargs)
return tls_config return tls_config
@ -327,11 +327,10 @@ class AnsibleDockerClient(Client):
def _handle_ssl_error(self, error): def _handle_ssl_error(self, error):
match = re.match(r"hostname.*doesn\'t match (\'.*\')", str(error)) match = re.match(r"hostname.*doesn\'t match (\'.*\')", str(error))
if match: if match:
msg = "You asked for verification that Docker host name matches %s. The actual hostname is %s. " \ self.fail("You asked for verification that Docker host name matches %s. The actual hostname is %s. "
"Most likely you need to set DOCKER_TLS_HOSTNAME or pass tls_hostname with a value of %s. " \ "Most likely you need to set DOCKER_TLS_HOSTNAME or pass tls_hostname with a value of %s. "
"You may also use TLS without verification by setting the tls parameter to true." \ "You may also use TLS without verification by setting the tls parameter to true."
% (self.auth_params['tls_hostname'], match.group(1), match.group(1)) % (self.auth_params['tls_hostname'], match.group(1), match.group(1)))
self.fail(msg)
self.fail("SSL Exception: %s" % (error)) self.fail("SSL Exception: %s" % (error))
def get_container(self, name=None): def get_container(self, name=None):
@ -448,5 +447,3 @@ class AnsibleDockerClient(Client):
new_tag = self.find_image(name, tag) new_tag = self.find_image(name, tag)
return new_tag, old_tag == new_tag return new_tag, old_tag == new_tag

View file

@ -34,7 +34,7 @@ from ansible.module_utils.cloud import CloudRetry
try: try:
import boto import boto
import boto.ec2 #boto does weird import stuff import boto.ec2 # boto does weird import stuff
HAS_BOTO = True HAS_BOTO = True
except ImportError: except ImportError:
HAS_BOTO = False HAS_BOTO = False
@ -54,6 +54,7 @@ except:
from ansible.module_utils.six import string_types, binary_type, text_type from ansible.module_utils.six import string_types, binary_type, text_type
class AnsibleAWSError(Exception): class AnsibleAWSError(Exception):
pass pass
@ -98,6 +99,7 @@ def boto3_conn(module, conn_type=None, resource=None, region=None, endpoint=None
module.fail_json(msg='There is an issue in the code of the module. You must specify either both, resource or client to the conn_type ' module.fail_json(msg='There is an issue in the code of the module. You must specify either both, resource or client to the conn_type '
'parameter in the boto3_conn function call') 'parameter in the boto3_conn function call')
def _boto3_conn(conn_type=None, resource=None, region=None, endpoint=None, **params): def _boto3_conn(conn_type=None, resource=None, region=None, endpoint=None, **params):
profile = params.pop('profile_name', None) profile = params.pop('profile_name', None)
@ -120,6 +122,7 @@ def _boto3_conn(conn_type=None, resource=None, region=None, endpoint=None, **par
boto3_inventory_conn = _boto3_conn boto3_inventory_conn = _boto3_conn
def aws_common_argument_spec(): def aws_common_argument_spec():
return dict( return dict(
ec2_url=dict(), ec2_url=dict(),
@ -291,6 +294,7 @@ def ec2_connect(module):
return ec2 return ec2
def paging(pause=0, marker_property='marker'): def paging(pause=0, marker_property='marker'):
""" Adds paging to boto retrieval functions that support a 'marker' """ Adds paging to boto retrieval functions that support a 'marker'
this is configurable as not all boto functions seem to use the this is configurable as not all boto functions seem to use the
@ -330,7 +334,6 @@ def camel_dict_to_snake_dict(camel_dict):
return all_cap_re.sub(r'\1_\2', s1).lower() return all_cap_re.sub(r'\1_\2', s1).lower()
def value_is_list(camel_list): def value_is_list(camel_list):
checked_list = [] checked_list = []
@ -344,7 +347,6 @@ def camel_dict_to_snake_dict(camel_dict):
return checked_list return checked_list
snake_dict = {} snake_dict = {}
for k, v in camel_dict.items(): for k, v in camel_dict.items():
if isinstance(v, dict): if isinstance(v, dict):
@ -403,7 +405,7 @@ def ansible_dict_to_boto3_filter_list(filters_dict):
""" """
filters_list = [] filters_list = []
for k,v in filters_dict.items(): for k, v in filters_dict.items():
filter_dict = {'Name': k} filter_dict = {'Name': k}
if isinstance(v, string_types): if isinstance(v, string_types):
filter_dict['Values'] = [v] filter_dict['Values'] = [v]
@ -470,7 +472,7 @@ def ansible_dict_to_boto3_tag_list(tags_dict, tag_name_key_name='Key', tag_value
""" """
tags_list = [] tags_list = []
for k,v in tags_dict.items(): for k, v in tags_dict.items():
tags_list.append({tag_name_key_name: k, tag_value_key_name: v}) tags_list.append({tag_name_key_name: k, tag_value_key_name: v})
return tags_list return tags_list
@ -491,7 +493,6 @@ def get_ec2_security_group_ids_from_names(sec_group_list, ec2_connection, vpc_id
else: else:
return sg.name return sg.name
def get_sg_id(sg, boto3): def get_sg_id(sg, boto3):
if boto3: if boto3:
@ -520,7 +521,7 @@ def get_ec2_security_group_ids_from_names(sec_group_list, ec2_connection, vpc_id
all_sec_groups = ec2_connection.describe_security_groups()['SecurityGroups'] all_sec_groups = ec2_connection.describe_security_groups()['SecurityGroups']
else: else:
if vpc_id: if vpc_id:
filters = { 'vpc-id': vpc_id } filters = {'vpc-id': vpc_id}
all_sec_groups = ec2_connection.get_all_security_groups(filters=filters) all_sec_groups = ec2_connection.get_all_security_groups(filters=filters)
else: else:
all_sec_groups = ec2_connection.get_all_security_groups() all_sec_groups = ec2_connection.get_all_security_groups()
@ -536,7 +537,7 @@ def get_ec2_security_group_ids_from_names(sec_group_list, ec2_connection, vpc_id
if len(still_unmatched) > 0: if len(still_unmatched) > 0:
raise ValueError("The following group names are not valid: %s" % ', '.join(still_unmatched)) raise ValueError("The following group names are not valid: %s" % ', '.join(still_unmatched))
sec_group_id_list += [ str(get_sg_id(all_sg, boto3)) for all_sg in all_sec_groups if str(get_sg_name(all_sg, boto3)) in sec_group_name_list ] sec_group_id_list += [str(get_sg_id(all_sg, boto3)) for all_sg in all_sec_groups if str(get_sg_name(all_sg, boto3)) in sec_group_name_list]
return sec_group_id_list return sec_group_id_list

View file

@ -56,7 +56,6 @@ def f5_argument_spec():
server_port=dict( server_port=dict(
type='int', type='int',
default=443, default=443,
required=False,
fallback=(env_fallback, ['F5_SERVER_PORT']) fallback=(env_fallback, ['F5_SERVER_PORT'])
), ),
state=dict( state=dict(
@ -80,7 +79,7 @@ def f5_parse_arguments(module):
import ssl import ssl
if not hasattr(ssl, 'SSLContext'): if not hasattr(ssl, 'SSLContext'):
module.fail_json( module.fail_json(
msg="bigsuds does not support verifying certificates with python < 2.7.9." \ msg="bigsuds does not support verifying certificates with python < 2.7.9."
"Either update python or set validate_certs=False on the task'") "Either update python or set validate_certs=False on the task'")
return ( return (
@ -122,26 +121,22 @@ def bigip_api(bigip, user, password, validate_certs, port=443):
# Fully Qualified name (with the partition) # Fully Qualified name (with the partition)
def fq_name(partition,name): def fq_name(partition, name):
if name is not None and not name.startswith('/'): if name is not None and not name.startswith('/'):
return '/%s/%s' % (partition,name) return '/%s/%s' % (partition, name)
return name return name
# Fully Qualified name (with partition) for a list # Fully Qualified name (with partition) for a list
def fq_list_names(partition,list_names): def fq_list_names(partition, list_names):
if list_names is None: if list_names is None:
return None return None
return map(lambda x: fq_name(partition,x),list_names) return map(lambda x: fq_name(partition, x), list_names)
# New style # New style
from abc import ABCMeta, abstractproperty from abc import ABCMeta, abstractproperty
from ansible.module_utils.six import with_metaclass
from collections import defaultdict from collections import defaultdict
try: try:
@ -158,7 +153,7 @@ except ImportError:
from ansible.module_utils.basic import * from ansible.module_utils.basic import *
from ansible.module_utils.six import iteritems from ansible.module_utils.six import iteritems, with_metaclass
F5_COMMON_ARGS = dict( F5_COMMON_ARGS = dict(
@ -187,7 +182,6 @@ F5_COMMON_ARGS = dict(
server_port=dict( server_port=dict(
type='int', type='int',
default=443, default=443,
required=False,
fallback=(env_fallback, ['F5_SERVER_PORT']) fallback=(env_fallback, ['F5_SERVER_PORT'])
), ),
state=dict( state=dict(
@ -286,7 +280,7 @@ class AnsibleF5Parameters(object):
def __init__(self, params=None): def __init__(self, params=None):
self._values = defaultdict(lambda: None) self._values = defaultdict(lambda: None)
if params: if params:
for k,v in iteritems(params): for k, v in iteritems(params):
if self.api_map is not None and k in self.api_map: if self.api_map is not None and k in self.api_map:
dict_to_use = self.api_map dict_to_use = self.api_map
map_key = self.api_map[k] map_key = self.api_map[k]

View file

@ -33,31 +33,31 @@ from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.pycompat24 import get_exception from ansible.module_utils.pycompat24 import get_exception
#check for pyFG lib # check for pyFG lib
try: try:
from pyFG import FortiOS, FortiConfig from pyFG import FortiOS, FortiConfig
from pyFG.exceptions import CommandExecutionException, FailedCommit from pyFG.exceptions import CommandExecutionException, FailedCommit
HAS_PYFG=True HAS_PYFG = True
except ImportError: except ImportError:
HAS_PYFG=False HAS_PYFG = False
fortios_argument_spec = dict( fortios_argument_spec = dict(
file_mode = dict(type='bool', default=False), file_mode=dict(type='bool', default=False),
config_file = dict(type='path'), config_file=dict(type='path'),
host = dict( ), host=dict(),
username = dict( ), username=dict(),
password = dict(type='str', no_log=True ), password=dict(type='str', no_log=True),
timeout = dict(type='int', default=60), timeout=dict(type='int', default=60),
vdom = dict(type='str', default=None ), vdom=dict(type='str'),
backup = dict(type='bool', default=False), backup=dict(type='bool', default=False),
backup_path = dict(type='path'), backup_path=dict(type='path'),
backup_filename = dict(type='str'), backup_filename=dict(type='str'),
) )
fortios_required_if = [ fortios_required_if = [
['file_mode', False, ['host', 'username', 'password']], ['file_mode', False, ['host', 'username', 'password']],
['file_mode', True, ['config_file']], ['file_mode', True, ['config_file']],
['backup', True , ['backup_path'] ], ['backup', True, ['backup_path']],
] ]
fortios_mutually_exclusive = [ fortios_mutually_exclusive = [
@ -67,12 +67,12 @@ fortios_mutually_exclusive = [
] ]
fortios_error_codes = { fortios_error_codes = {
'-3':"Object not found", '-3': "Object not found",
'-61':"Command error" '-61': "Command error"
} }
def backup(module,running_config): def backup(module, running_config):
backup_path = module.params['backup_path'] backup_path = module.params['backup_path']
backup_filename = module.params['backup_filename'] backup_filename = module.params['backup_filename']
if not os.path.exists(backup_path): if not os.path.exists(backup_path):
@ -91,8 +91,6 @@ def backup(module,running_config):
module.fail_json(msg="Can't create backup file {0} Permission denied ?".format(filename)) module.fail_json(msg="Can't create backup file {0} Permission denied ?".format(filename))
class AnsibleFortios(object): class AnsibleFortios(object):
def __init__(self, module): def __init__(self, module):
if not HAS_PYFG: if not HAS_PYFG:
@ -103,7 +101,6 @@ class AnsibleFortios(object):
} }
self.module = module self.module = module
def _connect(self): def _connect(self):
if self.module.params['file_mode']: if self.module.params['file_mode']:
self.forti_device = FortiOS('') self.forti_device = FortiOS('')
@ -122,11 +119,10 @@ class AnsibleFortios(object):
e = get_exception() e = get_exception()
self.module.fail_json(msg='Error connecting device. %s' % e) self.module.fail_json(msg='Error connecting device. %s' % e)
def load_config(self, path): def load_config(self, path):
self.path = path self.path = path
self._connect() self._connect()
#load in file_mode # load in file_mode
if self.module.params['file_mode']: if self.module.params['file_mode']:
try: try:
f = open(self.module.params['config_file'], 'r') f = open(self.module.params['config_file'], 'r')
@ -135,10 +131,10 @@ class AnsibleFortios(object):
except IOError: except IOError:
e = get_exception() e = get_exception()
self.module.fail_json(msg='Error reading configuration file. %s' % e) self.module.fail_json(msg='Error reading configuration file. %s' % e)
self.forti_device.load_config(config_text=running, path = path) self.forti_device.load_config(config_text=running, path=path)
else: else:
#get config # get config
try: try:
self.forti_device.load_config(path=path) self.forti_device.load_config(path=path)
except Exception: except Exception:
@ -146,22 +142,21 @@ class AnsibleFortios(object):
e = get_exception() e = get_exception()
self.module.fail_json(msg='Error reading running config. %s' % e) self.module.fail_json(msg='Error reading running config. %s' % e)
#set configs in object # set configs in object
self.result['running_config'] = self.forti_device.running_config.to_text() self.result['running_config'] = self.forti_device.running_config.to_text()
self.candidate_config = self.forti_device.candidate_config self.candidate_config = self.forti_device.candidate_config
#backup if needed # backup if needed
if self.module.params['backup']: if self.module.params['backup']:
backup(self.module, self.forti_device.running_config.to_text()) backup(self.module, self.forti_device.running_config.to_text())
def apply_changes(self): def apply_changes(self):
change_string = self.forti_device.compare_config() change_string = self.forti_device.compare_config()
if change_string: if change_string:
self.result['change_string'] = change_string self.result['change_string'] = change_string
self.result['changed'] = True self.result['changed'] = True
#Commit if not check mode # Commit if not check mode
if change_string and not self.module.check_mode: if change_string and not self.module.check_mode:
if self.module.params['file_mode']: if self.module.params['file_mode']:
try: try:
@ -175,35 +170,31 @@ class AnsibleFortios(object):
try: try:
self.forti_device.commit() self.forti_device.commit()
except FailedCommit: except FailedCommit:
#Something's wrong (rollback is automatic) # Something's wrong (rollback is automatic)
self.forti_device.close() self.forti_device.close()
e = get_exception() e = get_exception()
error_list = self.get_error_infos(e) error_list = self.get_error_infos(e)
self.module.fail_json(msg_error_list=error_list, msg="Unable to commit change, check your args, the error was %s" % e.message ) self.module.fail_json(msg_error_list=error_list, msg="Unable to commit change, check your args, the error was %s" % e.message)
self.forti_device.close() self.forti_device.close()
self.module.exit_json(**self.result) self.module.exit_json(**self.result)
def del_block(self, block_id): def del_block(self, block_id):
self.forti_device.candidate_config[self.path].del_block(block_id) self.forti_device.candidate_config[self.path].del_block(block_id)
def add_block(self, block_id, block): def add_block(self, block_id, block):
self.forti_device.candidate_config[self.path][block_id] = block self.forti_device.candidate_config[self.path][block_id] = block
def get_error_infos(self, cli_errors): def get_error_infos(self, cli_errors):
error_list = [] error_list = []
for errors in cli_errors.args: for errors in cli_errors.args:
for error in errors: for error in errors:
error_code = error[0] error_code = error[0]
error_string = error[1] error_string = error[1]
error_type = fortios_error_codes.get(error_code,"unknown") error_type = fortios_error_codes.get(error_code, "unknown")
error_list.append(dict(error_code=error_code, error_type=error_type, error_string= error_string)) error_list.append(dict(error_code=error_code, error_type=error_type, error_string=error_string))
return error_list return error_list
def get_empty_configuration_block(self, block_name, block_type): def get_empty_configuration_block(self, block_name, block_type):
return FortiConfig(block_name, block_type) return FortiConfig(block_name, block_type)

View file

@ -27,9 +27,6 @@
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# #
from ansible.module_utils.gcp import gcp_connect
from ansible.module_utils.gcp import unexpected_error_msg as gcp_error
try: try:
from libcloud.dns.types import Provider from libcloud.dns.types import Provider
from libcloud.dns.providers import get_driver from libcloud.dns.providers import get_driver
@ -37,9 +34,13 @@ try:
except ImportError: except ImportError:
HAS_LIBCLOUD_BASE = False HAS_LIBCLOUD_BASE = False
from ansible.module_utils.gcp import gcp_connect
from ansible.module_utils.gcp import unexpected_error_msg as gcp_error
USER_AGENT_PRODUCT = "Ansible-gcdns" USER_AGENT_PRODUCT = "Ansible-gcdns"
USER_AGENT_VERSION = "v1" USER_AGENT_VERSION = "v1"
def gcdns_connect(module, provider=None): def gcdns_connect(module, provider=None):
"""Return a GCP connection for Google Cloud DNS.""" """Return a GCP connection for Google Cloud DNS."""
if not HAS_LIBCLOUD_BASE: if not HAS_LIBCLOUD_BASE:
@ -48,6 +49,7 @@ def gcdns_connect(module, provider=None):
provider = provider or Provider.GOOGLE provider = provider or Provider.GOOGLE
return gcp_connect(module, provider, get_driver, USER_AGENT_PRODUCT, USER_AGENT_VERSION) return gcp_connect(module, provider, get_driver, USER_AGENT_PRODUCT, USER_AGENT_VERSION)
def unexpected_error_msg(error): def unexpected_error_msg(error):
"""Create an error string based on passed in error.""" """Create an error string based on passed in error."""
return gcp_error(error) return gcp_error(error)

View file

@ -25,10 +25,6 @@
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
from ansible.module_utils.gcp import gcp_connect
from ansible.module_utils.gcp import unexpected_error_msg as gcp_error
try: try:
from libcloud.compute.types import Provider from libcloud.compute.types import Provider
@ -37,9 +33,13 @@ try:
except ImportError: except ImportError:
HAS_LIBCLOUD_BASE = False HAS_LIBCLOUD_BASE = False
from ansible.module_utils.gcp import gcp_connect
from ansible.module_utils.gcp import unexpected_error_msg as gcp_error
USER_AGENT_PRODUCT = "Ansible-gce" USER_AGENT_PRODUCT = "Ansible-gce"
USER_AGENT_VERSION = "v1" USER_AGENT_VERSION = "v1"
def gce_connect(module, provider=None): def gce_connect(module, provider=None):
"""Return a GCP connection for Google Compute Engine.""" """Return a GCP connection for Google Compute Engine."""
if not HAS_LIBCLOUD_BASE: if not HAS_LIBCLOUD_BASE:
@ -48,6 +48,7 @@ def gce_connect(module, provider=None):
return gcp_connect(module, provider, get_driver, USER_AGENT_PRODUCT, USER_AGENT_VERSION) return gcp_connect(module, provider, get_driver, USER_AGENT_PRODUCT, USER_AGENT_VERSION)
def unexpected_error_msg(error): def unexpected_error_msg(error):
"""Create an error string based on passed in error.""" """Create an error string based on passed in error."""
return gcp_error(error) return gcp_error(error)

View file

@ -502,8 +502,7 @@ class GCPUtils(object):
@staticmethod @staticmethod
def underscore_to_camel(txt): def underscore_to_camel(txt):
return txt.split('_')[0] + ''.join(x.capitalize() return txt.split('_')[0] + ''.join(x.capitalize() or '_' for x in txt.split('_')[1:])
or '_' for x in txt.split('_')[1:])
@staticmethod @staticmethod
def remove_non_gcp_params(params): def remove_non_gcp_params(params):
@ -626,7 +625,7 @@ class GCPUtils(object):
# TODO(supertom): Isolate 'build-new-request' stuff. # TODO(supertom): Isolate 'build-new-request' stuff.
resource_name_singular = GCPUtils.get_entity_name_from_resource_name( resource_name_singular = GCPUtils.get_entity_name_from_resource_name(
resource_name) resource_name)
if op_resp['operationType'] == 'insert' or not 'entity_name' in parsed_url: if op_resp['operationType'] == 'insert' or 'entity_name' not in parsed_url:
parsed_url['entity_name'] = GCPUtils.parse_gcp_url(op_resp['targetLink'])[ parsed_url['entity_name'] = GCPUtils.parse_gcp_url(op_resp['targetLink'])[
'entity_name'] 'entity_name']
args = {'project': project_id, args = {'project': project_id,

View file

@ -82,9 +82,9 @@ def infinibox_argument_spec():
"""Return standard base dictionary used for the argument_spec argument in AnsibleModule""" """Return standard base dictionary used for the argument_spec argument in AnsibleModule"""
return dict( return dict(
system = dict(required=True), system=dict(required=True),
user = dict(), user=dict(),
password = dict(no_log=True), password=dict(no_log=True),
) )

View file

@ -29,6 +29,7 @@ try:
except ImportError: except ImportError:
import simplejson as json import simplejson as json
# NB: a copy of this function exists in ../../modules/core/async_wrapper.py. Ensure any # NB: a copy of this function exists in ../../modules/core/async_wrapper.py. Ensure any
# changes are propagated there. # changes are propagated there.
def _filter_non_json_lines(data): def _filter_non_json_lines(data):

View file

@ -47,12 +47,13 @@ ARGS_DEFAULT_VALUE = {
'timeout': 10 'timeout': 10
} }
def check_args(module, warnings): def check_args(module, warnings):
provider = module.params['provider'] or {} provider = module.params['provider'] or {}
for key in junos_argument_spec: for key in junos_argument_spec:
if key not in ('provider',) and module.params[key]: if key not in ('provider',) and module.params[key]:
warnings.append('argument %s has been deprecated and will be ' warnings.append('argument %s has been deprecated and will be '
'removed in a future version' % key) 'removed in a future version' % key)
# set argument's default value if not provided in input # set argument's default value if not provided in input
# This is done to avoid unwanted argument deprecation warning # This is done to avoid unwanted argument deprecation warning
@ -66,6 +67,7 @@ def check_args(module, warnings):
if provider.get(param): if provider.get(param):
module.no_log_values.update(return_values(provider[param])) module.no_log_values.update(return_values(provider[param]))
def _validate_rollback_id(module, value): def _validate_rollback_id(module, value):
try: try:
if not 0 <= int(value) <= 49: if not 0 <= int(value) <= 49:
@ -73,6 +75,7 @@ def _validate_rollback_id(module, value):
except ValueError: except ValueError:
module.fail_json(msg='rollback must be between 0 and 49') module.fail_json(msg='rollback must be between 0 and 49')
def load_configuration(module, candidate=None, action='merge', rollback=None, format='xml'): def load_configuration(module, candidate=None, action='merge', rollback=None, format='xml'):
if all((candidate is None, rollback is None)): if all((candidate is None, rollback is None)):
@ -117,6 +120,7 @@ def load_configuration(module, candidate=None, action='merge', rollback=None, fo
cfg.append(candidate) cfg.append(candidate)
return send_request(module, obj) return send_request(module, obj)
def get_configuration(module, compare=False, format='xml', rollback='0'): def get_configuration(module, compare=False, format='xml', rollback='0'):
if format not in CONFIG_FORMATS: if format not in CONFIG_FORMATS:
module.fail_json(msg='invalid config format specified') module.fail_json(msg='invalid config format specified')
@ -127,6 +131,7 @@ def get_configuration(module, compare=False, format='xml', rollback='0'):
xattrs['rollback'] = str(rollback) xattrs['rollback'] = str(rollback)
return send_request(module, Element('get-configuration', xattrs)) return send_request(module, Element('get-configuration', xattrs))
def commit_configuration(module, confirm=False, check=False, comment=None, confirm_timeout=None): def commit_configuration(module, confirm=False, check=False, comment=None, confirm_timeout=None):
obj = Element('commit-configuration') obj = Element('commit-configuration')
if confirm: if confirm:
@ -141,6 +146,7 @@ def commit_configuration(module, confirm=False, check=False, comment=None, confi
subele.text = str(confirm_timeout) subele.text = str(confirm_timeout)
return send_request(module, obj) return send_request(module, obj)
def command(module, command, format='text', rpc_only=False): def command(module, command, format='text', rpc_only=False):
xattrs = {'format': format} xattrs = {'format': format}
if rpc_only: if rpc_only:
@ -148,8 +154,14 @@ def command(module, command, format='text', rpc_only=False):
xattrs['format'] = 'text' xattrs['format'] = 'text'
return send_request(module, Element('command', xattrs, text=command)) return send_request(module, Element('command', xattrs, text=command))
lock_configuration = lambda x: send_request(x, Element('lock-configuration'))
unlock_configuration = lambda x: send_request(x, Element('unlock-configuration')) def lock_configuration(x):
return send_request(x, Element('lock-configuration'))
def unlock_configuration(x):
return send_request(x, Element('unlock-configuration'))
@contextmanager @contextmanager
def locked_config(module): def locked_config(module):
@ -159,6 +171,7 @@ def locked_config(module):
finally: finally:
unlock_configuration(module) unlock_configuration(module)
def get_diff(module): def get_diff(module):
reply = get_configuration(module, compare=True, format='text') reply = get_configuration(module, compare=True, format='text')
@ -166,6 +179,7 @@ def get_diff(module):
if output is not None: if output is not None:
return to_text(output.text, encoding='latin1').strip() return to_text(output.text, encoding='latin1').strip()
def load_config(module, candidate, warnings, action='merge', commit=False, format='xml', def load_config(module, candidate, warnings, action='merge', commit=False, format='xml',
comment=None, confirm=False, confirm_timeout=None): comment=None, confirm=False, confirm_timeout=None):
@ -192,5 +206,6 @@ def load_config(module, candidate, warnings, action='merge', commit=False, forma
return diff return diff
def get_param(module, key): def get_param(module, key):
return module.params[key] or module.params['provider'].get(key) return module.params[key] or module.params['provider'].get(key)

View file

@ -153,7 +153,7 @@ def not_in_host_file(self, host):
if tokens[0].find(HASHED_KEY_MAGIC) == 0: if tokens[0].find(HASHED_KEY_MAGIC) == 0:
# this is a hashed known host entry # this is a hashed known host entry
try: try:
(kn_salt,kn_host) = tokens[0][len(HASHED_KEY_MAGIC):].split("|",2) (kn_salt, kn_host) = tokens[0][len(HASHED_KEY_MAGIC):].split("|", 2)
hash = hmac.new(kn_salt.decode('base64'), digestmod=sha1) hash = hmac.new(kn_salt.decode('base64'), digestmod=sha1)
hash.update(host) hash.update(host)
if hash.digest() == kn_host.decode('base64'): if hash.digest() == kn_host.decode('base64'):
@ -204,7 +204,7 @@ def add_host_key(module, fqdn, port=22, key_type="rsa", create_dir=False):
if rc != 0 or not out: if rc != 0 or not out:
msg = 'failed to retrieve hostkey' msg = 'failed to retrieve hostkey'
if not out: if not out:
msg += '. "%s" returned no matches.' % this_cmd msg += '. "%s" returned no matches.' % this_cmd
else: else:
msg += ' using command "%s". [stdout]: %s' % (this_cmd, out) msg += ' using command "%s". [stdout]: %s' % (this_cmd, out)

View file

@ -38,12 +38,14 @@ except ImportError:
# httplib/http.client connection using unix domain socket # httplib/http.client connection using unix domain socket
import socket import socket
import ssl import ssl
try: try:
from httplib import HTTPConnection, HTTPSConnection from httplib import HTTPConnection, HTTPSConnection
except ImportError: except ImportError:
# Python 3 # Python 3
from http.client import HTTPConnection, HTTPSConnection from http.client import HTTPConnection, HTTPSConnection
class UnixHTTPConnection(HTTPConnection): class UnixHTTPConnection(HTTPConnection):
def __init__(self, path): def __init__(self, path):
HTTPConnection.__init__(self, 'localhost') HTTPConnection.__init__(self, 'localhost')
@ -54,11 +56,13 @@ class UnixHTTPConnection(HTTPConnection):
sock.connect(self.path) sock.connect(self.path)
self.sock = sock self.sock = sock
class LXDClientException(Exception): class LXDClientException(Exception):
def __init__(self, msg, **kwargs): def __init__(self, msg, **kwargs):
self.msg = msg self.msg = msg
self.kwargs = kwargs self.kwargs = kwargs
class LXDClient(object): class LXDClient(object):
def __init__(self, url, key_file=None, cert_file=None, debug=False): def __init__(self, url, key_file=None, cert_file=None, debug=False):
"""LXD Client. """LXD Client.

View file

@ -35,6 +35,7 @@ try:
except ImportError: except ImportError:
mysqldb_found = False mysqldb_found = False
def mysql_connect(module, login_user=None, login_password=None, config_file='', ssl_cert=None, ssl_key=None, ssl_ca=None, db=None, cursor_class=None, def mysql_connect(module, login_user=None, login_password=None, config_file='', ssl_cert=None, ssl_key=None, ssl_ca=None, db=None, cursor_class=None,
connect_timeout=30): connect_timeout=30):
config = {} config = {}

View file

@ -92,13 +92,20 @@ class ConfigLine(object):
assert isinstance(obj, ConfigLine), 'child must be of type `ConfigLine`' assert isinstance(obj, ConfigLine), 'child must be of type `ConfigLine`'
self._children.append(obj) self._children.append(obj)
def ignore_line(text, tokens=None): def ignore_line(text, tokens=None):
for item in (tokens or DEFAULT_COMMENT_TOKENS): for item in (tokens or DEFAULT_COMMENT_TOKENS):
if text.startswith(item): if text.startswith(item):
return True return True
_obj_to_text = lambda x: [o.text for o in x]
_obj_to_raw = lambda x: [o.raw for o in x] def _obj_to_text(x):
return [o.text for o in x]
def _obj_to_raw(x):
return [o.raw for o in x]
def _obj_to_block(objects, visited=None): def _obj_to_block(objects, visited=None):
items = list() items = list()
@ -110,6 +117,7 @@ def _obj_to_block(objects, visited=None):
items.append(child) items.append(child)
return _obj_to_raw(items) return _obj_to_raw(items)
def dumps(objects, output='block', comments=False): def dumps(objects, output='block', comments=False):
if output == 'block': if output == 'block':
items = _obj_to_block(objects) items = _obj_to_block(objects)
@ -130,6 +138,7 @@ def dumps(objects, output='block', comments=False):
return '\n'.join(items) return '\n'.join(items)
class NetworkConfig(object): class NetworkConfig(object):
def __init__(self, indent=1, contents=None): def __init__(self, indent=1, contents=None):
@ -328,7 +337,7 @@ class NetworkConfig(object):
offset = 0 offset = 0
obj = None obj = None
## global config command # global config command
if not parents: if not parents:
for line in lines: for line in lines:
item = ConfigLine(line) item = ConfigLine(line)

View file

@ -24,17 +24,16 @@
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
import re import re
import time
import shlex import shlex
import time
from ansible.module_utils.basic import BOOLEANS_TRUE, BOOLEANS_FALSE from ansible.module_utils.basic import BOOLEANS_TRUE, BOOLEANS_FALSE, get_exception
from ansible.module_utils.basic import get_exception
from ansible.module_utils.six import string_types, text_type from ansible.module_utils.six import string_types, text_type
from ansible.module_utils.six.moves import zip from ansible.module_utils.six.moves import zip
def to_list(val): def to_list(val):
if isinstance(val, (list, tuple)): if isinstance(val, (list, tuple)):
return list(val) return list(val)
@ -49,20 +48,23 @@ class FailedConditionsError(Exception):
super(FailedConditionsError, self).__init__(msg) super(FailedConditionsError, self).__init__(msg)
self.failed_conditions = failed_conditions self.failed_conditions = failed_conditions
class FailedConditionalError(Exception): class FailedConditionalError(Exception):
def __init__(self, msg, failed_conditional): def __init__(self, msg, failed_conditional):
super(FailedConditionalError, self).__init__(msg) super(FailedConditionalError, self).__init__(msg)
self.failed_conditional = failed_conditional self.failed_conditional = failed_conditional
class AddCommandError(Exception): class AddCommandError(Exception):
def __init__(self, msg, command): def __init__(self, msg, command):
super(AddCommandError, self).__init__(msg) super(AddCommandError, self).__init__(msg)
self.command = command self.command = command
class AddConditionError(Exception): class AddConditionError(Exception):
def __init__(self, msg, condition): def __init__(self, msg, condition):
super(AddConditionError, self).__init__(msg) super(AddConditionError, self).__init__(msg)
self.condition=condition self.condition = condition
class Cli(object): class Cli(object):
@ -105,6 +107,7 @@ class Cli(object):
return responses return responses
class Command(object): class Command(object):
def __init__(self, command, output=None, prompt=None, response=None, def __init__(self, command, output=None, prompt=None, response=None,
@ -122,6 +125,7 @@ class Command(object):
def __str__(self): def __str__(self):
return self.command_string return self.command_string
class CommandRunner(object): class CommandRunner(object):
def __init__(self, module): def __init__(self, module):

View file

@ -26,14 +26,13 @@
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# #
from contextlib import contextmanager from contextlib import contextmanager
from xml.etree.ElementTree import Element, SubElement from xml.etree.ElementTree import Element, SubElement, fromstring, tostring
from xml.etree.ElementTree import tostring, fromstring
from ansible.module_utils.connection import exec_command from ansible.module_utils.connection import exec_command
NS_MAP = {'nc': "urn:ietf:params:xml:ns:netconf:base:1.0"} NS_MAP = {'nc': "urn:ietf:params:xml:ns:netconf:base:1.0"}
def send_request(module, obj, check_rc=True): def send_request(module, obj, check_rc=True):
request = tostring(obj) request = tostring(obj)
rc, out, err = exec_command(module, request) rc, out, err = exec_command(module, request)
@ -58,6 +57,7 @@ def send_request(module, obj, check_rc=True):
return warnings return warnings
return fromstring(out) return fromstring(out)
def children(root, iterable): def children(root, iterable):
for item in iterable: for item in iterable:
try: try:
@ -65,33 +65,40 @@ def children(root, iterable):
except NameError: except NameError:
ele = SubElement(root, item) ele = SubElement(root, item)
def lock(module, target='candidate'): def lock(module, target='candidate'):
obj = Element('lock') obj = Element('lock')
children(obj, ('target', target)) children(obj, ('target', target))
return send_request(module, obj) return send_request(module, obj)
def unlock(module, target='candidate'): def unlock(module, target='candidate'):
obj = Element('unlock') obj = Element('unlock')
children(obj, ('target', target)) children(obj, ('target', target))
return send_request(module, obj) return send_request(module, obj)
def commit(module): def commit(module):
return send_request(module, Element('commit')) return send_request(module, Element('commit'))
def discard_changes(module): def discard_changes(module):
return send_request(module, Element('discard-changes')) return send_request(module, Element('discard-changes'))
def validate(module): def validate(module):
obj = Element('validate') obj = Element('validate')
children(obj, ('source', 'candidate')) children(obj, ('source', 'candidate'))
return send_request(module, obj) return send_request(module, obj)
def get_config(module, source='running', filter=None): def get_config(module, source='running', filter=None):
obj = Element('get-config') obj = Element('get-config')
children(obj, ('source', source)) children(obj, ('source', source))
children(obj, ('filter', filter)) children(obj, ('filter', filter))
return send_request(module, obj) return send_request(module, obj)
@contextmanager @contextmanager
def locked_config(module): def locked_config(module):
try: try:

View file

@ -52,6 +52,7 @@ NET_CONNECTION_ARGS = dict()
NET_CONNECTIONS = dict() NET_CONNECTIONS = dict()
def _transitional_argument_spec(): def _transitional_argument_spec():
argument_spec = {} argument_spec = {}
for key, value in iteritems(NET_TRANSPORT_ARGS): for key, value in iteritems(NET_TRANSPORT_ARGS):
@ -59,6 +60,7 @@ def _transitional_argument_spec():
argument_spec[key] = value argument_spec[key] = value
return argument_spec return argument_spec
def to_list(val): def to_list(val):
if isinstance(val, (list, tuple)): if isinstance(val, (list, tuple)):
return list(val) return list(val)
@ -75,12 +77,14 @@ class ModuleStub(object):
self.params[key] = value.get('default') self.params[key] = value.get('default')
self.fail_json = fail_json self.fail_json = fail_json
class NetworkError(Exception): class NetworkError(Exception):
def __init__(self, msg, **kwargs): def __init__(self, msg, **kwargs):
super(NetworkError, self).__init__(msg) super(NetworkError, self).__init__(msg)
self.kwargs = kwargs self.kwargs = kwargs
class Config(object): class Config(object):
def __init__(self, connection): def __init__(self, connection):
@ -185,6 +189,7 @@ class NetworkModule(AnsibleModule):
exc = get_exception() exc = get_exception()
self.fail_json(msg=to_native(exc)) self.fail_json(msg=to_native(exc))
def register_transport(transport, default=False): def register_transport(transport, default=False):
def register(cls): def register(cls):
NET_CONNECTIONS[transport] = cls NET_CONNECTIONS[transport] = cls
@ -193,6 +198,6 @@ def register_transport(transport, default=False):
return cls return cls
return register return register
def add_argument(key, value): def add_argument(key, value):
NET_CONNECTION_ARGS[key] = value NET_CONNECTION_ARGS[key] = value

View file

@ -24,9 +24,10 @@
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
from ansible.module_utils.six import iteritems
from ansible.module_utils.basic import AnsibleFallbackNotFound from ansible.module_utils.basic import AnsibleFallbackNotFound
from ansible.module_utils.six import iteritems
def to_list(val): def to_list(val):
if isinstance(val, (list, tuple, set)): if isinstance(val, (list, tuple, set)):
@ -36,6 +37,7 @@ def to_list(val):
else: else:
return list() return list()
class ComplexDict(object): class ComplexDict(object):
"""Transforms a dict to with an argument spec """Transforms a dict to with an argument spec
@ -77,7 +79,7 @@ class ComplexDict(object):
if attr.get('read_from'): if attr.get('read_from'):
spec = self._module.argument_spec.get(attr['read_from']) spec = self._module.argument_spec.get(attr['read_from'])
if not spec: if not spec:
raise ValueError('argument_spec %s does not exist' % attr['read_from']) raise ValueError('argument_spec %s does not exist' % attr['read_from'])
for key, value in iteritems(spec): for key, value in iteritems(spec):
if key not in attr: if key not in attr:
attr[key] = value attr[key] = value
@ -88,7 +90,6 @@ class ComplexDict(object):
self_has_key = True self_has_key = True
attr['required'] = True attr['required'] = True
def _dict(self, value): def _dict(self, value):
obj = {} obj = {}
for name, attr in iteritems(self._attributes): for name, attr in iteritems(self._attributes):
@ -131,8 +132,7 @@ class ComplexDict(object):
if 'choices' in attr: if 'choices' in attr:
if value[name] not in attr['choices']: if value[name] not in attr['choices']:
raise ValueError('%s must be one of %s, got %s' % \ raise ValueError('%s must be one of %s, got %s' % (name, ', '.join(attr['choices']), value[name]))
(name, ', '.join(attr['choices']), value[name]))
if value[name] is not None: if value[name] is not None:
value_type = attr.get('type', 'str') value_type = attr.get('type', 'str')
@ -141,6 +141,7 @@ class ComplexDict(object):
return value return value
class ComplexList(ComplexDict): class ComplexList(ComplexDict):
"""Extends ```ComplexDict``` to handle a list of dicts """ """Extends ```ComplexDict``` to handle a list of dicts """
@ -148,4 +149,3 @@ class ComplexList(ComplexDict):
if not isinstance(values, (list, tuple)): if not isinstance(values, (list, tuple)):
raise TypeError('value must be an ordered iterable') raise TypeError('value must be an ordered iterable')
return [(super(ComplexList, self).__call__(v)) for v in values] return [(super(ComplexList, self).__call__(v)) for v in values]

View file

@ -30,6 +30,7 @@ import os
from ansible.module_utils.six import iteritems from ansible.module_utils.six import iteritems
def openstack_argument_spec(): def openstack_argument_spec():
# DEPRECATED: This argument spec is only used for the deprecated old # DEPRECATED: This argument spec is only used for the deprecated old
# OpenStack modules. It turns out that modern OpenStack auth is WAY # OpenStack modules. It turns out that modern OpenStack auth is WAY
@ -37,17 +38,17 @@ def openstack_argument_spec():
# Consume standard OpenStack environment variables. # Consume standard OpenStack environment variables.
# This is mainly only useful for ad-hoc command line operation as # This is mainly only useful for ad-hoc command line operation as
# in playbooks one would assume variables would be used appropriately # in playbooks one would assume variables would be used appropriately
OS_AUTH_URL=os.environ.get('OS_AUTH_URL', 'http://127.0.0.1:35357/v2.0/') OS_AUTH_URL = os.environ.get('OS_AUTH_URL', 'http://127.0.0.1:35357/v2.0/')
OS_PASSWORD=os.environ.get('OS_PASSWORD', None) OS_PASSWORD = os.environ.get('OS_PASSWORD', None)
OS_REGION_NAME=os.environ.get('OS_REGION_NAME', None) OS_REGION_NAME = os.environ.get('OS_REGION_NAME', None)
OS_USERNAME=os.environ.get('OS_USERNAME', 'admin') OS_USERNAME = os.environ.get('OS_USERNAME', 'admin')
OS_TENANT_NAME=os.environ.get('OS_TENANT_NAME', OS_USERNAME) OS_TENANT_NAME = os.environ.get('OS_TENANT_NAME', OS_USERNAME)
spec = dict( spec = dict(
login_username = dict(default=OS_USERNAME), login_username=dict(default=OS_USERNAME),
auth_url = dict(default=OS_AUTH_URL), auth_url=dict(default=OS_AUTH_URL),
region_name = dict(default=OS_REGION_NAME), region_name=dict(default=OS_REGION_NAME),
availability_zone = dict(default=None), availability_zone=dict(),
) )
if OS_PASSWORD: if OS_PASSWORD:
spec['login_password'] = dict(default=OS_PASSWORD) spec['login_password'] = dict(default=OS_PASSWORD)
@ -59,6 +60,7 @@ def openstack_argument_spec():
spec['login_tenant_name'] = dict(required=True) spec['login_tenant_name'] = dict(required=True)
return spec return spec
def openstack_find_nova_addresses(addresses, ext_tag, key_name=None): def openstack_find_nova_addresses(addresses, ext_tag, key_name=None):
ret = [] ret = []
@ -71,6 +73,7 @@ def openstack_find_nova_addresses(addresses, ext_tag, key_name=None):
ret.append(interface_spec['addr']) ret.append(interface_spec['addr'])
return ret return ret
def openstack_full_argument_spec(**kwargs): def openstack_full_argument_spec(**kwargs):
spec = dict( spec = dict(
cloud=dict(default=None), cloud=dict(default=None),

View file

@ -37,6 +37,7 @@ from ansible.module_utils.urls import fetch_url, url_argument_spec
add_argument('use_ssl', dict(default=True, type='bool')) add_argument('use_ssl', dict(default=True, type='bool'))
add_argument('validate_certs', dict(default=True, type='bool')) add_argument('validate_certs', dict(default=True, type='bool'))
def get_opsidl(): def get_opsidl():
extschema = restparser.parseSchema(settings.get('ext_schema')) extschema = restparser.parseSchema(settings.get('ext_schema'))
ovsschema = settings.get('ovs_schema') ovsschema = settings.get('ovs_schema')
@ -129,7 +130,7 @@ class Rest(object):
def authorize(self, params, **kwargs): def authorize(self, params, **kwargs):
raise NotImplementedError raise NotImplementedError
### REST methods ### # REST methods
def _url_builder(self, path): def _url_builder(self, path):
if path[0] == '/': if path[0] == '/':
@ -160,12 +161,12 @@ class Rest(object):
def delete(self, path, data=None, headers=None): def delete(self, path, data=None, headers=None):
return self.request('DELETE', path, data, headers) return self.request('DELETE', path, data, headers)
### Command methods ### # Command methods
def run_commands(self, commands): def run_commands(self, commands):
raise NotImplementedError raise NotImplementedError
### Config methods ### # Config methods
def configure(self, commands): def configure(self, commands):
path = '/system/full-configuration' path = '/system/full-configuration'
@ -212,7 +213,7 @@ class Cli(CliBase):
NET_PASSWD_RE = re.compile(r"[\r\n]?password: $", re.I) NET_PASSWD_RE = re.compile(r"[\r\n]?password: $", re.I)
### Config methods ### # Config methods
def configure(self, commands, **kwargs): def configure(self, commands, **kwargs):
cmds = ['configure terminal'] cmds = ['configure terminal']

View file

@ -1,5 +1,6 @@
_DEVICE_CONFIGS = {} _DEVICE_CONFIGS = {}
def get_config(module, flags=[]): def get_config(module, flags=[]):
cmd = 'show running-config ' cmd = 'show running-config '
cmd += ' '.join(flags) cmd += ' '.join(flags)

View file

@ -504,7 +504,6 @@ class BaseModule(object):
after[k] = update[k] after[k] = update[k]
return after return after
def create( def create(
self, self,
entity=None, entity=None,
@ -579,9 +578,14 @@ class BaseModule(object):
# Wait for the entity to be created and to be in the defined state: # Wait for the entity to be created and to be in the defined state:
entity_service = self._service.service(entity.id) entity_service = self._service.service(entity.id)
state_condition = lambda entity: entity def state_condition(entity):
return entity
if result_state: if result_state:
state_condition = lambda entity: entity and entity.status == result_state
def state_condition(entity):
return entity and entity.status == result_state
wait( wait(
service=entity_service, service=entity_service,
condition=state_condition, condition=state_condition,

View file

@ -27,24 +27,21 @@
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# standard ansible imports
from ansible.module_utils.basic import get_exception
# standard PG imports
HAS_PSYCOPG2 = False
try: try:
import psycopg2 import psycopg2
import psycopg2.extras import psycopg2.extras
except ImportError:
pass
else:
HAS_PSYCOPG2 = True HAS_PSYCOPG2 = True
except ImportError:
HAS_PSYCOPG2 = False
from ansible.module_utils.basic import get_exception
from ansible.module_utils.six import iteritems from ansible.module_utils.six import iteritems
class LibraryError(Exception): class LibraryError(Exception):
pass pass
def ensure_libs(sslrootcert=None): def ensure_libs(sslrootcert=None):
if not HAS_PSYCOPG2: if not HAS_PSYCOPG2:
raise LibraryError('psycopg2 is not installed. we need psycopg2.') raise LibraryError('psycopg2 is not installed. we need psycopg2.')
@ -54,14 +51,14 @@ def ensure_libs(sslrootcert=None):
# no problems # no problems
return None return None
def postgres_common_argument_spec(): def postgres_common_argument_spec():
return dict( return dict(
login_user = dict(default='postgres'), login_user=dict(default='postgres'),
login_password = dict(default='', no_log=True), login_password=dict(default='', no_log=True),
login_host = dict(default=''), login_host=dict(default=''),
login_unix_socket = dict(default=''), login_unix_socket=dict(default=''),
port = dict(type='int', default=5432), port=dict(type='int', default=5432),
ssl_mode = dict(default='prefer', choices=['disable', 'allow', 'prefer', 'require', 'verify-ca', 'verify-full']), ssl_mode=dict(default='prefer', choices=['disable', 'allow', 'prefer', 'require', 'verify-ca', 'verify-full']),
ssl_rootcert = dict(default=None), ssl_rootcert=dict(),
) )

View file

@ -25,10 +25,10 @@
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
import sys import sys
def get_exception(): def get_exception():
"""Get the current exception. """Get the current exception.

View file

@ -125,9 +125,9 @@ class Rhsm(RegistrationBase):
# Pass supplied **kwargs as parameters to subscription-manager. Ignore # Pass supplied **kwargs as parameters to subscription-manager. Ignore
# non-configuration parameters and replace '_' with '.'. For example, # non-configuration parameters and replace '_' with '.'. For example,
# 'server_hostname' becomes '--system.hostname'. # 'server_hostname' becomes '--system.hostname'.
for k,v in kwargs.items(): for k, v in kwargs.items():
if re.search(r'^(system|rhsm)_', k): if re.search(r'^(system|rhsm)_', k):
args.append('--%s=%s' % (k.replace('_','.'), v)) args.append('--%s=%s' % (k.replace('_', '.'), v))
self.module.run_command(args, check_rc=True) self.module.run_command(args, check_rc=True)
@ -213,7 +213,7 @@ class RhsmPool(object):
def __init__(self, module, **kwargs): def __init__(self, module, **kwargs):
self.module = module self.module = module
for k,v in kwargs.items(): for k, v in kwargs.items():
setattr(self, k, v) setattr(self, k, v)
def __str__(self): def __str__(self):
@ -255,7 +255,7 @@ class RhsmPools(object):
continue continue
# If a colon ':' is found, parse # If a colon ':' is found, parse
elif ':' in line: elif ':' in line:
(key, value) = line.split(':',1) (key, value) = line.split(':', 1)
key = key.strip().replace(" ", "") # To unify key = key.strip().replace(" ", "") # To unify
value = value.strip() value = value.strip()
if key in ['ProductName', 'SubscriptionName']: if key in ['ProductName', 'SubscriptionName']:
@ -265,7 +265,7 @@ class RhsmPools(object):
# Associate value with most recently recorded product # Associate value with most recently recorded product
products[-1].__setattr__(key, value) products[-1].__setattr__(key, value)
# FIXME - log some warning? # FIXME - log some warning?
#else: # else:
# warnings.warn("Unhandled subscription key/value: %s/%s" % (key,value)) # warnings.warn("Unhandled subscription key/value: %s/%s" % (key,value))
return products return products
@ -277,4 +277,3 @@ class RhsmPools(object):
for product in self.products: for product in self.products:
if r.search(product._name): if r.search(product._name):
yield product yield product

View file

@ -25,20 +25,20 @@
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
import os
import shlex
import subprocess
import glob import glob
import select import os
import pickle import pickle
import platform import platform
import select
import shlex
import subprocess
import traceback import traceback
from ansible.module_utils.six import PY2, b from ansible.module_utils.six import PY2, b
from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils._text import to_bytes, to_text
def sysv_is_enabled(name): def sysv_is_enabled(name):
''' '''
This function will check if the service name supplied This function will check if the service name supplied
@ -48,6 +48,7 @@ def sysv_is_enabled(name):
''' '''
return bool(glob.glob('/etc/rc?.d/S??%s' % name)) return bool(glob.glob('/etc/rc?.d/S??%s' % name))
def get_sysv_script(name): def get_sysv_script(name):
''' '''
This function will return the expected path for an init script This function will return the expected path for an init script
@ -62,6 +63,7 @@ def get_sysv_script(name):
return result return result
def sysv_exists(name): def sysv_exists(name):
''' '''
This function will return True or False depending on This function will return True or False depending on
@ -71,6 +73,7 @@ def sysv_exists(name):
''' '''
return os.path.exists(get_sysv_script(name)) return os.path.exists(get_sysv_script(name))
def fail_if_missing(module, found, service, msg=''): def fail_if_missing(module, found, service, msg=''):
''' '''
This function will return an error or exit gracefully depending on check mode status This function will return an error or exit gracefully depending on check mode status
@ -87,6 +90,7 @@ def fail_if_missing(module, found, service, msg=''):
else: else:
module.fail_json(msg='Could not find the requested service %s: %s' % (service, msg)) module.fail_json(msg='Could not find the requested service %s: %s' % (service, msg))
def daemonize(module, cmd): def daemonize(module, cmd):
''' '''
Execute a command while detaching as a deamon, returns rc, stdout, and stderr. Execute a command while detaching as a deamon, returns rc, stdout, and stderr.
@ -100,10 +104,10 @@ def daemonize(module, cmd):
''' '''
# init some vars # init some vars
chunk = 4096 #FIXME: pass in as arg? chunk = 4096 # FIXME: pass in as arg?
errors = 'surrogate_or_strict' errors = 'surrogate_or_strict'
#start it! # start it!
try: try:
pipe = os.pipe() pipe = os.pipe()
pid = os.fork() pid = os.fork()
@ -162,7 +166,7 @@ def daemonize(module, cmd):
fds = [p.stdout, p.stderr] fds = [p.stdout, p.stderr]
# loop reading output till its done # loop reading output till its done
output = { p.stdout: b(""), p.sterr: b("") } output = {p.stdout: b(""), p.sterr: b("")}
while fds: while fds:
rfd, wfd, efd = select.select(fds, [], fds, 1) rfd, wfd, efd = select.select(fds, [], fds, 1)
if (rfd + wfd + efd) or p.poll(): if (rfd + wfd + efd) or p.poll():
@ -207,6 +211,7 @@ def daemonize(module, cmd):
# py2 and py3) # py2 and py3)
return pickle.loads(to_bytes(return_data, errors=errors)) return pickle.loads(to_bytes(return_data, errors=errors))
def check_ps(module, pattern): def check_ps(module, pattern):
# Set ps flags # Set ps flags

View file

@ -281,5 +281,8 @@ class CliBase(object):
exc = get_exception() exc = get_exception()
raise NetworkError(to_native(exc)) raise NetworkError(to_native(exc))
run_commands = lambda self, x: self.execute(to_list(x)) def run_commands(self, x):
exec_command = lambda self, x: self.shell.send(self.to_command(x)) return self.execute(to_list(x))
def exec_command(self, x):
return self.shell.send(self.to_command(x))

View file

@ -26,6 +26,7 @@
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
def _get_quote_state(token, quote_char): def _get_quote_state(token, quote_char):
''' '''
the goal of this block is to determine if the quoted string the goal of this block is to determine if the quoted string
@ -36,7 +37,7 @@ def _get_quote_state(token, quote_char):
prev_char = None prev_char = None
for idx, cur_char in enumerate(token): for idx, cur_char in enumerate(token):
if idx > 0: if idx > 0:
prev_char = token[idx-1] prev_char = token[idx - 1]
if cur_char in '"\'' and prev_char != '\\': if cur_char in '"\'' and prev_char != '\\':
if quote_char: if quote_char:
if cur_char == quote_char: if cur_char == quote_char:
@ -45,13 +46,14 @@ def _get_quote_state(token, quote_char):
quote_char = cur_char quote_char = cur_char
return quote_char return quote_char
def _count_jinja2_blocks(token, cur_depth, open_token, close_token): def _count_jinja2_blocks(token, cur_depth, open_token, close_token):
''' '''
this function counts the number of opening/closing blocks for a this function counts the number of opening/closing blocks for a
given opening/closing type and adjusts the current depth for that given opening/closing type and adjusts the current depth for that
block based on the difference block based on the difference
''' '''
num_open = token.count(open_token) num_open = token.count(open_token)
num_close = token.count(close_token) num_close = token.count(close_token)
if num_open != num_close: if num_open != num_close:
cur_depth += (num_open - num_close) cur_depth += (num_open - num_close)
@ -59,6 +61,7 @@ def _count_jinja2_blocks(token, cur_depth, open_token, close_token):
cur_depth = 0 cur_depth = 0
return cur_depth return cur_depth
def split_args(args): def split_args(args):
''' '''
Splits args on whitespace, but intelligently reassembles Splits args on whitespace, but intelligently reassembles
@ -99,13 +102,13 @@ def split_args(args):
quote_char = None quote_char = None
inside_quotes = False inside_quotes = False
print_depth = 0 # used to count nested jinja2 {{ }} blocks print_depth = 0 # used to count nested jinja2 {{ }} blocks
block_depth = 0 # used to count nested jinja2 {% %} blocks block_depth = 0 # used to count nested jinja2 {% %} blocks
comment_depth = 0 # used to count nested jinja2 {# #} blocks comment_depth = 0 # used to count nested jinja2 {# #} blocks
# now we loop over each split chunk, coalescing tokens if the white space # now we loop over each split chunk, coalescing tokens if the white space
# split occurred within quotes or a jinja2 block of some kind # split occurred within quotes or a jinja2 block of some kind
for itemidx,item in enumerate(items): for itemidx, item in enumerate(items):
# we split on spaces and newlines separately, so that we # we split on spaces and newlines separately, so that we
# can tell which character we split on for reassembly # can tell which character we split on for reassembly
@ -113,7 +116,7 @@ def split_args(args):
tokens = item.strip().split(' ') tokens = item.strip().split(' ')
line_continuation = False line_continuation = False
for idx,token in enumerate(tokens): for idx, token in enumerate(tokens):
# if we hit a line continuation character, but # if we hit a line continuation character, but
# we're not inside quotes, ignore it and continue # we're not inside quotes, ignore it and continue
@ -201,12 +204,13 @@ def split_args(args):
return params return params
def is_quoted(data): def is_quoted(data):
return len(data) > 0 and (data[0] == '"' and data[-1] == '"' or data[0] == "'" and data[-1] == "'") return len(data) > 0 and (data[0] == '"' and data[-1] == '"' or data[0] == "'" and data[-1] == "'")
def unquote(data): def unquote(data):
''' removes first and last quotes from a string, if the string starts and ends with the same quotes ''' ''' removes first and last quotes from a string, if the string starts and ends with the same quotes '''
if is_quoted(data): if is_quoted(data):
return data[1:-1] return data[1:-1]
return data return data

View file

@ -105,20 +105,20 @@ def uldap():
def construct(): def construct():
try: try:
secret_file = open('/etc/ldap.secret', 'r') secret_file = open('/etc/ldap.secret', 'r')
bind_dn = 'cn=admin,{}'.format(base_dn()) bind_dn = 'cn=admin,{}'.format(base_dn())
except IOError: # pragma: no cover except IOError: # pragma: no cover
secret_file = open('/etc/machine.secret', 'r') secret_file = open('/etc/machine.secret', 'r')
bind_dn = config_registry()["ldap/hostdn"] bind_dn = config_registry()["ldap/hostdn"]
pwd_line = secret_file.readline() pwd_line = secret_file.readline()
pwd = re.sub('\n', '', pwd_line) pwd = re.sub('\n', '', pwd_line)
import univention.admin.uldap import univention.admin.uldap
return univention.admin.uldap.access( return univention.admin.uldap.access(
host = config_registry()['ldap/master'], host=config_registry()['ldap/master'],
base = base_dn(), base=base_dn(),
binddn = bind_dn, binddn=bind_dn,
bindpw = pwd, bindpw=pwd,
start_tls = 1 start_tls=1,
) )
return _singleton('uldap', construct) return _singleton('uldap', construct)

View file

@ -206,17 +206,14 @@ except ImportError:
HAS_MATCH_HOSTNAME = False HAS_MATCH_HOSTNAME = False
if not HAS_MATCH_HOSTNAME: if not HAS_MATCH_HOSTNAME:
### # The following block of code is under the terms and conditions of the
### The following block of code is under the terms and conditions of the # Python Software Foundation License
### Python Software Foundation License
###
"""The match_hostname() function from Python 3.4, essential when using SSL.""" """The match_hostname() function from Python 3.4, essential when using SSL."""
class CertificateError(ValueError): class CertificateError(ValueError):
pass pass
def _dnsname_match(dn, hostname, max_wildcards=1): def _dnsname_match(dn, hostname, max_wildcards=1):
"""Matching according to RFC 6125, section 6.4.3 """Matching according to RFC 6125, section 6.4.3
@ -269,7 +266,6 @@ if not HAS_MATCH_HOSTNAME:
pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
return pat.match(hostname) return pat.match(hostname)
def match_hostname(cert, hostname): def match_hostname(cert, hostname):
"""Verify that *cert* (in decoded format as returned by """Verify that *cert* (in decoded format as returned by
SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125
@ -299,20 +295,13 @@ if not HAS_MATCH_HOSTNAME:
return return
dnsnames.append(value) dnsnames.append(value)
if len(dnsnames) > 1: if len(dnsnames) > 1:
raise CertificateError("hostname %r " raise CertificateError("hostname %r " "doesn't match either of %s" % (hostname, ', '.join(map(repr, dnsnames))))
"doesn't match either of %s"
% (hostname, ', '.join(map(repr, dnsnames))))
elif len(dnsnames) == 1: elif len(dnsnames) == 1:
raise CertificateError("hostname %r " raise CertificateError("hostname %r doesn't match %r" % (hostname, dnsnames[0]))
"doesn't match %r"
% (hostname, dnsnames[0]))
else: else:
raise CertificateError("no appropriate commonName or " raise CertificateError("no appropriate commonName or subjectAltName fields were found")
"subjectAltName fields were found")
### # End of Python Software Foundation Licensed code
### End of Python Software Foundation Licensed code
###
HAS_MATCH_HOSTNAME = True HAS_MATCH_HOSTNAME = True
@ -399,7 +388,7 @@ if hasattr(httplib, 'HTTPSConnection') and hasattr(urllib_request, 'HTTPSHandler
self.sock = self.context.wrap_socket(sock, server_hostname=server_hostname) self.sock = self.context.wrap_socket(sock, server_hostname=server_hostname)
elif HAS_URLLIB3_SSL_WRAP_SOCKET: elif HAS_URLLIB3_SSL_WRAP_SOCKET:
self.sock = ssl_wrap_socket(sock, keyfile=self.key_file, cert_reqs=ssl.CERT_NONE, certfile=self.cert_file, ssl_version=PROTOCOL, self.sock = ssl_wrap_socket(sock, keyfile=self.key_file, cert_reqs=ssl.CERT_NONE, certfile=self.cert_file, ssl_version=PROTOCOL,
server_hostname=server_hostname) server_hostname=server_hostname)
else: else:
self.sock = ssl.wrap_socket(sock, keyfile=self.key_file, certfile=self.cert_file, ssl_version=PROTOCOL) self.sock = ssl.wrap_socket(sock, keyfile=self.key_file, certfile=self.cert_file, ssl_version=PROTOCOL)
@ -448,24 +437,24 @@ def generic_urlparse(parts):
if hasattr(parts, 'netloc'): if hasattr(parts, 'netloc'):
# urlparse is newer, just read the fields straight # urlparse is newer, just read the fields straight
# from the parts object # from the parts object
generic_parts['scheme'] = parts.scheme generic_parts['scheme'] = parts.scheme
generic_parts['netloc'] = parts.netloc generic_parts['netloc'] = parts.netloc
generic_parts['path'] = parts.path generic_parts['path'] = parts.path
generic_parts['params'] = parts.params generic_parts['params'] = parts.params
generic_parts['query'] = parts.query generic_parts['query'] = parts.query
generic_parts['fragment'] = parts.fragment generic_parts['fragment'] = parts.fragment
generic_parts['username'] = parts.username generic_parts['username'] = parts.username
generic_parts['password'] = parts.password generic_parts['password'] = parts.password
generic_parts['hostname'] = parts.hostname generic_parts['hostname'] = parts.hostname
generic_parts['port'] = parts.port generic_parts['port'] = parts.port
else: else:
# we have to use indexes, and then parse out # we have to use indexes, and then parse out
# the other parts not supported by indexing # the other parts not supported by indexing
generic_parts['scheme'] = parts[0] generic_parts['scheme'] = parts[0]
generic_parts['netloc'] = parts[1] generic_parts['netloc'] = parts[1]
generic_parts['path'] = parts[2] generic_parts['path'] = parts[2]
generic_parts['params'] = parts[3] generic_parts['params'] = parts[3]
generic_parts['query'] = parts[4] generic_parts['query'] = parts[4]
generic_parts['fragment'] = parts[5] generic_parts['fragment'] = parts[5]
# get the username, password, etc. # get the username, password, etc.
try: try:
@ -488,12 +477,12 @@ def generic_urlparse(parts):
generic_parts['username'] = username generic_parts['username'] = username
generic_parts['password'] = password generic_parts['password'] = password
generic_parts['hostname'] = hostname generic_parts['hostname'] = hostname
generic_parts['port'] = port generic_parts['port'] = port
except: except:
generic_parts['username'] = None generic_parts['username'] = None
generic_parts['password'] = None generic_parts['password'] = None
generic_parts['hostname'] = parts[1] generic_parts['hostname'] = parts[1]
generic_parts['port'] = None generic_parts['port'] = None
return generic_parts return generic_parts
@ -551,9 +540,8 @@ def RedirectHandlerFactory(follow_redirects=None, validate_certs=True):
if do_redirect: if do_redirect:
# be conciliant with URIs containing a space # be conciliant with URIs containing a space
newurl = newurl.replace(' ', '%20') newurl = newurl.replace(' ', '%20')
newheaders = dict((k,v) for k,v in req.headers.items() newheaders = dict((k, v) for k, v in req.headers.items()
if k.lower() not in ("content-length", "content-type") if k.lower() not in ("content-length", "content-type"))
)
try: try:
# Python 2-3.3 # Python 2-3.3
origin_req_host = req.get_origin_req_host() origin_req_host = req.get_origin_req_host()
@ -561,9 +549,9 @@ def RedirectHandlerFactory(follow_redirects=None, validate_certs=True):
# Python 3.4+ # Python 3.4+
origin_req_host = req.origin_req_host origin_req_host = req.origin_req_host
return urllib_request.Request(newurl, return urllib_request.Request(newurl,
headers=newheaders, headers=newheaders,
origin_req_host=origin_req_host, origin_req_host=origin_req_host,
unverifiable=True) unverifiable=True)
else: else:
raise urllib_error.HTTPError(req.get_full_url(), code, msg, hdrs, fp) raise urllib_error.HTTPError(req.get_full_url(), code, msg, hdrs, fp)
@ -660,7 +648,7 @@ class SSLValidationHandler(urllib_request.BaseHandler):
dir_contents = os.listdir(path) dir_contents = os.listdir(path)
for f in dir_contents: for f in dir_contents:
full_path = os.path.join(path, f) full_path = os.path.join(path, f)
if os.path.isfile(full_path) and os.path.splitext(f)[1] in ('.crt','.pem'): if os.path.isfile(full_path) and os.path.splitext(f)[1] in ('.crt', '.pem'):
try: try:
cert_file = open(full_path, 'rb') cert_file = open(full_path, 'rb')
cert = cert_file.read() cert = cert_file.read()
@ -738,7 +726,7 @@ class SSLValidationHandler(urllib_request.BaseHandler):
if proxy_parts.get('scheme') == 'http': if proxy_parts.get('scheme') == 'http':
s.sendall(self.CONNECT_COMMAND % (self.hostname, self.port)) s.sendall(self.CONNECT_COMMAND % (self.hostname, self.port))
if proxy_parts.get('username'): if proxy_parts.get('username'):
credentials = "%s:%s" % (proxy_parts.get('username',''), proxy_parts.get('password','')) credentials = "%s:%s" % (proxy_parts.get('username', ''), proxy_parts.get('password', ''))
s.sendall(b('Proxy-Authorization: Basic %s\r\n') % base64.b64encode(to_bytes(credentials, errors='surrogate_or_strict')).strip()) s.sendall(b('Proxy-Authorization: Basic %s\r\n') % base64.b64encode(to_bytes(credentials, errors='surrogate_or_strict')).strip())
s.sendall(b('\r\n')) s.sendall(b('\r\n'))
connect_result = b("") connect_result = b("")
@ -767,7 +755,7 @@ class SSLValidationHandler(urllib_request.BaseHandler):
ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL) ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL)
match_hostname(ssl_s.getpeercert(), self.hostname) match_hostname(ssl_s.getpeercert(), self.hostname)
# close the ssl connection # close the ssl connection
#ssl_s.unwrap() # ssl_s.unwrap()
s.close() s.close()
except (ssl.SSLError, CertificateError): except (ssl.SSLError, CertificateError):
e = get_exception() e = get_exception()
@ -923,7 +911,7 @@ def open_url(url, data=None, headers=None, method=None, use_proxy=True,
data = to_bytes(data, nonstring='passthru') data = to_bytes(data, nonstring='passthru')
if method: if method:
if method.upper() not in ('OPTIONS','GET','HEAD','POST','PUT','DELETE','TRACE','CONNECT','PATCH'): if method.upper() not in ('OPTIONS', 'GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE', 'CONNECT', 'PATCH'):
raise ConnectionError('invalid HTTP request method; %s' % method.upper()) raise ConnectionError('invalid HTTP request method; %s' % method.upper())
request = RequestWithMethod(url, method.upper(), data) request = RequestWithMethod(url, method.upper(), data)
else: else:
@ -951,7 +939,7 @@ def open_url(url, data=None, headers=None, method=None, use_proxy=True,
request.add_header(header, headers[header]) request.add_header(header, headers[header])
urlopen_args = [request, None] urlopen_args = [request, None]
if sys.version_info >= (2,6,0): if sys.version_info >= (2, 6, 0):
# urlopen in python prior to 2.6.0 did not # urlopen in python prior to 2.6.0 did not
# have a timeout parameter # have a timeout parameter
urlopen_args.append(timeout) urlopen_args.append(timeout)

View file

@ -15,6 +15,7 @@
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
import os import os
try: try:
from pyvcloud.vcloudair import VCA from pyvcloud.vcloudair import VCA
HAS_PYVCLOUD = True HAS_PYVCLOUD = True
@ -29,16 +30,18 @@ LOGIN_HOST = {'vca': 'vca.vmware.com', 'vchs': 'vchs.vmware.com'}
DEFAULT_SERVICE_TYPE = 'vca' DEFAULT_SERVICE_TYPE = 'vca'
DEFAULT_VERSION = '5.7' DEFAULT_VERSION = '5.7'
class VcaError(Exception): class VcaError(Exception):
def __init__(self, msg, **kwargs): def __init__(self, msg, **kwargs):
self.kwargs = kwargs self.kwargs = kwargs
super(VcaError, self).__init__(msg) super(VcaError, self).__init__(msg)
def vca_argument_spec(): def vca_argument_spec():
return dict( return dict(
username=dict(type='str', aliases=['user'], required=True), username=dict(type='str', aliases=['user'], required=True),
password=dict(type='str', aliases=['pass','passwd'], required=True, no_log=True), password=dict(type='str', aliases=['pass', 'passwd'], required=True, no_log=True),
org=dict(), org=dict(),
service_id=dict(), service_id=dict(),
instance_id=dict(), instance_id=dict(),
@ -50,6 +53,7 @@ def vca_argument_spec():
verify_certs=dict(type='bool', default=True) verify_certs=dict(type='bool', default=True)
) )
class VcaAnsibleModule(AnsibleModule): class VcaAnsibleModule(AnsibleModule):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -193,7 +197,6 @@ class VcaAnsibleModule(AnsibleModule):
self.exit_json(**kwargs) self.exit_json(**kwargs)
# ------------------------------------------------------------- # -------------------------------------------------------------
# 9/18/2015 @privateip # 9/18/2015 @privateip
# All of the functions below here were migrated from the original # All of the functions below here were migrated from the original
@ -206,6 +209,7 @@ VCA_REQ_ARGS = ['instance_id', 'vdc_name']
VCHS_REQ_ARGS = ['service_id'] VCHS_REQ_ARGS = ['service_id']
VCD_REQ_ARGS = [] VCD_REQ_ARGS = []
def _validate_module(module): def _validate_module(module):
if not HAS_PYVCLOUD: if not HAS_PYVCLOUD:
module.fail_json(msg="python module pyvcloud is needed for this module") module.fail_json(msg="python module pyvcloud is needed for this module")
@ -216,19 +220,19 @@ def _validate_module(module):
for arg in VCA_REQ_ARGS: for arg in VCA_REQ_ARGS:
if module.params.get(arg) is None: if module.params.get(arg) is None:
module.fail_json(msg="argument %s is mandatory when service type " module.fail_json(msg="argument %s is mandatory when service type "
"is vca" % arg) "is vca" % arg)
if service_type == 'vchs': if service_type == 'vchs':
for arg in VCHS_REQ_ARGS: for arg in VCHS_REQ_ARGS:
if module.params.get(arg) is None: if module.params.get(arg) is None:
module.fail_json(msg="argument %s is mandatory when service type " module.fail_json(msg="argument %s is mandatory when service type "
"is vchs" % arg) "is vchs" % arg)
if service_type == 'vcd': if service_type == 'vcd':
for arg in VCD_REQ_ARGS: for arg in VCD_REQ_ARGS:
if module.params.get(arg) is None: if module.params.get(arg) is None:
module.fail_json(msg="argument %s is mandatory when service type " module.fail_json(msg="argument %s is mandatory when service type "
"is vcd" % arg) "is vcd" % arg)
def serialize_instances(instance_list): def serialize_instances(instance_list):
@ -237,6 +241,7 @@ def serialize_instances(instance_list):
instances.append(dict(apiUrl=i['apiUrl'], instance_id=i['id'])) instances.append(dict(apiUrl=i['apiUrl'], instance_id=i['id']))
return instances return instances
def _vca_login(vca, password, instance): def _vca_login(vca, password, instance):
if not vca.login(password=password): if not vca.login(password=password):
raise VcaError("Login Failed: Please check username or password", raise VcaError("Login Failed: Please check username or password",
@ -245,10 +250,11 @@ def _vca_login(vca, password, instance):
if not vca.login_to_instance_sso(instance=instance): if not vca.login_to_instance_sso(instance=instance):
s_json = serialize_instances(vca.instances) s_json = serialize_instances(vca.instances)
raise VcaError("Login to Instance failed: Seems like instance_id provided " raise VcaError("Login to Instance failed: Seems like instance_id provided "
"is wrong .. Please check", valid_instances=s_json) "is wrong .. Please check", valid_instances=s_json)
return vca return vca
def _vchs_login(vca, password, service, org): def _vchs_login(vca, password, service, org):
if not vca.login(password=password): if not vca.login(password=password):
raise VcaError("Login Failed: Please check username or password", raise VcaError("Login Failed: Please check username or password",
@ -256,7 +262,7 @@ def _vchs_login(vca, password, service, org):
if not vca.login_to_org(service, org): if not vca.login_to_org(service, org):
raise VcaError("Failed to login to org, Please check the orgname", raise VcaError("Failed to login to org, Please check the orgname",
error=vca.response.content) error=vca.response.content)
def _vcd_login(vca, password, org): def _vcd_login(vca, password, org):
@ -272,6 +278,7 @@ def _vcd_login(vca, password, org):
if not vca.login(token=vca.token, org=org, org_url=vca.vcloud_session.org_url): if not vca.login(token=vca.token, org=org, org_url=vca.vcloud_session.org_url):
raise VcaError("Failed to login to org", error=vca.response.content) raise VcaError("Failed to login to org", error=vca.response.content)
def vca_login(module): def vca_login(module):
service_type = module.params.get('service_type') service_type = module.params.get('service_type')
username = module.params.get('username') username = module.params.get('username')
@ -323,8 +330,3 @@ def vca_login(module):
module.fail_json(msg=e.message, **e.kwargs) module.fail_json(msg=e.message, **e.kwargs)
return vca return vca

View file

@ -45,7 +45,7 @@ class Playbook:
# be either a play or an include statement # be either a play or an include statement
self._entries = [] self._entries = []
self._basedir = to_text(os.getcwd(), errors='surrogate_or_strict') self._basedir = to_text(os.getcwd(), errors='surrogate_or_strict')
self._loader = loader self._loader = loader
self._file_name = None self._file_name = None
@staticmethod @staticmethod

View file

@ -21,6 +21,7 @@ __metaclass__ = type
from copy import deepcopy from copy import deepcopy
class Attribute: class Attribute:
def __init__(self, isa=None, private=False, default=None, required=False, listof=None, priority=0, class_type=None, always_post_validate=False, def __init__(self, isa=None, private=False, default=None, required=False, listof=None, priority=0, class_type=None, always_post_validate=False,

View file

@ -149,21 +149,21 @@ class BaseMeta(type):
class Base(with_metaclass(BaseMeta, object)): class Base(with_metaclass(BaseMeta, object)):
# connection/transport # connection/transport
_connection = FieldAttribute(isa='string') _connection = FieldAttribute(isa='string')
_port = FieldAttribute(isa='int') _port = FieldAttribute(isa='int')
_remote_user = FieldAttribute(isa='string') _remote_user = FieldAttribute(isa='string')
# variables # variables
_vars = FieldAttribute(isa='dict', priority=100, inherit=False) _vars = FieldAttribute(isa='dict', priority=100, inherit=False)
# flags and misc. settings # flags and misc. settings
_environment = FieldAttribute(isa='list') _environment = FieldAttribute(isa='list')
_no_log = FieldAttribute(isa='bool') _no_log = FieldAttribute(isa='bool')
_always_run = FieldAttribute(isa='bool') _always_run = FieldAttribute(isa='bool')
_run_once = FieldAttribute(isa='bool') _run_once = FieldAttribute(isa='bool')
_ignore_errors = FieldAttribute(isa='bool') _ignore_errors = FieldAttribute(isa='bool')
_check_mode = FieldAttribute(isa='bool') _check_mode = FieldAttribute(isa='bool')
_any_errors_fatal = FieldAttribute(isa='bool', default=False, always_post_validate=True) _any_errors_fatal = FieldAttribute(isa='bool', default=False, always_post_validate=True)
# param names which have been deprecated/removed # param names which have been deprecated/removed
DEPRECATED_ATTRIBUTES = [ DEPRECATED_ATTRIBUTES = [
@ -180,7 +180,7 @@ class Base(with_metaclass(BaseMeta, object)):
# other internal params # other internal params
self._validated = False self._validated = False
self._squashed = False self._squashed = False
self._finalized = False self._finalized = False
# every object gets a random uuid: # every object gets a random uuid:
@ -200,13 +200,13 @@ class Base(with_metaclass(BaseMeta, object)):
print("DUMPING OBJECT ------------------------------------------------------") print("DUMPING OBJECT ------------------------------------------------------")
print("%s- %s (%s, id=%s)" % (" " * depth, self.__class__.__name__, self, id(self))) print("%s- %s (%s, id=%s)" % (" " * depth, self.__class__.__name__, self, id(self)))
if hasattr(self, '_parent') and self._parent: if hasattr(self, '_parent') and self._parent:
self._parent.dump_me(depth+2) self._parent.dump_me(depth + 2)
dep_chain = self._parent.get_dep_chain() dep_chain = self._parent.get_dep_chain()
if dep_chain: if dep_chain:
for dep in dep_chain: for dep in dep_chain:
dep.dump_me(depth+2) dep.dump_me(depth + 2)
if hasattr(self, '_play') and self._play: if hasattr(self, '_play') and self._play:
self._play.dump_me(depth+2) self._play.dump_me(depth + 2)
def preprocess_data(self, ds): def preprocess_data(self, ds):
''' infrequently used method to do some pre-processing of legacy terms ''' ''' infrequently used method to do some pre-processing of legacy terms '''
@ -405,12 +405,12 @@ class Base(with_metaclass(BaseMeta, object)):
) )
value = value.split(',') value = value.split(',')
else: else:
value = [ value ] value = [value]
if attribute.listof is not None: if attribute.listof is not None:
for item in value: for item in value:
if not isinstance(item, attribute.listof): if not isinstance(item, attribute.listof):
raise AnsibleParserError("the field '%s' should be a list of %s," raise AnsibleParserError("the field '%s' should be a list of %s, "
" but the item '%s' is a %s" % (name, attribute.listof, item, type(item)), obj=self.get_ds()) "but the item '%s' is a %s" % (name, attribute.listof, item, type(item)), obj=self.get_ds())
elif attribute.required and attribute.listof == string_types: elif attribute.required and attribute.listof == string_types:
if item is None or item.strip() == "": if item is None or item.strip() == "":
raise AnsibleParserError("the field '%s' is required, and cannot have empty values" % (name,), obj=self.get_ds()) raise AnsibleParserError("the field '%s' is required, and cannot have empty values" % (name,), obj=self.get_ds())
@ -423,7 +423,7 @@ class Base(with_metaclass(BaseMeta, object)):
else: else:
# Making a list like this handles strings of # Making a list like this handles strings of
# text and bytes properly # text and bytes properly
value = [ value ] value = [value]
if not isinstance(value, set): if not isinstance(value, set):
value = set(value) value = set(value)
elif attribute.isa == 'dict': elif attribute.isa == 'dict':
@ -440,12 +440,12 @@ class Base(with_metaclass(BaseMeta, object)):
setattr(self, name, value) setattr(self, name, value)
except (TypeError, ValueError) as e: except (TypeError, ValueError) as e:
raise AnsibleParserError("the field '%s' has an invalid value (%s), and could not be converted to an %s." raise AnsibleParserError("the field '%s' has an invalid value (%s), and could not be converted to an %s. "
" Error was: %s" % (name, value, attribute.isa, e), obj=self.get_ds()) "The error was: %s" % (name, value, attribute.isa, e), obj=self.get_ds())
except (AnsibleUndefinedVariable, UndefinedError) as e: except (AnsibleUndefinedVariable, UndefinedError) as e:
if templar._fail_on_undefined_errors and name != 'name': if templar._fail_on_undefined_errors and name != 'name':
raise AnsibleParserError("the field '%s' has an invalid value, which appears to include a variable that is undefined." raise AnsibleParserError("the field '%s' has an invalid value, which appears to include a variable that is undefined. "
" The error was: %s" % (name,e), obj=self.get_ds()) "The error was: %s" % (name, e), obj=self.get_ds())
self._finalized = True self._finalized = True
@ -490,16 +490,16 @@ class Base(with_metaclass(BaseMeta, object)):
''' '''
if not isinstance(value, list): if not isinstance(value, list):
value = [ value ] value = [value]
if not isinstance(new_value, list): if not isinstance(new_value, list):
new_value = [ new_value ] new_value = [new_value]
if prepend: if prepend:
combined = new_value + value combined = new_value + value
else: else:
combined = value + new_value combined = value + new_value
return [i for i,_ in itertools.groupby(combined) if i is not None] return [i for i, _ in itertools.groupby(combined) if i is not None]
def dump_attrs(self): def dump_attrs(self):
''' '''

View file

@ -29,13 +29,14 @@ except ImportError:
from ansible.utils.display import Display from ansible.utils.display import Display
display = Display() display = Display()
class Become: class Become:
# Privilege escalation # Privilege escalation
_become = FieldAttribute(isa='bool') _become = FieldAttribute(isa='bool')
_become_method = FieldAttribute(isa='string') _become_method = FieldAttribute(isa='string')
_become_user = FieldAttribute(isa='string') _become_user = FieldAttribute(isa='string')
_become_flags = FieldAttribute(isa='string') _become_flags = FieldAttribute(isa='string')
def __init__(self): def __init__(self):
super(Become, self).__init__() super(Become, self).__init__()
@ -44,8 +45,8 @@ class Become:
# Fail out if user specifies conflicting privilege escalations # Fail out if user specifies conflicting privilege escalations
has_become = 'become' in ds or 'become_user'in ds has_become = 'become' in ds or 'become_user'in ds
has_sudo = 'sudo' in ds or 'sudo_user' in ds has_sudo = 'sudo' in ds or 'sudo_user' in ds
has_su = 'su' in ds or 'su_user' in ds has_su = 'su' in ds or 'su_user' in ds
if has_become: if has_become:
msg = 'The become params ("become", "become_user") and' msg = 'The become params ("become", "become_user") and'
@ -101,4 +102,3 @@ class Become:
become_method = C.DEFAULT_BECOME_METHOD become_method = C.DEFAULT_BECOME_METHOD
if become_user is None: if become_user is None:
become_user = C.DEFAULT_BECOME_USER become_user = C.DEFAULT_BECOME_USER

View file

@ -28,29 +28,30 @@ from ansible.playbook.helpers import load_list_of_tasks
from ansible.playbook.role import Role from ansible.playbook.role import Role
from ansible.playbook.taggable import Taggable from ansible.playbook.taggable import Taggable
class Block(Base, Become, Conditional, Taggable): class Block(Base, Become, Conditional, Taggable):
# main block fields containing the task lists # main block fields containing the task lists
_block = FieldAttribute(isa='list', default=[], inherit=False) _block = FieldAttribute(isa='list', default=[], inherit=False)
_rescue = FieldAttribute(isa='list', default=[], inherit=False) _rescue = FieldAttribute(isa='list', default=[], inherit=False)
_always = FieldAttribute(isa='list', default=[], inherit=False) _always = FieldAttribute(isa='list', default=[], inherit=False)
# other fields # other fields
_delegate_to = FieldAttribute(isa='string') _delegate_to = FieldAttribute(isa='string')
_delegate_facts = FieldAttribute(isa='bool', default=False) _delegate_facts = FieldAttribute(isa='bool', default=False)
_name = FieldAttribute(isa='string', default='') _name = FieldAttribute(isa='string', default='')
# for future consideration? this would be functionally # for future consideration? this would be functionally
# similar to the 'else' clause for exceptions # similar to the 'else' clause for exceptions
#_otherwise = FieldAttribute(isa='list') # _otherwise = FieldAttribute(isa='list')
def __init__(self, play=None, parent_block=None, role=None, task_include=None, use_handlers=False, implicit=False): def __init__(self, play=None, parent_block=None, role=None, task_include=None, use_handlers=False, implicit=False):
self._play = play self._play = play
self._role = role self._role = role
self._parent = None self._parent = None
self._dep_chain = None self._dep_chain = None
self._use_handlers = use_handlers self._use_handlers = use_handlers
self._implicit = implicit self._implicit = implicit
# end of role flag # end of role flag
self._eor = False self._eor = False
@ -182,9 +183,9 @@ class Block(Base, Become, Conditional, Taggable):
return new_task_list return new_task_list
new_me = super(Block, self).copy() new_me = super(Block, self).copy()
new_me._play = self._play new_me._play = self._play
new_me._use_handlers = self._use_handlers new_me._use_handlers = self._use_handlers
new_me._eor = self._eor new_me._eor = self._eor
if self._dep_chain is not None: if self._dep_chain is not None:
new_me._dep_chain = self._dep_chain[:] new_me._dep_chain = self._dep_chain[:]
@ -194,7 +195,7 @@ class Block(Base, Become, Conditional, Taggable):
new_me._parent = self._parent.copy(exclude_tasks=exclude_tasks) new_me._parent = self._parent.copy(exclude_tasks=exclude_tasks)
if not exclude_tasks: if not exclude_tasks:
new_me.block = _dupe_task_list(self.block or [], new_me) new_me.block = _dupe_task_list(self.block or [], new_me)
new_me.rescue = _dupe_task_list(self.rescue or [], new_me) new_me.rescue = _dupe_task_list(self.rescue or [], new_me)
new_me.always = _dupe_task_list(self.always or [], new_me) new_me.always = _dupe_task_list(self.always or [], new_me)
@ -355,7 +356,7 @@ class Block(Base, Become, Conditional, Taggable):
def evaluate_block(block): def evaluate_block(block):
new_block = self.copy(exclude_tasks=True) new_block = self.copy(exclude_tasks=True)
new_block.block = evaluate_and_append_task(block.block) new_block.block = evaluate_and_append_task(block.block)
new_block.rescue = evaluate_and_append_task(block.rescue) new_block.rescue = evaluate_and_append_task(block.rescue)
new_block.always = evaluate_and_append_task(block.always) new_block.always = evaluate_and_append_task(block.always)
return new_block return new_block
@ -385,4 +386,3 @@ class Block(Base, Become, Conditional, Taggable):
return self._parent.all_parents_static() return self._parent.all_parents_static()
return True return True

View file

@ -41,6 +41,7 @@ DEFINED_REGEX = re.compile(r'(hostvars\[.+\]|[\w_]+)\s+(not\s+is|is|is\s+not)\s+
LOOKUP_REGEX = re.compile(r'lookup\s*\(') LOOKUP_REGEX = re.compile(r'lookup\s*\(')
VALID_VAR_REGEX = re.compile("^[_A-Za-z][_a-zA-Z0-9]*$") VALID_VAR_REGEX = re.compile("^[_A-Za-z][_a-zA-Z0-9]*$")
class Conditional: class Conditional:
''' '''
@ -63,7 +64,7 @@ class Conditional:
def _validate_when(self, attr, name, value): def _validate_when(self, attr, name, value):
if not isinstance(value, list): if not isinstance(value, list):
setattr(self, name, [ value ]) setattr(self, name, [value])
def _get_attr_when(self): def _get_attr_when(self):
''' '''
@ -234,7 +235,4 @@ class Conditional:
# trigger the AnsibleUndefinedVariable exception again below # trigger the AnsibleUndefinedVariable exception again below
raise raise
except Exception as new_e: except Exception as new_e:
raise AnsibleUndefinedVariable( raise AnsibleUndefinedVariable("error while evaluating conditional (%s): %s" % (original, e))
"error while evaluating conditional (%s): %s" % (original, e)
)

View file

@ -22,6 +22,7 @@ __metaclass__ = type
from ansible.playbook.attribute import FieldAttribute from ansible.playbook.attribute import FieldAttribute
from ansible.playbook.task import Task from ansible.playbook.task import Task
class Handler(Task): class Handler(Task):
_listen = FieldAttribute(isa='list') _listen = FieldAttribute(isa='list')
@ -41,7 +42,7 @@ class Handler(Task):
return t.load_data(data, variable_manager=variable_manager, loader=loader) return t.load_data(data, variable_manager=variable_manager, loader=loader)
def flag_for_host(self, host): def flag_for_host(self, host):
#assert instanceof(host, Host) # assert instanceof(host, Host)
if host not in self._flagged_hosts: if host not in self._flagged_hosts:
self._flagged_hosts.append(host) self._flagged_hosts.append(host)

View file

@ -19,9 +19,10 @@
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
#from ansible.inventory.host import Host # from ansible.inventory.host import Host
from ansible.playbook.task_include import TaskInclude
from ansible.playbook.handler import Handler from ansible.playbook.handler import Handler
from ansible.playbook.task_include import TaskInclude
class HandlerTaskInclude(Handler, TaskInclude): class HandlerTaskInclude(Handler, TaskInclude):
@ -29,4 +30,3 @@ class HandlerTaskInclude(Handler, TaskInclude):
def load(data, block=None, role=None, task_include=None, variable_manager=None, loader=None): def load(data, block=None, role=None, task_include=None, variable_manager=None, loader=None):
t = HandlerTaskInclude(block=block, role=role, task_include=task_include) t = HandlerTaskInclude(block=block, role=role, task_include=task_include)
return t.load_data(data, variable_manager=variable_manager, loader=loader) return t.load_data(data, variable_manager=variable_manager, loader=loader)

View file

@ -179,13 +179,13 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
include_target = templar.template(t.args['_raw_params']) include_target = templar.template(t.args['_raw_params'])
except AnsibleUndefinedVariable: except AnsibleUndefinedVariable:
raise AnsibleParserError( raise AnsibleParserError(
"Error when evaluating variable in include name: %s.\n\n" \ "Error when evaluating variable in include name: %s.\n\n"
"When using static includes, ensure that any variables used in their names are defined in vars/vars_files\n" \ "When using static includes, ensure that any variables used in their names are defined in vars/vars_files\n"
"or extra-vars passed in from the command line. Static includes cannot use variables from inventory\n" \ "or extra-vars passed in from the command line. Static includes cannot use variables from inventory\n"
"sources like group or host vars." % t.args['_raw_params'], "sources like group or host vars." % t.args['_raw_params'],
obj=task_ds, obj=task_ds,
suppress_extended_error=True, suppress_extended_error=True,
) )
if t._role: if t._role:
include_file = loader.path_dwim_relative(t._role._role_path, subdir, include_target) include_file = loader.path_dwim_relative(t._role._role_path, subdir, include_target)
else: else:
@ -209,11 +209,11 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
C.DEFAULT_HANDLER_INCLUDES_STATIC and use_handlers: C.DEFAULT_HANDLER_INCLUDES_STATIC and use_handlers:
raise raise
display.deprecated( display.deprecated(
"Included file '%s' not found, however since this include is not " \ "Included file '%s' not found, however since this include is not "
"explicitly marked as 'static: yes', we will try and include it dynamically " \ "explicitly marked as 'static: yes', we will try and include it dynamically "
"later. In the future, this will be an error unless 'static: no' is used " \ "later. In the future, this will be an error unless 'static: no' is used "
"on the include task. If you do not want missing includes to be considered " \ "on the include task. If you do not want missing includes to be considered "
"dynamic, use 'static: yes' on the include or set the global ansible.cfg " \ "dynamic, use 'static: yes' on the include or set the global ansible.cfg "
"options to make all inclues static for tasks and/or handlers" % include_file, version="2.7" "options to make all inclues static for tasks and/or handlers" % include_file, version="2.7"
) )
task_list.append(t) task_list.append(t)
@ -242,7 +242,7 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
if len(tags) > 0: if len(tags) > 0:
if len(ti_copy.tags) > 0: if len(ti_copy.tags) > 0:
raise AnsibleParserError( raise AnsibleParserError(
"Include tasks should not specify tags in more than one way (both via args and directly on the task). " \ "Include tasks should not specify tags in more than one way (both via args and directly on the task). "
"Mixing styles in which tags are specified is prohibited for whole import hierarchy, not only for single import statement", "Mixing styles in which tags are specified is prohibited for whole import hierarchy, not only for single import statement",
obj=task_ds, obj=task_ds,
suppress_extended_error=True, suppress_extended_error=True,
@ -275,8 +275,8 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
role=role, role=role,
task_include=None, task_include=None,
variable_manager=variable_manager, variable_manager=variable_manager,
loader=loader loader=loader,
) )
# 1. the user has set the 'static' option to false or true # 1. the user has set the 'static' option to false or true
# 2. one of the appropriate config options was set # 2. one of the appropriate config options was set
@ -293,9 +293,11 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
if not templar.is_template(ir.args[param]): if not templar.is_template(ir.args[param]):
needs_templating = True needs_templating = True
break break
is_static = C.DEFAULT_TASK_INCLUDES_STATIC or \ is_static = (
(use_handlers and C.DEFAULT_HANDLER_INCLUDES_STATIC) or \ C.DEFAULT_TASK_INCLUDES_STATIC or
(not needs_templating and ir.all_parents_static() and not ir.loop) (use_handlers and C.DEFAULT_HANDLER_INCLUDES_STATIC) or
(not needs_templating and ir.all_parents_static() and not ir.loop)
)
display.debug('Determined that if include_role static is %s' % str(is_static)) display.debug('Determined that if include_role static is %s' % str(is_static))
if is_static: if is_static:
# uses compiled list from object # uses compiled list from object
@ -331,4 +333,3 @@ def load_list_of_roles(ds, play, current_role_path=None, variable_manager=None,
roles.append(i) roles.append(i)
return roles return roles

View file

@ -30,13 +30,14 @@ except ImportError:
from ansible.utils.display import Display from ansible.utils.display import Display
display = Display() display = Display()
class IncludedFile: class IncludedFile:
def __init__(self, filename, args, task): def __init__(self, filename, args, task):
self._filename = filename self._filename = filename
self._args = args self._args = args
self._task = task self._task = task
self._hosts = [] self._hosts = []
def add_host(self, host): def add_host(self, host):
if host not in self._hosts: if host not in self._hosts:
@ -69,7 +70,7 @@ class IncludedFile:
continue continue
include_results = res._result['results'] include_results = res._result['results']
else: else:
include_results = [ res._result ] include_results = [res._result]
for include_result in include_results: for include_result in include_results:
# if the task result was skipped or failed, continue # if the task result was skipped or failed, continue

View file

@ -26,8 +26,8 @@ from ansible.playbook.base import Base
class LoopControl(Base): class LoopControl(Base):
_loop_var = FieldAttribute(isa='str') _loop_var = FieldAttribute(isa='str')
_label = FieldAttribute(isa='str') _label = FieldAttribute(isa='str')
_pause = FieldAttribute(isa='int') _pause = FieldAttribute(isa='int')
def __init__(self): def __init__(self):
super(LoopControl, self).__init__() super(LoopControl, self).__init__()
@ -36,4 +36,3 @@ class LoopControl(Base):
def load(data, variable_manager=None, loader=None): def load(data, variable_manager=None, loader=None):
t = LoopControl() t = LoopControl()
return t.load_data(data, variable_manager=variable_manager, loader=loader) return t.load_data(data, variable_manager=variable_manager, loader=loader)

View file

@ -20,10 +20,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
from ansible import constants as C from ansible import constants as C
from ansible.errors import AnsibleParserError from ansible.errors import AnsibleParserError
from ansible.module_utils.six import string_types from ansible.module_utils.six import string_types
from ansible.playbook.attribute import FieldAttribute from ansible.playbook.attribute import FieldAttribute
from ansible.playbook.base import Base from ansible.playbook.base import Base
from ansible.playbook.become import Become from ansible.playbook.become import Become
@ -56,40 +54,40 @@ class Play(Base, Taggable, Become):
""" """
# ================================================================================= # =================================================================================
_name = FieldAttribute(isa='string', default='', always_post_validate=True) _name = FieldAttribute(isa='string', default='', always_post_validate=True)
# TODO: generalize connection # TODO: generalize connection
_accelerate = FieldAttribute(isa='bool', default=False, always_post_validate=True) _accelerate = FieldAttribute(isa='bool', default=False, always_post_validate=True)
_accelerate_ipv6 = FieldAttribute(isa='bool', default=False, always_post_validate=True) _accelerate_ipv6 = FieldAttribute(isa='bool', default=False, always_post_validate=True)
_accelerate_port = FieldAttribute(isa='int', default=5099, always_post_validate=True) _accelerate_port = FieldAttribute(isa='int', default=5099, always_post_validate=True)
# Connection # Connection
_fact_path = FieldAttribute(isa='string', default=None) _fact_path = FieldAttribute(isa='string', default=None)
_gather_facts = FieldAttribute(isa='bool', default=None, always_post_validate=True) _gather_facts = FieldAttribute(isa='bool', default=None, always_post_validate=True)
_gather_subset = FieldAttribute(isa='barelist', default=None, always_post_validate=True) _gather_subset = FieldAttribute(isa='barelist', default=None, always_post_validate=True)
_gather_timeout = FieldAttribute(isa='int', default=None, always_post_validate=True) _gather_timeout = FieldAttribute(isa='int', default=None, always_post_validate=True)
_hosts = FieldAttribute(isa='list', required=True, listof=string_types, always_post_validate=True) _hosts = FieldAttribute(isa='list', required=True, listof=string_types, always_post_validate=True)
# Variable Attributes # Variable Attributes
_vars_files = FieldAttribute(isa='list', default=[], priority=99) _vars_files = FieldAttribute(isa='list', default=[], priority=99)
_vars_prompt = FieldAttribute(isa='list', default=[], always_post_validate=True) _vars_prompt = FieldAttribute(isa='list', default=[], always_post_validate=True)
_vault_password = FieldAttribute(isa='string', always_post_validate=True) _vault_password = FieldAttribute(isa='string', always_post_validate=True)
# Role Attributes # Role Attributes
_roles = FieldAttribute(isa='list', default=[], priority=90) _roles = FieldAttribute(isa='list', default=[], priority=90)
# Block (Task) Lists Attributes # Block (Task) Lists Attributes
_handlers = FieldAttribute(isa='list', default=[]) _handlers = FieldAttribute(isa='list', default=[])
_pre_tasks = FieldAttribute(isa='list', default=[]) _pre_tasks = FieldAttribute(isa='list', default=[])
_post_tasks = FieldAttribute(isa='list', default=[]) _post_tasks = FieldAttribute(isa='list', default=[])
_tasks = FieldAttribute(isa='list', default=[]) _tasks = FieldAttribute(isa='list', default=[])
# Flag/Setting Attributes # Flag/Setting Attributes
_force_handlers = FieldAttribute(isa='bool', always_post_validate=True) _force_handlers = FieldAttribute(isa='bool', always_post_validate=True)
_max_fail_percentage = FieldAttribute(isa='percent', always_post_validate=True) _max_fail_percentage = FieldAttribute(isa='percent', always_post_validate=True)
_serial = FieldAttribute(isa='list', default=[], always_post_validate=True) _serial = FieldAttribute(isa='list', default=[], always_post_validate=True)
_strategy = FieldAttribute(isa='string', default=C.DEFAULT_STRATEGY, always_post_validate=True) _strategy = FieldAttribute(isa='string', default=C.DEFAULT_STRATEGY, always_post_validate=True)
_order = FieldAttribute(isa='string', always_post_validate=True) _order = FieldAttribute(isa='string', always_post_validate=True)
# ================================================================================= # =================================================================================
@ -132,8 +130,8 @@ class Play(Base, Taggable, Become):
# this should never happen, but error out with a helpful message # this should never happen, but error out with a helpful message
# to the user if it does... # to the user if it does...
if 'remote_user' in ds: if 'remote_user' in ds:
raise AnsibleParserError("both 'user' and 'remote_user' are set for %s." raise AnsibleParserError("both 'user' and 'remote_user' are set for %s. "
" The use of 'user' is deprecated, and should be removed" % self.get_name(), obj=ds) "The use of 'user' is deprecated, and should be removed" % self.get_name(), obj=ds)
ds['remote_user'] = ds['user'] ds['remote_user'] = ds['user']
del ds['user'] del ds['user']
@ -207,14 +205,14 @@ class Play(Base, Taggable, Become):
display.deprecated("Using the 'short form' for vars_prompt has been deprecated", version="2.7") display.deprecated("Using the 'short form' for vars_prompt has been deprecated", version="2.7")
for vname, prompt in prompt_data.items(): for vname, prompt in prompt_data.items():
vars_prompts.append(dict( vars_prompts.append(dict(
name = vname, name=vname,
prompt = prompt, prompt=prompt,
default = None, default=None,
private = None, private=None,
confirm = None, confirm=None,
encrypt = None, encrypt=None,
salt_size = None, salt_size=None,
salt = None, salt=None,
)) ))
else: else:
vars_prompts.append(prompt_data) vars_prompts.append(prompt_data)

View file

@ -54,42 +54,42 @@ except ImportError:
# in variable names. # in variable names.
MAGIC_VARIABLE_MAPPING = dict( MAGIC_VARIABLE_MAPPING = dict(
connection = ('ansible_connection',), connection=('ansible_connection', ),
remote_addr = ('ansible_ssh_host', 'ansible_host'), remote_addr=('ansible_ssh_host', 'ansible_host'),
remote_user = ('ansible_ssh_user', 'ansible_user'), remote_user=('ansible_ssh_user', 'ansible_user'),
port = ('ansible_ssh_port', 'ansible_port'), port=('ansible_ssh_port', 'ansible_port'),
timeout = ('ansible_ssh_timeout', 'ansible_timeout'), timeout=('ansible_ssh_timeout', 'ansible_timeout'),
ssh_executable = ('ansible_ssh_executable',), ssh_executable=('ansible_ssh_executable', ),
accelerate_port = ('ansible_accelerate_port',), accelerate_port=('ansible_accelerate_port', ),
password = ('ansible_ssh_pass', 'ansible_password'), password=('ansible_ssh_pass', 'ansible_password'),
private_key_file = ('ansible_ssh_private_key_file', 'ansible_private_key_file'), private_key_file=('ansible_ssh_private_key_file', 'ansible_private_key_file'),
pipelining = ('ansible_ssh_pipelining', 'ansible_pipelining'), pipelining=('ansible_ssh_pipelining', 'ansible_pipelining'),
shell = ('ansible_shell_type',), shell=('ansible_shell_type', ),
network_os = ('ansible_network_os',), network_os=('ansible_network_os', ),
become = ('ansible_become',), become=('ansible_become', ),
become_method = ('ansible_become_method',), become_method=('ansible_become_method', ),
become_user = ('ansible_become_user',), become_user=('ansible_become_user', ),
become_pass = ('ansible_become_password','ansible_become_pass'), become_pass=('ansible_become_password', 'ansible_become_pass'),
become_exe = ('ansible_become_exe',), become_exe=('ansible_become_exe', ),
become_flags = ('ansible_become_flags',), become_flags=('ansible_become_flags', ),
ssh_common_args = ('ansible_ssh_common_args',), ssh_common_args=('ansible_ssh_common_args', ),
docker_extra_args= ('ansible_docker_extra_args',), docker_extra_args=('ansible_docker_extra_args', ),
sftp_extra_args = ('ansible_sftp_extra_args',), sftp_extra_args=('ansible_sftp_extra_args', ),
scp_extra_args = ('ansible_scp_extra_args',), scp_extra_args=('ansible_scp_extra_args', ),
ssh_extra_args = ('ansible_ssh_extra_args',), ssh_extra_args=('ansible_ssh_extra_args', ),
ssh_transfer_method = ('ansible_ssh_transfer_method',), ssh_transfer_method=('ansible_ssh_transfer_method', ),
sudo = ('ansible_sudo',), sudo=('ansible_sudo', ),
sudo_user = ('ansible_sudo_user',), sudo_user=('ansible_sudo_user', ),
sudo_pass = ('ansible_sudo_password', 'ansible_sudo_pass'), sudo_pass=('ansible_sudo_password', 'ansible_sudo_pass'),
sudo_exe = ('ansible_sudo_exe',), sudo_exe=('ansible_sudo_exe', ),
sudo_flags = ('ansible_sudo_flags',), sudo_flags=('ansible_sudo_flags', ),
su = ('ansible_su',), su=('ansible_su', ),
su_user = ('ansible_su_user',), su_user=('ansible_su_user', ),
su_pass = ('ansible_su_password', 'ansible_su_pass'), su_pass=('ansible_su_password', 'ansible_su_pass'),
su_exe = ('ansible_su_exe',), su_exe=('ansible_su_exe', ),
su_flags = ('ansible_su_flags',), su_flags=('ansible_su_flags', ),
executable = ('ansible_shell_executable',), executable=('ansible_shell_executable', ),
module_compression = ('ansible_module_compression',), module_compression=('ansible_module_compression', ),
) )
b_SU_PROMPT_LOCALIZATIONS = [ b_SU_PROMPT_LOCALIZATIONS = [
@ -155,6 +155,7 @@ RESET_VARS = (
'ansible_port', 'ansible_port',
) )
class PlayContext(Base): class PlayContext(Base):
''' '''
@ -165,60 +166,60 @@ class PlayContext(Base):
# connection fields, some are inherited from Base: # connection fields, some are inherited from Base:
# (connection, port, remote_user, environment, no_log) # (connection, port, remote_user, environment, no_log)
_docker_extra_args = FieldAttribute(isa='string') _docker_extra_args = FieldAttribute(isa='string')
_remote_addr = FieldAttribute(isa='string') _remote_addr = FieldAttribute(isa='string')
_password = FieldAttribute(isa='string') _password = FieldAttribute(isa='string')
_private_key_file = FieldAttribute(isa='string', default=C.DEFAULT_PRIVATE_KEY_FILE) _private_key_file = FieldAttribute(isa='string', default=C.DEFAULT_PRIVATE_KEY_FILE)
_timeout = FieldAttribute(isa='int', default=C.DEFAULT_TIMEOUT) _timeout = FieldAttribute(isa='int', default=C.DEFAULT_TIMEOUT)
_shell = FieldAttribute(isa='string') _shell = FieldAttribute(isa='string')
_network_os = FieldAttribute(isa='string') _network_os = FieldAttribute(isa='string')
_connection_user = FieldAttribute(isa='string') _connection_user = FieldAttribute(isa='string')
_ssh_args = FieldAttribute(isa='string', default=C.ANSIBLE_SSH_ARGS) _ssh_args = FieldAttribute(isa='string', default=C.ANSIBLE_SSH_ARGS)
_ssh_common_args = FieldAttribute(isa='string') _ssh_common_args = FieldAttribute(isa='string')
_sftp_extra_args = FieldAttribute(isa='string') _sftp_extra_args = FieldAttribute(isa='string')
_scp_extra_args = FieldAttribute(isa='string') _scp_extra_args = FieldAttribute(isa='string')
_ssh_extra_args = FieldAttribute(isa='string') _ssh_extra_args = FieldAttribute(isa='string')
_ssh_executable = FieldAttribute(isa='string', default=C.ANSIBLE_SSH_EXECUTABLE) _ssh_executable = FieldAttribute(isa='string', default=C.ANSIBLE_SSH_EXECUTABLE)
_ssh_transfer_method = FieldAttribute(isa='string', default=C.DEFAULT_SSH_TRANSFER_METHOD) _ssh_transfer_method = FieldAttribute(isa='string', default=C.DEFAULT_SSH_TRANSFER_METHOD)
_connection_lockfd= FieldAttribute(isa='int') _connection_lockfd = FieldAttribute(isa='int')
_pipelining = FieldAttribute(isa='bool', default=C.ANSIBLE_SSH_PIPELINING) _pipelining = FieldAttribute(isa='bool', default=C.ANSIBLE_SSH_PIPELINING)
_accelerate = FieldAttribute(isa='bool', default=False) _accelerate = FieldAttribute(isa='bool', default=False)
_accelerate_ipv6 = FieldAttribute(isa='bool', default=False, always_post_validate=True) _accelerate_ipv6 = FieldAttribute(isa='bool', default=False, always_post_validate=True)
_accelerate_port = FieldAttribute(isa='int', default=C.ACCELERATE_PORT, always_post_validate=True) _accelerate_port = FieldAttribute(isa='int', default=C.ACCELERATE_PORT, always_post_validate=True)
_executable = FieldAttribute(isa='string', default=C.DEFAULT_EXECUTABLE) _executable = FieldAttribute(isa='string', default=C.DEFAULT_EXECUTABLE)
_module_compression = FieldAttribute(isa='string', default=C.DEFAULT_MODULE_COMPRESSION) _module_compression = FieldAttribute(isa='string', default=C.DEFAULT_MODULE_COMPRESSION)
# privilege escalation fields # privilege escalation fields
_become = FieldAttribute(isa='bool') _become = FieldAttribute(isa='bool')
_become_method = FieldAttribute(isa='string') _become_method = FieldAttribute(isa='string')
_become_user = FieldAttribute(isa='string') _become_user = FieldAttribute(isa='string')
_become_pass = FieldAttribute(isa='string') _become_pass = FieldAttribute(isa='string')
_become_exe = FieldAttribute(isa='string') _become_exe = FieldAttribute(isa='string')
_become_flags = FieldAttribute(isa='string') _become_flags = FieldAttribute(isa='string')
_prompt = FieldAttribute(isa='string') _prompt = FieldAttribute(isa='string')
# backwards compatibility fields for sudo/su # backwards compatibility fields for sudo/su
_sudo_exe = FieldAttribute(isa='string') _sudo_exe = FieldAttribute(isa='string')
_sudo_flags = FieldAttribute(isa='string') _sudo_flags = FieldAttribute(isa='string')
_sudo_pass = FieldAttribute(isa='string') _sudo_pass = FieldAttribute(isa='string')
_su_exe = FieldAttribute(isa='string') _su_exe = FieldAttribute(isa='string')
_su_flags = FieldAttribute(isa='string') _su_flags = FieldAttribute(isa='string')
_su_pass = FieldAttribute(isa='string') _su_pass = FieldAttribute(isa='string')
# general flags # general flags
_verbosity = FieldAttribute(isa='int', default=0) _verbosity = FieldAttribute(isa='int', default=0)
_only_tags = FieldAttribute(isa='set', default=set()) _only_tags = FieldAttribute(isa='set', default=set())
_skip_tags = FieldAttribute(isa='set', default=set()) _skip_tags = FieldAttribute(isa='set', default=set())
_check_mode = FieldAttribute(isa='bool', default=False) _check_mode = FieldAttribute(isa='bool', default=False)
_force_handlers = FieldAttribute(isa='bool', default=False) _force_handlers = FieldAttribute(isa='bool', default=False)
_start_at_task = FieldAttribute(isa='string') _start_at_task = FieldAttribute(isa='string')
_step = FieldAttribute(isa='bool', default=False) _step = FieldAttribute(isa='bool', default=False)
_diff = FieldAttribute(isa='bool', default=C.DIFF_ALWAYS) _diff = FieldAttribute(isa='bool', default=C.DIFF_ALWAYS)
# Fact gathering settings # Fact gathering settings
_gather_subset = FieldAttribute(isa='string', default=C.DEFAULT_GATHER_SUBSET) _gather_subset = FieldAttribute(isa='string', default=C.DEFAULT_GATHER_SUBSET)
_gather_timeout = FieldAttribute(isa='string', default=C.DEFAULT_GATHER_TIMEOUT) _gather_timeout = FieldAttribute(isa='string', default=C.DEFAULT_GATHER_TIMEOUT)
_fact_path = FieldAttribute(isa='string', default=C.DEFAULT_FACT_PATH) _fact_path = FieldAttribute(isa='string', default=C.DEFAULT_FACT_PATH)
def __init__(self, play=None, options=None, passwords=None, connection_lockfd=None): def __init__(self, play=None, options=None, passwords=None, connection_lockfd=None):
@ -227,10 +228,10 @@ class PlayContext(Base):
if passwords is None: if passwords is None:
passwords = {} passwords = {}
self.password = passwords.get('conn_pass','') self.password = passwords.get('conn_pass', '')
self.become_pass = passwords.get('become_pass','') self.become_pass = passwords.get('become_pass', '')
self.prompt = '' self.prompt = ''
self.success_key = '' self.success_key = ''
# a file descriptor to be used during locking operations # a file descriptor to be used during locking operations
@ -243,7 +244,6 @@ class PlayContext(Base):
if play: if play:
self.set_play(play) self.set_play(play)
def set_play(self, play): def set_play(self, play):
''' '''
Configures this connection information instance with data from Configures this connection information instance with data from
@ -283,18 +283,18 @@ class PlayContext(Base):
''' '''
# privilege escalation # privilege escalation
self.become = options.become self.become = options.become
self.become_method = options.become_method self.become_method = options.become_method
self.become_user = options.become_user self.become_user = options.become_user
self.check_mode = boolean(options.check) self.check_mode = boolean(options.check)
# get ssh options FIXME: make these common to all connections # get ssh options FIXME: make these common to all connections
for flag in ['ssh_common_args', 'docker_extra_args', 'sftp_extra_args', 'scp_extra_args', 'ssh_extra_args']: for flag in ['ssh_common_args', 'docker_extra_args', 'sftp_extra_args', 'scp_extra_args', 'ssh_extra_args']:
setattr(self, flag, getattr(options,flag, '')) setattr(self, flag, getattr(options, flag, ''))
# general flags (should we move out?) # general flags (should we move out?)
for flag in ['connection','remote_user', 'private_key_file', 'verbosity', 'force_handlers', 'step', 'start_at_task', 'diff']: for flag in ['connection', 'remote_user', 'private_key_file', 'verbosity', 'force_handlers', 'step', 'start_at_task', 'diff']:
attribute = getattr(options, flag, False) attribute = getattr(options, flag, False)
if attribute: if attribute:
setattr(self, flag, attribute) setattr(self, flag, attribute)
@ -435,7 +435,7 @@ class PlayContext(Base):
if connection_type in delegated_vars: if connection_type in delegated_vars:
break break
else: else:
remote_addr_local = new_info.remote_addr in C.LOCALHOST remote_addr_local = new_info.remote_addr in C.LOCALHOST
inv_hostname_local = delegated_vars.get('inventory_hostname') in C.LOCALHOST inv_hostname_local = delegated_vars.get('inventory_hostname') in C.LOCALHOST
if remote_addr_local and inv_hostname_local: if remote_addr_local and inv_hostname_local:
setattr(new_info, 'connection', 'local') setattr(new_info, 'connection', 'local')
@ -464,13 +464,12 @@ class PlayContext(Base):
if task.check_mode is not None: if task.check_mode is not None:
new_info.check_mode = task.check_mode new_info.check_mode = task.check_mode
return new_info return new_info
def make_become_cmd(self, cmd, executable=None): def make_become_cmd(self, cmd, executable=None):
""" helper function to create privilege escalation commands """ """ helper function to create privilege escalation commands """
prompt = None prompt = None
success_key = None success_key = None
self.prompt = None self.prompt = None
@ -479,8 +478,8 @@ class PlayContext(Base):
if not executable: if not executable:
executable = self.executable executable = self.executable
becomecmd = None becomecmd = None
randbits = ''.join(random.choice(string.ascii_lowercase) for x in range(32)) randbits = ''.join(random.choice(string.ascii_lowercase) for x in range(32))
success_key = 'BECOME-SUCCESS-%s' % randbits success_key = 'BECOME-SUCCESS-%s' % randbits
success_cmd = shlex_quote('echo %s; %s' % (success_key, cmd)) success_cmd = shlex_quote('echo %s; %s' % (success_key, cmd))
@ -490,18 +489,22 @@ class PlayContext(Base):
command = success_cmd command = success_cmd
# set executable to use for the privilege escalation method, with various overrides # set executable to use for the privilege escalation method, with various overrides
exe = self.become_exe or \ exe = (
getattr(self, '%s_exe' % self.become_method, None) or \ self.become_exe or
C.DEFAULT_BECOME_EXE or \ getattr(self, '%s_exe' % self.become_method, None) or
getattr(C, 'DEFAULT_%s_EXE' % self.become_method.upper(), None) or \ C.DEFAULT_BECOME_EXE or
self.become_method getattr(C, 'DEFAULT_%s_EXE' % self.become_method.upper(), None) or
self.become_method
)
# set flags to use for the privilege escalation method, with various overrides # set flags to use for the privilege escalation method, with various overrides
flags = self.become_flags or \ flags = (
getattr(self, '%s_flags' % self.become_method, None) or \ self.become_flags or
C.DEFAULT_BECOME_FLAGS or \ getattr(self, '%s_flags' % self.become_method, None) or
getattr(C, 'DEFAULT_%s_FLAGS' % self.become_method.upper(), None) or \ C.DEFAULT_BECOME_FLAGS or
'' getattr(C, 'DEFAULT_%s_FLAGS' % self.become_method.upper(), None) or
''
)
if self.become_method == 'sudo': if self.become_method == 'sudo':
# If we have a password, we run sudo with a randomly-generated # If we have a password, we run sudo with a randomly-generated
@ -517,11 +520,10 @@ class PlayContext(Base):
# force quick error if password is required but not supplied, should prevent sudo hangs. # force quick error if password is required but not supplied, should prevent sudo hangs.
if self.become_pass: if self.become_pass:
prompt = '[sudo via ansible, key=%s] password: ' % randbits prompt = '[sudo via ansible, key=%s] password: ' % randbits
becomecmd = '%s %s -p "%s" -u %s %s' % (exe, flags.replace('-n',''), prompt, self.become_user, command) becomecmd = '%s %s -p "%s" -u %s %s' % (exe, flags.replace('-n', ''), prompt, self.become_user, command)
else: else:
becomecmd = '%s %s -u %s %s' % (exe, flags, self.become_user, command) becomecmd = '%s %s -u %s %s' % (exe, flags, self.become_user, command)
elif self.become_method == 'su': elif self.become_method == 'su':
# passing code ref to examine prompt as simple string comparisson isn't good enough with su # passing code ref to examine prompt as simple string comparisson isn't good enough with su
@ -537,7 +539,7 @@ class PlayContext(Base):
elif self.become_method == 'pbrun': elif self.become_method == 'pbrun':
prompt='Password:' prompt = 'Password:'
becomecmd = '%s %s -u %s %s' % (exe, flags, self.become_user, success_cmd) becomecmd = '%s %s -u %s %s' % (exe, flags, self.become_user, success_cmd)
elif self.become_method == 'ksu': elif self.become_method == 'ksu':
@ -575,7 +577,7 @@ class PlayContext(Base):
if self.become_user: if self.become_user:
flags += ' -u %s ' % self.become_user flags += ' -u %s ' % self.become_user
#FIXME: make shell independent # FIXME: make shell independent
becomecmd = '%s %s echo %s && %s %s env ANSIBLE=true %s' % (exe, flags, success_key, exe, flags, cmd) becomecmd = '%s %s echo %s && %s %s env ANSIBLE=true %s' % (exe, flags, success_key, exe, flags, cmd)
elif self.become_method == 'dzdo': elif self.become_method == 'dzdo':
@ -591,7 +593,7 @@ class PlayContext(Base):
exe = self.become_exe or 'pmrun' exe = self.become_exe or 'pmrun'
prompt='Enter UPM user password:' prompt = 'Enter UPM user password:'
becomecmd = '%s %s %s' % (exe, flags, shlex_quote(command)) becomecmd = '%s %s %s' % (exe, flags, shlex_quote(command))
else: else:
@ -645,4 +647,3 @@ class PlayContext(Base):
self.connection = conn_type self.connection = conn_type
return self._attributes['connection'] return self._attributes['connection']

View file

@ -34,9 +34,9 @@ from ansible.template import Templar
class PlaybookInclude(Base, Conditional, Taggable): class PlaybookInclude(Base, Conditional, Taggable):
_name = FieldAttribute(isa='string') _name = FieldAttribute(isa='string')
_include = FieldAttribute(isa='string') _include = FieldAttribute(isa='string')
_vars = FieldAttribute(isa='dict', default=dict()) _vars = FieldAttribute(isa='dict', default=dict())
@staticmethod @staticmethod
def load(data, basedir, variable_manager=None, loader=None): def load(data, basedir, variable_manager=None, loader=None):
@ -113,7 +113,7 @@ class PlaybookInclude(Base, Conditional, Taggable):
if isinstance(ds, AnsibleBaseYAMLObject): if isinstance(ds, AnsibleBaseYAMLObject):
new_ds.ansible_pos = ds.ansible_pos new_ds.ansible_pos = ds.ansible_pos
for (k,v) in iteritems(ds): for (k, v) in iteritems(ds):
if k == 'include': if k == 'include':
self._preprocess_include(ds, new_ds, k, v) self._preprocess_include(ds, new_ds, k, v)
else: else:
@ -152,4 +152,3 @@ class PlaybookInclude(Base, Conditional, Taggable):
if 'vars' in new_ds: if 'vars' in new_ds:
raise AnsibleParserError("include parameters cannot be mixed with 'vars' entries for include statements", obj=ds) raise AnsibleParserError("include parameters cannot be mixed with 'vars' entries for include statements", obj=ds)
new_ds['vars'] = params new_ds['vars'] = params

View file

@ -42,6 +42,7 @@ __all__ = ['Role', 'hash_params']
# in a static method. This is also used in the base class for # in a static method. This is also used in the base class for
# strategies (ansible/plugins/strategy/__init__.py) # strategies (ansible/plugins/strategy/__init__.py)
def hash_params(params): def hash_params(params):
""" """
Construct a data structure of parameters that is hashable. Construct a data structure of parameters that is hashable.
@ -96,21 +97,21 @@ class Role(Base, Become, Conditional, Taggable):
_delegate_facts = FieldAttribute(isa='bool', default=False) _delegate_facts = FieldAttribute(isa='bool', default=False)
def __init__(self, play=None, from_files=None): def __init__(self, play=None, from_files=None):
self._role_name = None self._role_name = None
self._role_path = None self._role_path = None
self._role_params = dict() self._role_params = dict()
self._loader = None self._loader = None
self._metadata = None self._metadata = None
self._play = play self._play = play
self._parents = [] self._parents = []
self._dependencies = [] self._dependencies = []
self._task_blocks = [] self._task_blocks = []
self._handler_blocks = [] self._handler_blocks = []
self._default_vars = dict() self._default_vars = dict()
self._role_vars = dict() self._role_vars = dict()
self._had_task_run = dict() self._had_task_run = dict()
self._completed = dict() self._completed = dict()
if from_files is None: if from_files is None:
from_files = {} from_files = {}
@ -166,11 +167,11 @@ class Role(Base, Become, Conditional, Taggable):
obj=role_include._ds) obj=role_include._ds)
def _load_role_data(self, role_include, parent_role=None): def _load_role_data(self, role_include, parent_role=None):
self._role_name = role_include.role self._role_name = role_include.role
self._role_path = role_include.get_role_path() self._role_path = role_include.get_role_path()
self._role_params = role_include.get_role_params() self._role_params = role_include.get_role_params()
self._variable_manager = role_include.get_variable_manager() self._variable_manager = role_include.get_variable_manager()
self._loader = role_include.get_loader() self._loader = role_include.get_loader()
if parent_role: if parent_role:
self.add_parent(parent_role) self.add_parent(parent_role)
@ -209,7 +210,7 @@ class Role(Base, Become, Conditional, Taggable):
try: try:
self._task_blocks = load_list_of_blocks(task_data, play=self._play, role=self, loader=self._loader, variable_manager=self._variable_manager) self._task_blocks = load_list_of_blocks(task_data, play=self._play, role=self, loader=self._loader, variable_manager=self._variable_manager)
except AssertionError: except AssertionError:
raise AnsibleParserError("The tasks/main.yml file for role '%s' must contain a list of tasks" % self._role_name , obj=task_data) raise AnsibleParserError("The tasks/main.yml file for role '%s' must contain a list of tasks" % self._role_name, obj=task_data)
handler_data = self._load_role_yaml('handlers') handler_data = self._load_role_yaml('handlers')
if handler_data: if handler_data:
@ -217,10 +218,10 @@ class Role(Base, Become, Conditional, Taggable):
self._handler_blocks = load_list_of_blocks(handler_data, play=self._play, role=self, use_handlers=True, loader=self._loader, self._handler_blocks = load_list_of_blocks(handler_data, play=self._play, role=self, use_handlers=True, loader=self._loader,
variable_manager=self._variable_manager) variable_manager=self._variable_manager)
except AssertionError: except AssertionError:
raise AnsibleParserError("The handlers/main.yml file for role '%s' must contain a list of tasks" % self._role_name , obj=handler_data) raise AnsibleParserError("The handlers/main.yml file for role '%s' must contain a list of tasks" % self._role_name, obj=handler_data)
# vars and default vars are regular dictionaries # vars and default vars are regular dictionaries
self._role_vars = self._load_role_yaml('vars', main=self._from_files.get('vars')) self._role_vars = self._load_role_yaml('vars', main=self._from_files.get('vars'))
if self._role_vars is None: if self._role_vars is None:
self._role_vars = dict() self._role_vars = dict()
elif not isinstance(self._role_vars, dict): elif not isinstance(self._role_vars, dict):
@ -239,7 +240,7 @@ class Role(Base, Become, Conditional, Taggable):
if self._loader.path_exists(main_file): if self._loader.path_exists(main_file):
return self._loader.load_from_file(main_file) return self._loader.load_from_file(main_file)
elif main is not None: elif main is not None:
raise AnsibleParserError("Could not find specified file in role: %s/%s" % (subdir,main)) raise AnsibleParserError("Could not find specified file in role: %s/%s" % (subdir, main))
return None return None
def _resolve_main(self, basepath, main=None): def _resolve_main(self, basepath, main=None):
@ -269,8 +270,8 @@ class Role(Base, Become, Conditional, Taggable):
else: else:
for m in possible_mains: for m in possible_mains:
if self._loader.is_file(m): if self._loader.is_file(m):
return m # exactly one main file return m # exactly one main file
return possible_mains[0] # zero mains (we still need to return something) return possible_mains[0] # zero mains (we still need to return something)
def _load_dependencies(self): def _load_dependencies(self):
''' '''
@ -286,7 +287,6 @@ class Role(Base, Become, Conditional, Taggable):
return deps return deps
#------------------------------------------------------------------------------
# other functions # other functions
def add_parent(self, parent_role): def add_parent(self, parent_role):
@ -347,7 +347,7 @@ class Role(Base, Become, Conditional, Taggable):
in the proper order in which they should be executed or evaluated. in the proper order in which they should be executed or evaluated.
''' '''
child_deps = [] child_deps = []
for dep in self.get_direct_dependencies(): for dep in self.get_direct_dependencies():
for child_dep in dep.get_all_dependencies(): for child_dep in dep.get_all_dependencies():
@ -425,13 +425,13 @@ class Role(Base, Become, Conditional, Taggable):
def serialize(self, include_deps=True): def serialize(self, include_deps=True):
res = super(Role, self).serialize() res = super(Role, self).serialize()
res['_role_name'] = self._role_name res['_role_name'] = self._role_name
res['_role_path'] = self._role_path res['_role_path'] = self._role_path
res['_role_vars'] = self._role_vars res['_role_vars'] = self._role_vars
res['_role_params'] = self._role_params res['_role_params'] = self._role_params
res['_default_vars'] = self._default_vars res['_default_vars'] = self._default_vars
res['_had_task_run'] = self._had_task_run.copy() res['_had_task_run'] = self._had_task_run.copy()
res['_completed'] = self._completed.copy() res['_completed'] = self._completed.copy()
if self._metadata: if self._metadata:
res['_metadata'] = self._metadata.serialize() res['_metadata'] = self._metadata.serialize()
@ -450,13 +450,13 @@ class Role(Base, Become, Conditional, Taggable):
return res return res
def deserialize(self, data, include_deps=True): def deserialize(self, data, include_deps=True):
self._role_name = data.get('_role_name', '') self._role_name = data.get('_role_name', '')
self._role_path = data.get('_role_path', '') self._role_path = data.get('_role_path', '')
self._role_vars = data.get('_role_vars', dict()) self._role_vars = data.get('_role_vars', dict())
self._role_params = data.get('_role_params', dict()) self._role_params = data.get('_role_params', dict())
self._default_vars = data.get('_default_vars', dict()) self._default_vars = data.get('_default_vars', dict())
self._had_task_run = data.get('_had_task_run', dict()) self._had_task_run = data.get('_had_task_run', dict())
self._completed = data.get('_completed', dict()) self._completed = data.get('_completed', dict())
if include_deps: if include_deps:
deps = [] deps = []
@ -488,4 +488,3 @@ class Role(Base, Become, Conditional, Taggable):
parent.set_loader(loader) parent.set_loader(loader)
for dep in self.get_direct_dependencies(): for dep in self.get_direct_dependencies():
dep.set_loader(loader) dep.set_loader(loader)

View file

@ -51,16 +51,16 @@ class RoleDefinition(Base, Become, Conditional, Taggable):
super(RoleDefinition, self).__init__() super(RoleDefinition, self).__init__()
self._play = play self._play = play
self._variable_manager = variable_manager self._variable_manager = variable_manager
self._loader = loader self._loader = loader
self._role_path = None self._role_path = None
self._role_basedir = role_basedir self._role_basedir = role_basedir
self._role_params = dict() self._role_params = dict()
#def __repr__(self): # def __repr__(self):
# return 'ROLEDEF: ' + self._attributes.get('role', '<no name set>') # return 'ROLEDEF: ' + self._attributes.get('role', '<no name set>')
@staticmethod @staticmethod
def load(data, variable_manager=None, loader=None): def load(data, variable_manager=None, loader=None):
@ -205,8 +205,8 @@ class RoleDefinition(Base, Become, Conditional, Taggable):
# remember to update it manually. # remember to update it manually.
if key not in base_attribute_names or key in ('connection', 'port', 'remote_user'): if key not in base_attribute_names or key in ('connection', 'port', 'remote_user'):
if key in ('connection', 'port', 'remote_user'): if key in ('connection', 'port', 'remote_user'):
display.deprecated("Using '%s' as a role param has been deprecated. " % key + \ display.deprecated("Using '%s' as a role param has been deprecated. " % key +
"In the future, these values should be entered in the `vars:` " + \ "In the future, these values should be entered in the `vars:` " +
"section for roles, but for now we'll store it as both a param and an attribute.", version="2.7") "section for roles, but for now we'll store it as both a param and an attribute.", version="2.7")
role_def[key] = value role_def[key] = value
# this key does not match a field attribute, so it must be a role param # this key does not match a field attribute, so it must be a role param

View file

@ -40,7 +40,7 @@ class RoleInclude(RoleDefinition):
is included for execution in a play. is included for execution in a play.
""" """
_delegate_to = FieldAttribute(isa='string') _delegate_to = FieldAttribute(isa='string')
_delegate_facts = FieldAttribute(isa='bool', default=False) _delegate_facts = FieldAttribute(isa='bool', default=False)
def __init__(self, play=None, role_basedir=None, variable_manager=None, loader=None): def __init__(self, play=None, role_basedir=None, variable_manager=None, loader=None):
@ -57,4 +57,3 @@ class RoleInclude(RoleDefinition):
ri = RoleInclude(play=play, role_basedir=current_role_path, variable_manager=variable_manager, loader=loader) ri = RoleInclude(play=play, role_basedir=current_role_path, variable_manager=variable_manager, loader=loader)
return ri.load_data(data, variable_manager=variable_manager, loader=loader) return ri.load_data(data, variable_manager=variable_manager, loader=loader)

View file

@ -39,8 +39,8 @@ class RoleMetadata(Base):
''' '''
_allow_duplicates = FieldAttribute(isa='bool', default=False) _allow_duplicates = FieldAttribute(isa='bool', default=False)
_dependencies = FieldAttribute(isa='list', default=[]) _dependencies = FieldAttribute(isa='list', default=[])
_galaxy_info = FieldAttribute(isa='GalaxyInfo') _galaxy_info = FieldAttribute(isa='GalaxyInfo')
def __init__(self, owner=None): def __init__(self, owner=None):
self._owner = owner self._owner = owner
@ -103,8 +103,8 @@ class RoleMetadata(Base):
def serialize(self): def serialize(self):
return dict( return dict(
allow_duplicates = self._allow_duplicates, allow_duplicates=self._allow_duplicates,
dependencies = self._dependencies, dependencies=self._dependencies,
) )
def deserialize(self, data): def deserialize(self, data):

View file

@ -46,6 +46,7 @@ except ImportError:
from ansible.utils.display import Display from ansible.utils.display import Display
display = Display() display = Display()
class RoleRequirement(RoleDefinition): class RoleRequirement(RoleDefinition):
""" """
@ -193,7 +194,7 @@ class RoleRequirement(RoleDefinition):
raise AnsibleError("error executing: %s" % " ".join(clone_cmd)) raise AnsibleError("error executing: %s" % " ".join(clone_cmd))
rc = popen.wait() rc = popen.wait()
if rc != 0: if rc != 0:
raise AnsibleError ("- command %s failed in directory %s (rc=%s)" % (' '.join(clone_cmd), tempdir, rc)) raise AnsibleError("- command %s failed in directory %s (rc=%s)" % (' '.join(clone_cmd), tempdir, rc))
if scm == 'git' and version: if scm == 'git' and version:
checkout_cmd = [scm, 'checkout', version] checkout_cmd = [scm, 'checkout', version]
@ -228,4 +229,3 @@ class RoleRequirement(RoleDefinition):
shutil.rmtree(tempdir, ignore_errors=True) shutil.rmtree(tempdir, ignore_errors=True)
return temp_file.name return temp_file.name

View file

@ -60,12 +60,11 @@ class IncludeRole(Task):
self._parent_role = role self._parent_role = role
self._role_name = None self._role_name = None
def get_block_list(self, play=None, variable_manager=None, loader=None): def get_block_list(self, play=None, variable_manager=None, loader=None):
# only need play passed in when dynamic # only need play passed in when dynamic
if play is None: if play is None:
myplay = self._parent._play myplay = self._parent._play
else: else:
myplay = play myplay = play
@ -99,7 +98,7 @@ class IncludeRole(Task):
ir = IncludeRole(block, role, task_include=task_include).load_data(data, variable_manager=variable_manager, loader=loader) ir = IncludeRole(block, role, task_include=task_include).load_data(data, variable_manager=variable_manager, loader=loader)
### Process options # Process options
# name is needed, or use role as alias # name is needed, or use role as alias
ir._role_name = ir.args.get('name', ir.args.get('role')) ir._role_name = ir.args.get('name', ir.args.get('role'))
if ir._role_name is None: if ir._role_name is None:
@ -107,11 +106,11 @@ class IncludeRole(Task):
# build options for role includes # build options for role includes
for key in ['tasks', 'vars', 'defaults']: for key in ['tasks', 'vars', 'defaults']:
from_key ='%s_from' % key from_key = '%s_from' % key
if ir.args.get(from_key): if ir.args.get(from_key):
ir._from_files[key] = basename(ir.args.get(from_key)) ir._from_files[key] = basename(ir.args.get(from_key))
#FIXME: find a way to make this list come from object ( attributes does not work as per below) # FIXME: find a way to make this list come from object ( attributes does not work as per below)
# manual list as otherwise the options would set other task parameters we don't want. # manual list as otherwise the options would set other task parameters we don't want.
for option in ['private', 'allow_duplicates']: for option in ['private', 'allow_duplicates']:
if option in ir.args: if option in ir.args:
@ -125,7 +124,7 @@ class IncludeRole(Task):
new_me.statically_loaded = self.statically_loaded new_me.statically_loaded = self.statically_loaded
new_me._from_files = self._from_files.copy() new_me._from_files = self._from_files.copy()
new_me._parent_role = self._parent_role new_me._parent_role = self._parent_role
new_me._role_name = self._role_name new_me._role_name = self._role_name
return new_me return new_me

View file

@ -30,7 +30,7 @@ from ansible.template import Templar
class Taggable: class Taggable:
untagged = frozenset(['untagged']) untagged = frozenset(['untagged'])
_tags = FieldAttribute(isa='list', default=[], listof=(string_types,int)) _tags = FieldAttribute(isa='list', default=[], listof=(string_types, int))
def __init__(self): def __init__(self):
super(Taggable, self).__init__() super(Taggable, self).__init__()
@ -41,9 +41,9 @@ class Taggable:
elif isinstance(ds, string_types): elif isinstance(ds, string_types):
value = ds.split(',') value = ds.split(',')
if isinstance(value, list): if isinstance(value, list):
return [ x.strip() for x in value ] return [x.strip() for x in value]
else: else:
return [ ds ] return [ds]
else: else:
raise AnsibleError('tags must be specified as a list', obj=ds) raise AnsibleError('tags must be specified as a list', obj=ds)
@ -73,7 +73,7 @@ class Taggable:
else: else:
tags = set([tags]) tags = set([tags])
else: else:
tags = set([i for i,_ in itertools.groupby(tags)]) tags = set([i for i, _ in itertools.groupby(tags)])
else: else:
# this makes isdisjoint work for untagged # this makes isdisjoint work for untagged
tags = self.untagged tags = self.untagged

View file

@ -65,29 +65,29 @@ class Task(Base, Conditional, Taggable, Become):
# will be used if defined # will be used if defined
# might be possible to define others # might be possible to define others
_args = FieldAttribute(isa='dict', default=dict()) _args = FieldAttribute(isa='dict', default=dict())
_action = FieldAttribute(isa='string') _action = FieldAttribute(isa='string')
_async = FieldAttribute(isa='int', default=0) _async = FieldAttribute(isa='int', default=0)
_changed_when = FieldAttribute(isa='list', default=[]) _changed_when = FieldAttribute(isa='list', default=[])
_delay = FieldAttribute(isa='int', default=5) _delay = FieldAttribute(isa='int', default=5)
_delegate_to = FieldAttribute(isa='string') _delegate_to = FieldAttribute(isa='string')
_delegate_facts = FieldAttribute(isa='bool', default=False) _delegate_facts = FieldAttribute(isa='bool', default=False)
_failed_when = FieldAttribute(isa='list', default=[]) _failed_when = FieldAttribute(isa='list', default=[])
_loop = FieldAttribute(isa='string', private=True, inherit=False) _loop = FieldAttribute(isa='string', private=True, inherit=False)
_loop_args = FieldAttribute(isa='list', private=True, inherit=False) _loop_args = FieldAttribute(isa='list', private=True, inherit=False)
_loop_control = FieldAttribute(isa='class', class_type=LoopControl, inherit=False) _loop_control = FieldAttribute(isa='class', class_type=LoopControl, inherit=False)
_name = FieldAttribute(isa='string', default='') _name = FieldAttribute(isa='string', default='')
_notify = FieldAttribute(isa='list') _notify = FieldAttribute(isa='list')
_poll = FieldAttribute(isa='int', default=10) _poll = FieldAttribute(isa='int', default=10)
_register = FieldAttribute(isa='string') _register = FieldAttribute(isa='string')
_retries = FieldAttribute(isa='int') _retries = FieldAttribute(isa='int')
_until = FieldAttribute(isa='list', default=[]) _until = FieldAttribute(isa='list', default=[])
def __init__(self, block=None, role=None, task_include=None): def __init__(self, block=None, role=None, task_include=None):
''' constructors a task, without the Task.load classmethod, it will be pretty blank ''' ''' constructors a task, without the Task.load classmethod, it will be pretty blank '''
self._role = role self._role = role
self._parent = None self._parent = None
if task_include: if task_include:
@ -125,10 +125,10 @@ class Task(Base, Conditional, Taggable, Become):
return ds return ds
elif isinstance(ds, dict): elif isinstance(ds, dict):
buf = "" buf = ""
for (k,v) in iteritems(ds): for (k, v) in iteritems(ds):
if k.startswith('_'): if k.startswith('_'):
continue continue
buf = buf + "%s=%s " % (k,v) buf = buf + "%s=%s " % (k, v)
buf = buf.strip() buf = buf.strip()
return buf return buf
@ -186,11 +186,11 @@ class Task(Base, Conditional, Taggable, Become):
if 'cmd' in args: if 'cmd' in args:
if args.get('_raw_params', '') != '': if args.get('_raw_params', '') != '':
raise AnsibleError("The 'cmd' argument cannot be used when other raw parameters are specified." raise AnsibleError("The 'cmd' argument cannot be used when other raw parameters are specified."
" Please put everything in one or the other place.", obj=ds) " Please put everything in one or the other place.", obj=ds)
args['_raw_params'] = args.pop('cmd') args['_raw_params'] = args.pop('cmd')
new_ds['action'] = action new_ds['action'] = action
new_ds['args'] = args new_ds['args'] = args
new_ds['delegate_to'] = delegate_to new_ds['delegate_to'] = delegate_to
# we handle any 'vars' specified in the ds here, as we may # we handle any 'vars' specified in the ds here, as we may
@ -203,7 +203,7 @@ class Task(Base, Conditional, Taggable, Become):
else: else:
new_ds['vars'] = dict() new_ds['vars'] = dict()
for (k,v) in iteritems(ds): for (k, v) in iteritems(ds):
if k in ('action', 'local_action', 'args', 'delegate_to') or k == action or k == 'shell': if k in ('action', 'local_action', 'args', 'delegate_to') or k == action or k == 'shell':
# we don't want to re-assign these values, which were # we don't want to re-assign these values, which were
# determined by the ModuleArgsParser() above # determined by the ModuleArgsParser() above
@ -216,9 +216,9 @@ class Task(Base, Conditional, Taggable, Become):
# here, and show a deprecation message as we will remove this at # here, and show a deprecation message as we will remove this at
# some point in the future. # some point in the future.
if action == 'include' and k not in self._valid_attrs and k not in self.DEPRECATED_ATTRIBUTES: if action == 'include' and k not in self._valid_attrs and k not in self.DEPRECATED_ATTRIBUTES:
display.deprecated("Specifying include variables at the top-level of the task is deprecated." display.deprecated("Specifying include variables at the top-level of the task is deprecated. "
" Please see:\nhttp://docs.ansible.com/ansible/playbooks_roles.html#task-include-files-and-encouraging-reuse\n\n" "Please see:\nhttp://docs.ansible.com/ansible/playbooks_roles.html#task-include-files-and-encouraging-reuse\n\n "
" for currently supported syntax regarding included files and variables", version="2.7") "for currently supported syntax regarding included files and variables", version="2.7")
new_ds['vars'][k] = v new_ds['vars'][k] = v
else: else:
new_ds[k] = v new_ds[k] = v

View file

@ -76,4 +76,3 @@ class TaskInclude(Task):
del all_vars['when'] del all_vars['when']
return all_vars return all_vars

View file

@ -62,11 +62,11 @@ class PluginLoader:
def __init__(self, class_name, package, config, subdir, aliases={}, required_base_class=None): def __init__(self, class_name, package, config, subdir, aliases={}, required_base_class=None):
self.class_name = class_name self.class_name = class_name
self.base_class = required_base_class self.base_class = required_base_class
self.package = package self.package = package
self.subdir = subdir self.subdir = subdir
self.aliases = aliases self.aliases = aliases
if config and not isinstance(config, list): if config and not isinstance(config, list):
config = [config] config = [config]
@ -82,8 +82,8 @@ class PluginLoader:
if class_name not in PLUGIN_PATH_CACHE: if class_name not in PLUGIN_PATH_CACHE:
PLUGIN_PATH_CACHE[class_name] = defaultdict(dict) PLUGIN_PATH_CACHE[class_name] = defaultdict(dict)
self._module_cache = MODULE_CACHE[class_name] self._module_cache = MODULE_CACHE[class_name]
self._paths = PATH_CACHE[class_name] self._paths = PATH_CACHE[class_name]
self._plugin_path_cache = PLUGIN_PATH_CACHE[class_name] self._plugin_path_cache = PLUGIN_PATH_CACHE[class_name]
self._extra_dirs = [] self._extra_dirs = []
@ -95,10 +95,10 @@ class PluginLoader:
''' '''
class_name = data.get('class_name') class_name = data.get('class_name')
package = data.get('package') package = data.get('package')
config = data.get('config') config = data.get('config')
subdir = data.get('subdir') subdir = data.get('subdir')
aliases = data.get('aliases') aliases = data.get('aliases')
base_class = data.get('base_class') base_class = data.get('base_class')
PATH_CACHE[class_name] = data.get('PATH_CACHE') PATH_CACHE[class_name] = data.get('PATH_CACHE')
@ -114,16 +114,16 @@ class PluginLoader:
''' '''
return dict( return dict(
class_name = self.class_name, class_name=self.class_name,
base_class = self.base_class, base_class=self.base_class,
package = self.package, package=self.package,
config = self.config, config=self.config,
subdir = self.subdir, subdir=self.subdir,
aliases = self.aliases, aliases=self.aliases,
_extra_dirs = self._extra_dirs, _extra_dirs=self._extra_dirs,
_searched_paths = self._searched_paths, _searched_paths=self._searched_paths,
PATH_CACHE = PATH_CACHE[self.class_name], PATH_CACHE=PATH_CACHE[self.class_name],
PLUGIN_PATH_CACHE = PLUGIN_PATH_CACHE[self.class_name], PLUGIN_PATH_CACHE=PLUGIN_PATH_CACHE[self.class_name],
) )
def format_paths(self, paths): def format_paths(self, paths):
@ -145,7 +145,7 @@ class PluginLoader:
for root, subdirs, files in os.walk(dir, followlinks=True): for root, subdirs, files in os.walk(dir, followlinks=True):
if '__init__.py' in files: if '__init__.py' in files:
for x in subdirs: for x in subdirs:
results.append(os.path.join(root,x)) results.append(os.path.join(root, x))
return results return results
def _get_package_paths(self, subdirs=True): def _get_package_paths(self, subdirs=True):
@ -271,7 +271,7 @@ class PluginLoader:
# HACK: We have no way of executing python byte # HACK: We have no way of executing python byte
# compiled files as ansible modules so specifically exclude them # compiled files as ansible modules so specifically exclude them
### FIXME: I believe this is only correct for modules and # FIXME: I believe this is only correct for modules and
# module_utils. For all other plugins we want .pyc and .pyo should # module_utils. For all other plugins we want .pyc and .pyo should
# bew valid # bew valid
if full_path.endswith(('.pyc', '.pyo')): if full_path.endswith(('.pyc', '.pyo')):
@ -313,10 +313,10 @@ class PluginLoader:
if alias_name in pull_cache: if alias_name in pull_cache:
if not ignore_deprecated and not os.path.islink(pull_cache[alias_name]): if not ignore_deprecated and not os.path.islink(pull_cache[alias_name]):
display.deprecated('%s is kept for backwards compatibility ' display.deprecated('%s is kept for backwards compatibility '
'but usage is discouraged. The module ' 'but usage is discouraged. The module '
'documentation details page may explain ' 'documentation details page may explain '
'more about this rationale.' % 'more about this rationale.' %
name.lstrip('_')) name.lstrip('_'))
return pull_cache[alias_name] return pull_cache[alias_name]
return None return None
@ -550,4 +550,3 @@ vars_loader = PluginLoader(
C.DEFAULT_VARS_PLUGIN_PATH, C.DEFAULT_VARS_PLUGIN_PATH,
'vars_plugins', 'vars_plugins',
) )

View file

@ -59,18 +59,18 @@ class ActionBase(with_metaclass(ABCMeta, object)):
''' '''
def __init__(self, task, connection, play_context, loader, templar, shared_loader_obj): def __init__(self, task, connection, play_context, loader, templar, shared_loader_obj):
self._task = task self._task = task
self._connection = connection self._connection = connection
self._play_context = play_context self._play_context = play_context
self._loader = loader self._loader = loader
self._templar = templar self._templar = templar
self._shared_loader_obj = shared_loader_obj self._shared_loader_obj = shared_loader_obj
# Backwards compat: self._display isn't really needed, just import the global display and use that. # Backwards compat: self._display isn't really needed, just import the global display and use that.
self._display = display self._display = display
self._cleanup_remote_tmp = False self._cleanup_remote_tmp = False
self._supports_check_mode = True self._supports_check_mode = True
self._supports_async = False self._supports_async = False
@abstractmethod @abstractmethod
def run(self, tmp=None, task_vars=None): def run(self, tmp=None, task_vars=None):
@ -154,7 +154,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
# insert shared code and arguments into the module # insert shared code and arguments into the module
(module_data, module_style, module_shebang) = modify_module(module_name, module_path, module_args, (module_data, module_style, module_shebang) = modify_module(module_name, module_path, module_args,
task_vars=task_vars, module_compression=self._play_context.module_compression) task_vars=task_vars, module_compression=self._play_context.module_compression)
# FUTURE: we'll have to get fancier about this to support powershell over SSH on Windows... # FUTURE: we'll have to get fancier about this to support powershell over SSH on Windows...
if self._connection.transport == "winrm": if self._connection.transport == "winrm":
@ -162,9 +162,9 @@ class ActionBase(with_metaclass(ABCMeta, object)):
final_environment = dict() final_environment = dict()
self._compute_environment_string(final_environment) self._compute_environment_string(final_environment)
module_data = build_windows_module_payload(module_name=module_name, module_path=module_path, module_data = build_windows_module_payload(module_name=module_name, module_path=module_path,
b_module_data=module_data, module_args=module_args, b_module_data=module_data, module_args=module_args,
task_vars=task_vars, task=self._task, task_vars=task_vars, task=self._task,
play_context=self._play_context, environment=final_environment) play_context=self._play_context, environment=final_environment)
return (module_style, module_shebang, module_data, module_path) return (module_style, module_shebang, module_data, module_path)
@ -177,7 +177,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
if self._task.environment is not None: if self._task.environment is not None:
environments = self._task.environment environments = self._task.environment
if not isinstance(environments, list): if not isinstance(environments, list):
environments = [ environments ] environments = [environments]
# the environments as inherited need to be reversed, to make # the environments as inherited need to be reversed, to make
# sure we merge in the parent's values first so those in the # sure we merge in the parent's values first so those in the
@ -213,7 +213,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
Determines if we are required and can do pipelining Determines if we are required and can do pipelining
''' '''
if self._connection.always_pipeline_modules: if self._connection.always_pipeline_modules:
return True #eg, winrm return True # eg, winrm
# any of these require a true # any of these require a true
for condition in [ for condition in [
@ -249,7 +249,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
if use_system_tmp: if use_system_tmp:
tmpdir = None tmpdir = None
else: else:
tmpdir = self._remote_expand_user(C.DEFAULT_REMOTE_TMP, sudoable=False) tmpdir = self._remote_expand_user(C.DEFAULT_REMOTE_TMP, sudoable=False)
cmd = self._connection._shell.mkdtemp(basefile, use_system_tmp, tmp_mode, tmpdir) cmd = self._connection._shell.mkdtemp(basefile, use_system_tmp, tmp_mode, tmpdir)
result = self._low_level_execute_command(cmd, sudoable=False) result = self._low_level_execute_command(cmd, sudoable=False)
@ -263,16 +263,16 @@ class ActionBase(with_metaclass(ABCMeta, object)):
if self._play_context.verbosity > 3: if self._play_context.verbosity > 3:
output = u'SSH encountered an unknown error. The output was:\n%s%s' % (result['stdout'], result['stderr']) output = u'SSH encountered an unknown error. The output was:\n%s%s' % (result['stdout'], result['stderr'])
else: else:
output = (u'SSH encountered an unknown error during the connection.' output = (u'SSH encountered an unknown error during the connection. '
' We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue') 'We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue')
elif u'No space left on device' in result['stderr']: elif u'No space left on device' in result['stderr']:
output = result['stderr'] output = result['stderr']
else: else:
output = ('Authentication or permission failure.' output = ('Authentication or permission failure. '
' In some cases, you may have been able to authenticate and did not have permissions on the target directory.' 'In some cases, you may have been able to authenticate and did not have permissions on the target directory. '
' Consider changing the remote temp path in ansible.cfg to a path rooted in "/tmp".' 'Consider changing the remote temp path in ansible.cfg to a path rooted in "/tmp". '
' Failed command was: %s, exited with result %d' % (cmd, result['rc'])) 'Failed command was: %s, exited with result %d' % (cmd, result['rc']))
if 'stdout' in result and result['stdout'] != u'': if 'stdout' in result and result['stdout'] != u'':
output = output + u": %s" % result['stdout'] output = output + u": %s" % result['stdout']
raise AnsibleConnectionFailure(output) raise AnsibleConnectionFailure(output)
@ -309,8 +309,8 @@ class ActionBase(with_metaclass(ABCMeta, object)):
tmp_rm_data = self._parse_returned_data(tmp_rm_res) tmp_rm_data = self._parse_returned_data(tmp_rm_res)
if tmp_rm_data.get('rc', 0) != 0: if tmp_rm_data.get('rc', 0) != 0:
display.warning('Error deleting remote temporary files (rc: {0}, stderr: {1})'.format(tmp_rm_res.get('rc'), display.warning('Error deleting remote temporary files (rc: %s, stderr: %s})'
tmp_rm_res.get('stderr', 'No error string available.'))) % (tmp_rm_res.get('rc'), tmp_rm_res.get('stderr', 'No error string available.')))
def _transfer_file(self, local_path, remote_path): def _transfer_file(self, local_path, remote_path):
self._connection.put_file(local_path, remote_path) self._connection.put_file(local_path, remote_path)
@ -408,7 +408,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
setfacl_mode = 'r-x' setfacl_mode = 'r-x'
else: else:
chmod_mode = 'rX' chmod_mode = 'rX'
### Note: this form fails silently on freebsd. We currently # NOTE: this form fails silently on freebsd. We currently
# never call _fixup_perms2() with execute=False but if we # never call _fixup_perms2() with execute=False but if we
# start to we'll have to fix this. # start to we'll have to fix this.
setfacl_mode = 'r-X' setfacl_mode = 'r-X'
@ -426,22 +426,23 @@ class ActionBase(with_metaclass(ABCMeta, object)):
res = self._remote_chown(remote_paths, self._play_context.become_user) res = self._remote_chown(remote_paths, self._play_context.become_user)
if res['rc'] != 0 and remote_user == 'root': if res['rc'] != 0 and remote_user == 'root':
# chown failed even if remove_user is root # chown failed even if remove_user is root
raise AnsibleError('Failed to change ownership of the temporary files Ansible needs to create despite connecting as root.' raise AnsibleError('Failed to change ownership of the temporary files Ansible needs to create despite connecting as root. '
' Unprivileged become user would be unable to read the file.') 'Unprivileged become user would be unable to read the file.')
elif res['rc'] != 0: elif res['rc'] != 0:
if C.ALLOW_WORLD_READABLE_TMPFILES: if C.ALLOW_WORLD_READABLE_TMPFILES:
# chown and fs acls failed -- do things this insecure # chown and fs acls failed -- do things this insecure
# way only if the user opted in in the config file # way only if the user opted in in the config file
display.warning('Using world-readable permissions for temporary files Ansible needs to create when becoming an unprivileged user.' display.warning('Using world-readable permissions for temporary files Ansible needs to create when becoming an unprivileged user. '
' This may be insecure. For information on securing this, see' 'This may be insecure. For information on securing this, see '
' https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user') 'https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user')
res = self._remote_chmod(remote_paths, 'a+%s' % chmod_mode) res = self._remote_chmod(remote_paths, 'a+%s' % chmod_mode)
if res['rc'] != 0: if res['rc'] != 0:
raise AnsibleError('Failed to set file mode on remote files (rc: {0}, err: {1})'.format(res['rc'], to_native(res['stderr']))) raise AnsibleError('Failed to set file mode on remote files (rc: {0}, err: {1})'.format(res['rc'], to_native(res['stderr'])))
else: else:
raise AnsibleError('Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user' raise AnsibleError('Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user '
' (rc: {0}, err: {1}). For information on working around this,' '(rc: %s, err: %s}). For information on working around this, see '
' see https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user'.format(res['rc'], to_native(res['stderr']))) 'https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user'
% (res['rc'], to_native(res['stderr'])))
elif execute: elif execute:
# Can't depend on the file being transferred with execute permissions. # Can't depend on the file being transferred with execute permissions.
# Only need user perms because no become was used here # Only need user perms because no become was used here
@ -479,7 +480,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
''' '''
Get information from remote file. Get information from remote file.
''' '''
module_args=dict( module_args = dict(
path=path, path=path,
follow=follow, follow=follow,
get_md5=False, get_md5=False,
@ -534,7 +535,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
elif errormsg.endswith(u'MODULE FAILURE'): elif errormsg.endswith(u'MODULE FAILURE'):
x = "4" # python not found or module uncaught exception x = "4" # python not found or module uncaught exception
elif 'json' in errormsg or 'simplejson' in errormsg: elif 'json' in errormsg or 'simplejson' in errormsg:
x = "5" # json or simplejson modules needed x = "5" # json or simplejson modules needed
finally: finally:
return x return x
@ -611,8 +612,6 @@ class ActionBase(with_metaclass(ABCMeta, object)):
# give the module the socket for persistent connections # give the module the socket for persistent connections
module_args['_ansible_socket'] = task_vars.get('ansible_socket') module_args['_ansible_socket'] = task_vars.get('ansible_socket')
def _execute_module(self, module_name=None, module_args=None, tmp=None, task_vars=None, persist_files=False, delete_remote_tmp=True, wrap_async=False): def _execute_module(self, module_name=None, module_args=None, tmp=None, task_vars=None, persist_files=False, delete_remote_tmp=True, wrap_async=False):
''' '''
Transfer and run a module along with its arguments. Transfer and run a module along with its arguments.
@ -641,7 +640,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
if not self._is_pipelining_enabled(module_style, wrap_async): if not self._is_pipelining_enabled(module_style, wrap_async):
# we might need remote tmp dir # we might need remote tmp dir
if not tmp or not 'tmp' in tmp: if not tmp or 'tmp' not in tmp:
tmp = self._make_tmp_path() tmp = self._make_tmp_path()
remote_module_filename = self._connection._shell.get_remote_filename(module_path) remote_module_filename = self._connection._shell.get_remote_filename(module_path)
@ -661,7 +660,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
# we need to dump the module args to a k=v string in a file on # we need to dump the module args to a k=v string in a file on
# the remote system, which can be read and parsed by the module # the remote system, which can be read and parsed by the module
args_data = "" args_data = ""
for k,v in iteritems(module_args): for k, v in iteritems(module_args):
args_data += '%s=%s ' % (k, shlex_quote(text_type(v))) args_data += '%s=%s ' % (k, shlex_quote(text_type(v)))
self._transfer_data(args_file_path, args_data) self._transfer_data(args_file_path, args_data)
elif module_style in ('non_native_want_json', 'binary'): elif module_style in ('non_native_want_json', 'binary'):
@ -690,7 +689,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
remote_files.append(remote_async_module_path) remote_files.append(remote_async_module_path)
async_limit = self._task.async async_limit = self._task.async
async_jid = str(random.randint(0, 999999999999)) async_jid = str(random.randint(0, 999999999999))
# call the interpreter for async_wrapper directly # call the interpreter for async_wrapper directly
# this permits use of a script for an interpreter on non-Linux platforms # this permits use of a script for an interpreter on non-Linux platforms
@ -710,7 +709,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
if not self._should_remove_tmp_path(tmp): if not self._should_remove_tmp_path(tmp):
async_cmd.append("-preserve_tmp") async_cmd.append("-preserve_tmp")
cmd= " ".join(to_text(x) for x in async_cmd) cmd = " ".join(to_text(x) for x in async_cmd)
else: else:
@ -736,7 +735,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
# Fix permissions of the tmp path and tmp files. This should be called after all files have been transferred. # Fix permissions of the tmp path and tmp files. This should be called after all files have been transferred.
if remote_files: if remote_files:
# remove none/empty # remove none/empty
remote_files = [ x for x in remote_files if x] remote_files = [x for x in remote_files if x]
self._fixup_perms2(remote_files, self._play_context.remote_user) self._fixup_perms2(remote_files, self._play_context.remote_user)
# actually execute # actually execute
@ -745,7 +744,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
# parse the main result # parse the main result
data = self._parse_returned_data(res) data = self._parse_returned_data(res)
#NOTE: INTERNAL KEYS ONLY ACCESSIBLE HERE # NOTE: INTERNAL KEYS ONLY ACCESSIBLE HERE
# get internal info before cleaning # get internal info before cleaning
tmpdir_delete = (not data.pop("_ansible_suppress_tmpdir_delete", False) and wrap_async) tmpdir_delete = (not data.pop("_ansible_suppress_tmpdir_delete", False) and wrap_async)
@ -756,7 +755,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
if (self._play_context.become and self._play_context.become_user != 'root') and not persist_files and delete_remote_tmp or tmpdir_delete: if (self._play_context.become and self._play_context.become_user != 'root') and not persist_files and delete_remote_tmp or tmpdir_delete:
self._remove_tmp_path(tmp) self._remove_tmp_path(tmp)
#FIXME: for backwards compat, figure out if still makes sense # FIXME: for backwards compat, figure out if still makes sense
if wrap_async: if wrap_async:
data['changed'] = True data['changed'] = True
@ -784,7 +783,6 @@ class ActionBase(with_metaclass(ABCMeta, object)):
if key in data and not data[key]: if key in data and not data[key]:
del data[key] del data[key]
def _clean_returned_data(self, data): def _clean_returned_data(self, data):
remove_keys = set() remove_keys = set()
fact_keys = set(data.keys()) fact_keys = set(data.keys())

View file

@ -22,7 +22,6 @@ __metaclass__ = type
from ansible.plugins.action import ActionBase from ansible.plugins.action import ActionBase
from ansible.plugins.action.net_config import ActionModule as NetActionModule from ansible.plugins.action.net_config import ActionModule as NetActionModule
class ActionModule(NetActionModule, ActionBase): class ActionModule(NetActionModule, ActionBase):
pass pass

View file

@ -22,5 +22,6 @@ __metaclass__ = type
from ansible.plugins.action import ActionBase from ansible.plugins.action import ActionBase
from ansible.plugins.action.net_template import ActionModule as NetActionModule from ansible.plugins.action.net_template import ActionModule as NetActionModule
class ActionModule(NetActionModule, ActionBase): class ActionModule(NetActionModule, ActionBase):
pass pass

View file

@ -87,14 +87,14 @@ class ActionModule(ActionBase):
if task_vars is None: if task_vars is None:
task_vars = dict() task_vars = dict()
src = self._task.args.get('src', None) src = self._task.args.get('src', None)
dest = self._task.args.get('dest', None) dest = self._task.args.get('dest', None)
delimiter = self._task.args.get('delimiter', None) delimiter = self._task.args.get('delimiter', None)
remote_src = self._task.args.get('remote_src', 'yes') remote_src = self._task.args.get('remote_src', 'yes')
regexp = self._task.args.get('regexp', None) regexp = self._task.args.get('regexp', None)
follow = self._task.args.get('follow', False) follow = self._task.args.get('follow', False)
ignore_hidden = self._task.args.get('ignore_hidden', False) ignore_hidden = self._task.args.get('ignore_hidden', False)
decrypt = self._task.args.get('decrypt', True) decrypt = self._task.args.get('decrypt', True)
if src is None or dest is None: if src is None or dest is None:
result['failed'] = True result['failed'] = True
@ -159,7 +159,7 @@ class ActionModule(ActionBase):
# fix file permissions when the copy is done as a different user # fix file permissions when the copy is done as a different user
self._fixup_perms2((tmp, remote_path)) self._fixup_perms2((tmp, remote_path))
new_module_args.update( dict( src=xfered,)) new_module_args.update(dict(src=xfered,))
res = self._execute_module(module_name='copy', module_args=new_module_args, task_vars=task_vars, tmp=tmp, delete_remote_tmp=False) res = self._execute_module(module_name='copy', module_args=new_module_args, task_vars=task_vars, tmp=tmp, delete_remote_tmp=False)
if diff: if diff:

View file

@ -40,13 +40,13 @@ class ActionModule(ActionBase):
result = super(ActionModule, self).run(tmp, task_vars) result = super(ActionModule, self).run(tmp, task_vars)
source = self._task.args.get('src', None) source = self._task.args.get('src', None)
content = self._task.args.get('content', None) content = self._task.args.get('content', None)
dest = self._task.args.get('dest', None) dest = self._task.args.get('dest', None)
raw = boolean(self._task.args.get('raw', 'no')) raw = boolean(self._task.args.get('raw', 'no'))
force = boolean(self._task.args.get('force', 'yes')) force = boolean(self._task.args.get('force', 'yes'))
remote_src = boolean(self._task.args.get('remote_src', False)) remote_src = boolean(self._task.args.get('remote_src', False))
follow = boolean(self._task.args.get('follow', False)) follow = boolean(self._task.args.get('follow', False))
decrypt = boolean(self._task.args.get('decrypt', True)) decrypt = boolean(self._task.args.get('decrypt', True))
result['failed'] = True result['failed'] = True
@ -256,8 +256,8 @@ class ActionModule(ActionBase):
del new_module_args[key] del new_module_args[key]
module_return = self._execute_module(module_name='copy', module_return = self._execute_module(module_name='copy',
module_args=new_module_args, task_vars=task_vars, module_args=new_module_args, task_vars=task_vars,
tmp=tmp, delete_remote_tmp=delete_remote_tmp) tmp=tmp, delete_remote_tmp=delete_remote_tmp)
module_executed = True module_executed = True
else: else:
@ -291,8 +291,8 @@ class ActionModule(ActionBase):
# Execute the file module. # Execute the file module.
module_return = self._execute_module(module_name='file', module_return = self._execute_module(module_name='file',
module_args=new_module_args, task_vars=task_vars, module_args=new_module_args, task_vars=task_vars,
tmp=tmp, delete_remote_tmp=delete_remote_tmp) tmp=tmp, delete_remote_tmp=delete_remote_tmp)
module_executed = True module_executed = True
if not module_return.get('checksum'): if not module_return.get('checksum'):

View file

@ -27,6 +27,7 @@ import urlparse
from ansible.module_utils._text import to_text from ansible.module_utils._text import to_text
from ansible.plugins.action.eos import ActionModule as _ActionModule from ansible.plugins.action.eos import ActionModule as _ActionModule
class ActionModule(_ActionModule): class ActionModule(_ActionModule):
def run(self, tmp=None, task_vars=None): def run(self, tmp=None, task_vars=None):

View file

@ -42,10 +42,10 @@ class ActionModule(ActionBase):
result['msg'] = 'check mode not (yet) supported for this module' result['msg'] = 'check mode not (yet) supported for this module'
return result return result
source = self._task.args.get('src', None) source = self._task.args.get('src', None)
dest = self._task.args.get('dest', None) dest = self._task.args.get('dest', None)
flat = boolean(self._task.args.get('flat')) flat = boolean(self._task.args.get('flat'))
fail_on_missing = boolean(self._task.args.get('fail_on_missing')) fail_on_missing = boolean(self._task.args.get('fail_on_missing'))
validate_checksum = boolean(self._task.args.get('validate_checksum', self._task.args.get('validate_md5', True))) validate_checksum = boolean(self._task.args.get('validate_checksum', self._task.args.get('validate_md5', True)))
# validate_md5 is the deprecated way to specify validate_checksum # validate_md5 is the deprecated way to specify validate_checksum
@ -120,7 +120,7 @@ class ActionModule(ActionBase):
target_name = self._play_context.remote_addr target_name = self._play_context.remote_addr
dest = "%s/%s/%s" % (self._loader.path_dwim(dest), target_name, source_local) dest = "%s/%s/%s" % (self._loader.path_dwim(dest), target_name, source_local)
dest = dest.replace("//","/") dest = dest.replace("//", "/")
if remote_checksum in ('0', '1', '2', '3', '4', '5'): if remote_checksum in ('0', '1', '2', '3', '4', '5'):
result['changed'] = False result['changed'] = False
@ -175,8 +175,8 @@ class ActionModule(ActionBase):
if validate_checksum and new_checksum != remote_checksum: if validate_checksum and new_checksum != remote_checksum:
result.update(dict(failed=True, md5sum=new_md5, result.update(dict(failed=True, md5sum=new_md5,
msg="checksum mismatch", file=source, dest=dest, remote_md5sum=None, msg="checksum mismatch", file=source, dest=dest, remote_md5sum=None,
checksum=new_checksum, remote_checksum=remote_checksum)) checksum=new_checksum, remote_checksum=remote_checksum))
else: else:
result.update({'changed': True, 'md5sum': new_md5, 'dest': dest, result.update({'changed': True, 'md5sum': new_md5, 'dest': dest,
'remote_md5sum': None, 'checksum': new_checksum, 'remote_md5sum': None, 'checksum': new_checksum,

View file

@ -23,7 +23,7 @@ from ansible.plugins.action import ActionBase
class ActionModule(ActionBase): class ActionModule(ActionBase):
''' Create inventory groups based on variables ''' ''' Create inventory groups based on variables '''
### We need to be able to modify the inventory # We need to be able to modify the inventory
TRANSFERS_FILES = False TRANSFERS_FILES = False
def run(self, tmp=None, task_vars=None): def run(self, tmp=None, task_vars=None):
@ -38,7 +38,7 @@ class ActionModule(ActionBase):
return result return result
group_name = self._task.args.get('key') group_name = self._task.args.get('key')
group_name = group_name.replace(' ','-') group_name = group_name.replace(' ', '-')
result['changed'] = False result['changed'] = False
result['add_group'] = group_name result['add_group'] = group_name

View file

@ -27,6 +27,7 @@ import urlparse
from ansible.module_utils._text import to_text from ansible.module_utils._text import to_text
from ansible.plugins.action.ios import ActionModule as _ActionModule from ansible.plugins.action.ios import ActionModule as _ActionModule
class ActionModule(_ActionModule): class ActionModule(_ActionModule):
def run(self, tmp=None, task_vars=None): def run(self, tmp=None, task_vars=None):

View file

@ -27,6 +27,7 @@ import urlparse
from ansible.module_utils._text import to_text from ansible.module_utils._text import to_text
from ansible.plugins.action.iosxr import ActionModule as _ActionModule from ansible.plugins.action.iosxr import ActionModule as _ActionModule
class ActionModule(_ActionModule): class ActionModule(_ActionModule):
def run(self, tmp=None, task_vars=None): def run(self, tmp=None, task_vars=None):
@ -100,4 +101,3 @@ class ActionModule(_ActionModule):
searchpath.append(os.path.dirname(source)) searchpath.append(os.path.dirname(source))
self._templar.environment.loader.searchpath = searchpath self._templar.environment.loader.searchpath = searchpath
self._task.args['src'] = self._templar.template(template_data) self._task.args['src'] = self._templar.template(template_data)

View file

@ -112,7 +112,7 @@ class ActionModule(_ActionModule):
path = unfrackpath("$HOME/.ansible/pc") path = unfrackpath("$HOME/.ansible/pc")
# use play_context.connection instea of play_context.port to avoid # use play_context.connection instea of play_context.port to avoid
# collision if netconf is listening on port 22 # collision if netconf is listening on port 22
#cp = ssh._create_control_path(play_context.remote_addr, play_context.connection, play_context.remote_user) # cp = ssh._create_control_path(play_context.remote_addr, play_context.connection, play_context.remote_user)
cp = ssh._create_control_path(play_context.remote_addr, play_context.port, play_context.remote_user) cp = ssh._create_control_path(play_context.remote_addr, play_context.port, play_context.remote_user)
return cp % dict(directory=path) return cp % dict(directory=path)

View file

@ -27,6 +27,7 @@ import urlparse
from ansible.module_utils._text import to_text from ansible.module_utils._text import to_text
from ansible.plugins.action.junos import ActionModule as _ActionModule from ansible.plugins.action.junos import ActionModule as _ActionModule
class ActionModule(_ActionModule): class ActionModule(_ActionModule):
def run(self, tmp=None, task_vars=None): def run(self, tmp=None, task_vars=None):

View file

@ -27,7 +27,7 @@ class ActionModule(ActionBase):
# individual modules might disagree but as the generic the action plugin, pass at this point. # individual modules might disagree but as the generic the action plugin, pass at this point.
self._supports_check_mode = True self._supports_check_mode = True
self._supports_async = True self._supports_async = True
results = super(ActionModule, self).run(tmp, task_vars) results = super(ActionModule, self).run(tmp, task_vars)

View file

@ -27,6 +27,7 @@ import urlparse
from ansible.module_utils._text import to_text from ansible.module_utils._text import to_text
from ansible.plugins.action.nxos import ActionModule as _ActionModule from ansible.plugins.action.nxos import ActionModule as _ActionModule
class ActionModule(_ActionModule): class ActionModule(_ActionModule):
def run(self, tmp=None, task_vars=None): def run(self, tmp=None, task_vars=None):

View file

@ -22,7 +22,6 @@ __metaclass__ = type
from ansible.plugins.action import ActionBase from ansible.plugins.action import ActionBase
from ansible.plugins.action.net_config import ActionModule as NetActionModule from ansible.plugins.action.net_config import ActionModule as NetActionModule
class ActionModule(NetActionModule, ActionBase): class ActionModule(NetActionModule, ActionBase):
pass pass

View file

@ -38,7 +38,7 @@ class ActionModule(NetActionModule, ActionBase):
self._handle_template() self._handle_template()
result.update(self._execute_module(module_name=self._task.action, result.update(self._execute_module(module_name=self._task.action,
module_args=self._task.args, task_vars=task_vars)) module_args=self._task.args, task_vars=task_vars))
if self._task.args.get('backup') and result.get('_backup'): if self._task.args.get('backup') and result.get('_backup'):
contents = json.dumps(result['_backup'], indent=4) contents = json.dumps(result['_backup'], indent=4)
@ -48,5 +48,3 @@ class ActionModule(NetActionModule, ActionBase):
del result['_backup'] del result['_backup']
return result return result

View file

@ -34,7 +34,7 @@ class ActionModule(ActionBase):
''' handler for package operations ''' ''' handler for package operations '''
self._supports_check_mode = True self._supports_check_mode = True
self._supports_async = True self._supports_async = True
result = super(ActionModule, self).run(tmp, task_vars) result = super(ActionModule, self).run(tmp, task_vars)
@ -42,12 +42,12 @@ class ActionModule(ActionBase):
if module == 'auto': if module == 'auto':
try: try:
if self._task.delegate_to: # if we delegate, we should use delegated host's facts if self._task.delegate_to: # if we delegate, we should use delegated host's facts
module = self._templar.template("{{hostvars['%s']['ansible_facts']['ansible_pkg_mgr']}}" % self._task.delegate_to) module = self._templar.template("{{hostvars['%s']['ansible_facts']['ansible_pkg_mgr']}}" % self._task.delegate_to)
else: else:
module = self._templar.template('{{ansible_facts["ansible_pkg_mgr"]}}') module = self._templar.template('{{ansible_facts["ansible_pkg_mgr"]}}')
except: except:
pass # could not get it from template! pass # could not get it from template!
if module == 'auto': if module == 'auto':
facts = self._execute_module(module_name='setup', module_args=dict(filter='ansible_pkg_mgr', gather_subset='!all'), task_vars=task_vars) facts = self._execute_module(module_name='setup', module_args=dict(filter='ansible_pkg_mgr', gather_subset='!all'), task_vars=task_vars)

View file

@ -34,7 +34,7 @@ class ActionModule(ActionBase):
result = super(ActionModule, self).run(tmp, task_vars) result = super(ActionModule, self).run(tmp, task_vars)
src = self._task.args.get('src', None) src = self._task.args.get('src', None)
remote_src = boolean(self._task.args.get('remote_src', 'no')) remote_src = boolean(self._task.args.get('remote_src', 'no'))
if src is None: if src is None:
@ -61,7 +61,7 @@ class ActionModule(ActionBase):
tmp_src = self._connection._shell.join_path(tmp, os.path.basename(src)) tmp_src = self._connection._shell.join_path(tmp, os.path.basename(src))
self._transfer_file(src, tmp_src) self._transfer_file(src, tmp_src)
self._fixup_perms2((tmp, tmp_src) ) self._fixup_perms2((tmp, tmp_src))
new_module_args = self._task.args.copy() new_module_args = self._task.args.copy()
new_module_args.update( new_module_args.update(

View file

@ -59,13 +59,13 @@ class ActionModule(ActionBase):
prompt = None prompt = None
seconds = None seconds = None
result.update(dict( result.update(dict(
changed = False, changed=False,
rc = 0, rc=0,
stderr = '', stderr='',
stdout = '', stdout='',
start = None, start=None,
stop = None, stop=None,
delta = None, delta=None,
)) ))
# Is 'args' empty, then this is the default prompted pause # Is 'args' empty, then this is the default prompted pause
@ -163,7 +163,6 @@ class ActionModule(ActionBase):
else: else:
raise AnsibleError('user requested abort!') raise AnsibleError('user requested abort!')
except AnsibleTimeoutExceeded: except AnsibleTimeoutExceeded:
# this is the exception we expect when the alarm signal # this is the exception we expect when the alarm signal
# fires, so we simply ignore it to move into the cleanup # fires, so we simply ignore it to move into the cleanup

View file

@ -59,9 +59,9 @@ class ActionModule(ActionBase):
# out now so we know the file name we need to transfer to the remote, # out now so we know the file name we need to transfer to the remote,
# and everything else is an argument to the script which we need later # and everything else is an argument to the script which we need later
# to append to the remote command # to append to the remote command
parts = self._task.args.get('_raw_params', '').strip().split() parts = self._task.args.get('_raw_params', '').strip().split()
source = parts[0] source = parts[0]
args = ' '.join(parts[1:]) args = ' '.join(parts[1:])
try: try:
source = self._loader.get_real_file(self._find_needle('files', source), decrypt=self._task.args.get('decrypt', True)) source = self._loader.get_real_file(self._find_needle('files', source), decrypt=self._task.args.get('decrypt', True))

View file

@ -33,7 +33,7 @@ class ActionModule(ActionBase):
''' handler for package operations ''' ''' handler for package operations '''
self._supports_check_mode = True self._supports_check_mode = True
self._supports_async = True self._supports_async = True
result = super(ActionModule, self).run(tmp, task_vars) result = super(ActionModule, self).run(tmp, task_vars)
@ -41,12 +41,12 @@ class ActionModule(ActionBase):
if module == 'auto': if module == 'auto':
try: try:
if self._task.delegate_to: # if we delegate, we should use delegated host's facts if self._task.delegate_to: # if we delegate, we should use delegated host's facts
module = self._templar.template("{{hostvars['%s']['ansible_facts']['ansible_service_mgr']}}" % self._task.delegate_to) module = self._templar.template("{{hostvars['%s']['ansible_facts']['ansible_service_mgr']}}" % self._task.delegate_to)
else: else:
module = self._templar.template('{{ansible_facts["ansible_service_mgr"]}}') module = self._templar.template('{{ansible_facts["ansible_service_mgr"]}}')
except: except:
pass # could not get it from template! pass # could not get it from template!
if module == 'auto': if module == 'auto':
facts = self._execute_module(module_name='setup', module_args=dict(gather_subset='!all', filter='ansible_service_mgr'), task_vars=task_vars) facts = self._execute_module(module_name='setup', module_args=dict(gather_subset='!all', filter='ansible_service_mgr'), task_vars=task_vars)

Some files were not shown because too many files have changed in this diff Show more