mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-22 21:00:22 -07:00
parent
2f33c1a1a1
commit
5553b20828
206 changed files with 1853 additions and 1870 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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'))
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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'):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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'),
|
||||||
)
|
)
|
||||||
|
|
|
@ -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 )
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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]:
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 = {}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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']
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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):
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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']
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -76,4 +76,3 @@ class TaskInclude(Task):
|
||||||
del all_vars['when']
|
del all_vars['when']
|
||||||
|
|
||||||
return all_vars
|
return all_vars
|
||||||
|
|
||||||
|
|
|
@ -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',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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'):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue