mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-05-08 06:12:51 +00:00
committed by
John R Barker
parent
2f33c1a1a1
commit
5553b20828
@@ -62,11 +62,11 @@ class PluginLoader:
|
||||
|
||||
def __init__(self, class_name, package, config, subdir, aliases={}, required_base_class=None):
|
||||
|
||||
self.class_name = class_name
|
||||
self.base_class = required_base_class
|
||||
self.package = package
|
||||
self.subdir = subdir
|
||||
self.aliases = aliases
|
||||
self.class_name = class_name
|
||||
self.base_class = required_base_class
|
||||
self.package = package
|
||||
self.subdir = subdir
|
||||
self.aliases = aliases
|
||||
|
||||
if config and not isinstance(config, list):
|
||||
config = [config]
|
||||
@@ -82,8 +82,8 @@ class PluginLoader:
|
||||
if class_name not in PLUGIN_PATH_CACHE:
|
||||
PLUGIN_PATH_CACHE[class_name] = defaultdict(dict)
|
||||
|
||||
self._module_cache = MODULE_CACHE[class_name]
|
||||
self._paths = PATH_CACHE[class_name]
|
||||
self._module_cache = MODULE_CACHE[class_name]
|
||||
self._paths = PATH_CACHE[class_name]
|
||||
self._plugin_path_cache = PLUGIN_PATH_CACHE[class_name]
|
||||
|
||||
self._extra_dirs = []
|
||||
@@ -95,10 +95,10 @@ class PluginLoader:
|
||||
'''
|
||||
|
||||
class_name = data.get('class_name')
|
||||
package = data.get('package')
|
||||
config = data.get('config')
|
||||
subdir = data.get('subdir')
|
||||
aliases = data.get('aliases')
|
||||
package = data.get('package')
|
||||
config = data.get('config')
|
||||
subdir = data.get('subdir')
|
||||
aliases = data.get('aliases')
|
||||
base_class = data.get('base_class')
|
||||
|
||||
PATH_CACHE[class_name] = data.get('PATH_CACHE')
|
||||
@@ -114,16 +114,16 @@ class PluginLoader:
|
||||
'''
|
||||
|
||||
return dict(
|
||||
class_name = self.class_name,
|
||||
base_class = self.base_class,
|
||||
package = self.package,
|
||||
config = self.config,
|
||||
subdir = self.subdir,
|
||||
aliases = self.aliases,
|
||||
_extra_dirs = self._extra_dirs,
|
||||
_searched_paths = self._searched_paths,
|
||||
PATH_CACHE = PATH_CACHE[self.class_name],
|
||||
PLUGIN_PATH_CACHE = PLUGIN_PATH_CACHE[self.class_name],
|
||||
class_name=self.class_name,
|
||||
base_class=self.base_class,
|
||||
package=self.package,
|
||||
config=self.config,
|
||||
subdir=self.subdir,
|
||||
aliases=self.aliases,
|
||||
_extra_dirs=self._extra_dirs,
|
||||
_searched_paths=self._searched_paths,
|
||||
PATH_CACHE=PATH_CACHE[self.class_name],
|
||||
PLUGIN_PATH_CACHE=PLUGIN_PATH_CACHE[self.class_name],
|
||||
)
|
||||
|
||||
def format_paths(self, paths):
|
||||
@@ -145,7 +145,7 @@ class PluginLoader:
|
||||
for root, subdirs, files in os.walk(dir, followlinks=True):
|
||||
if '__init__.py' in files:
|
||||
for x in subdirs:
|
||||
results.append(os.path.join(root,x))
|
||||
results.append(os.path.join(root, x))
|
||||
return results
|
||||
|
||||
def _get_package_paths(self, subdirs=True):
|
||||
@@ -271,7 +271,7 @@ class PluginLoader:
|
||||
|
||||
# HACK: We have no way of executing python byte
|
||||
# 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
|
||||
# bew valid
|
||||
if full_path.endswith(('.pyc', '.pyo')):
|
||||
@@ -313,10 +313,10 @@ class PluginLoader:
|
||||
if alias_name in pull_cache:
|
||||
if not ignore_deprecated and not os.path.islink(pull_cache[alias_name]):
|
||||
display.deprecated('%s is kept for backwards compatibility '
|
||||
'but usage is discouraged. The module '
|
||||
'documentation details page may explain '
|
||||
'more about this rationale.' %
|
||||
name.lstrip('_'))
|
||||
'but usage is discouraged. The module '
|
||||
'documentation details page may explain '
|
||||
'more about this rationale.' %
|
||||
name.lstrip('_'))
|
||||
return pull_cache[alias_name]
|
||||
|
||||
return None
|
||||
@@ -550,4 +550,3 @@ vars_loader = PluginLoader(
|
||||
C.DEFAULT_VARS_PLUGIN_PATH,
|
||||
'vars_plugins',
|
||||
)
|
||||
|
||||
|
||||
@@ -59,18 +59,18 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||
'''
|
||||
|
||||
def __init__(self, task, connection, play_context, loader, templar, shared_loader_obj):
|
||||
self._task = task
|
||||
self._connection = connection
|
||||
self._play_context = play_context
|
||||
self._loader = loader
|
||||
self._templar = templar
|
||||
self._task = task
|
||||
self._connection = connection
|
||||
self._play_context = play_context
|
||||
self._loader = loader
|
||||
self._templar = templar
|
||||
self._shared_loader_obj = shared_loader_obj
|
||||
# Backwards compat: self._display isn't really needed, just import the global display and use that.
|
||||
self._display = display
|
||||
self._cleanup_remote_tmp = False
|
||||
self._display = display
|
||||
self._cleanup_remote_tmp = False
|
||||
|
||||
self._supports_check_mode = True
|
||||
self._supports_async = False
|
||||
self._supports_async = False
|
||||
|
||||
@abstractmethod
|
||||
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
|
||||
(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...
|
||||
if self._connection.transport == "winrm":
|
||||
@@ -162,9 +162,9 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||
final_environment = dict()
|
||||
self._compute_environment_string(final_environment)
|
||||
module_data = build_windows_module_payload(module_name=module_name, module_path=module_path,
|
||||
b_module_data=module_data, module_args=module_args,
|
||||
task_vars=task_vars, task=self._task,
|
||||
play_context=self._play_context, environment=final_environment)
|
||||
b_module_data=module_data, module_args=module_args,
|
||||
task_vars=task_vars, task=self._task,
|
||||
play_context=self._play_context, environment=final_environment)
|
||||
|
||||
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:
|
||||
environments = self._task.environment
|
||||
if not isinstance(environments, list):
|
||||
environments = [ environments ]
|
||||
environments = [environments]
|
||||
|
||||
# the environments as inherited need to be reversed, to make
|
||||
# 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
|
||||
'''
|
||||
if self._connection.always_pipeline_modules:
|
||||
return True #eg, winrm
|
||||
return True # eg, winrm
|
||||
|
||||
# any of these require a true
|
||||
for condition in [
|
||||
@@ -249,7 +249,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||
if use_system_tmp:
|
||||
tmpdir = None
|
||||
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)
|
||||
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:
|
||||
output = u'SSH encountered an unknown error. The output was:\n%s%s' % (result['stdout'], result['stderr'])
|
||||
else:
|
||||
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')
|
||||
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')
|
||||
|
||||
elif u'No space left on device' in result['stderr']:
|
||||
output = result['stderr']
|
||||
else:
|
||||
output = ('Authentication or permission failure.'
|
||||
' 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".'
|
||||
' Failed command was: %s, exited with result %d' % (cmd, result['rc']))
|
||||
output = ('Authentication or permission failure. '
|
||||
'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". '
|
||||
'Failed command was: %s, exited with result %d' % (cmd, result['rc']))
|
||||
if 'stdout' in result and result['stdout'] != u'':
|
||||
output = output + u": %s" % result['stdout']
|
||||
raise AnsibleConnectionFailure(output)
|
||||
@@ -309,8 +309,8 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||
|
||||
tmp_rm_data = self._parse_returned_data(tmp_rm_res)
|
||||
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'),
|
||||
tmp_rm_res.get('stderr', 'No error string available.')))
|
||||
display.warning('Error deleting remote temporary files (rc: %s, stderr: %s})'
|
||||
% (tmp_rm_res.get('rc'), tmp_rm_res.get('stderr', 'No error string available.')))
|
||||
|
||||
def _transfer_file(self, 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'
|
||||
else:
|
||||
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
|
||||
# start to we'll have to fix this.
|
||||
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)
|
||||
if res['rc'] != 0 and remote_user == '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.'
|
||||
' Unprivileged become user would be unable to read the file.')
|
||||
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.')
|
||||
elif res['rc'] != 0:
|
||||
if C.ALLOW_WORLD_READABLE_TMPFILES:
|
||||
# chown and fs acls failed -- do things this insecure
|
||||
# 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.'
|
||||
' This may be insecure. For information on securing this, see'
|
||||
' https://docs.ansible.com/ansible/become.html#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 '
|
||||
'https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user')
|
||||
res = self._remote_chmod(remote_paths, 'a+%s' % chmod_mode)
|
||||
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'])))
|
||||
else:
|
||||
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,'
|
||||
' see https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user'.format(res['rc'], to_native(res['stderr'])))
|
||||
raise AnsibleError('Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user '
|
||||
'(rc: %s, err: %s}). For information on working around this, see '
|
||||
'https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user'
|
||||
% (res['rc'], to_native(res['stderr'])))
|
||||
elif execute:
|
||||
# Can't depend on the file being transferred with execute permissions.
|
||||
# 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.
|
||||
'''
|
||||
module_args=dict(
|
||||
module_args = dict(
|
||||
path=path,
|
||||
follow=follow,
|
||||
get_md5=False,
|
||||
@@ -534,7 +535,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||
elif errormsg.endswith(u'MODULE FAILURE'):
|
||||
x = "4" # python not found or module uncaught exception
|
||||
elif 'json' in errormsg or 'simplejson' in errormsg:
|
||||
x = "5" # json or simplejson modules needed
|
||||
x = "5" # json or simplejson modules needed
|
||||
finally:
|
||||
return x
|
||||
|
||||
@@ -611,8 +612,6 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||
# give the module the socket for persistent connections
|
||||
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):
|
||||
'''
|
||||
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):
|
||||
|
||||
# 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()
|
||||
|
||||
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
|
||||
# the remote system, which can be read and parsed by the module
|
||||
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)))
|
||||
self._transfer_data(args_file_path, args_data)
|
||||
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)
|
||||
|
||||
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
|
||||
# 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):
|
||||
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:
|
||||
|
||||
@@ -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.
|
||||
if remote_files:
|
||||
# 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)
|
||||
|
||||
# actually execute
|
||||
@@ -745,7 +744,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||
# parse the main result
|
||||
data = self._parse_returned_data(res)
|
||||
|
||||
#NOTE: INTERNAL KEYS ONLY ACCESSIBLE HERE
|
||||
# NOTE: INTERNAL KEYS ONLY ACCESSIBLE HERE
|
||||
# get internal info before cleaning
|
||||
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:
|
||||
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:
|
||||
data['changed'] = True
|
||||
|
||||
@@ -784,7 +783,6 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||
if key in data and not data[key]:
|
||||
del data[key]
|
||||
|
||||
|
||||
def _clean_returned_data(self, data):
|
||||
remove_keys = set()
|
||||
fact_keys = set(data.keys())
|
||||
|
||||
@@ -22,7 +22,6 @@ __metaclass__ = type
|
||||
from ansible.plugins.action import ActionBase
|
||||
from ansible.plugins.action.net_config import ActionModule as NetActionModule
|
||||
|
||||
|
||||
class ActionModule(NetActionModule, ActionBase):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -22,5 +22,6 @@ __metaclass__ = type
|
||||
from ansible.plugins.action import ActionBase
|
||||
from ansible.plugins.action.net_template import ActionModule as NetActionModule
|
||||
|
||||
|
||||
class ActionModule(NetActionModule, ActionBase):
|
||||
pass
|
||||
|
||||
@@ -87,14 +87,14 @@ class ActionModule(ActionBase):
|
||||
if task_vars is None:
|
||||
task_vars = dict()
|
||||
|
||||
src = self._task.args.get('src', None)
|
||||
dest = self._task.args.get('dest', None)
|
||||
delimiter = self._task.args.get('delimiter', None)
|
||||
src = self._task.args.get('src', None)
|
||||
dest = self._task.args.get('dest', None)
|
||||
delimiter = self._task.args.get('delimiter', None)
|
||||
remote_src = self._task.args.get('remote_src', 'yes')
|
||||
regexp = self._task.args.get('regexp', None)
|
||||
follow = self._task.args.get('follow', False)
|
||||
regexp = self._task.args.get('regexp', None)
|
||||
follow = self._task.args.get('follow', 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:
|
||||
result['failed'] = True
|
||||
@@ -159,7 +159,7 @@ class ActionModule(ActionBase):
|
||||
# fix file permissions when the copy is done as a different user
|
||||
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)
|
||||
if diff:
|
||||
|
||||
@@ -40,13 +40,13 @@ class ActionModule(ActionBase):
|
||||
|
||||
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)
|
||||
dest = self._task.args.get('dest', None)
|
||||
raw = boolean(self._task.args.get('raw', 'no'))
|
||||
force = boolean(self._task.args.get('force', 'yes'))
|
||||
dest = self._task.args.get('dest', None)
|
||||
raw = boolean(self._task.args.get('raw', 'no'))
|
||||
force = boolean(self._task.args.get('force', 'yes'))
|
||||
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))
|
||||
|
||||
result['failed'] = True
|
||||
@@ -256,8 +256,8 @@ class ActionModule(ActionBase):
|
||||
del new_module_args[key]
|
||||
|
||||
module_return = self._execute_module(module_name='copy',
|
||||
module_args=new_module_args, task_vars=task_vars,
|
||||
tmp=tmp, delete_remote_tmp=delete_remote_tmp)
|
||||
module_args=new_module_args, task_vars=task_vars,
|
||||
tmp=tmp, delete_remote_tmp=delete_remote_tmp)
|
||||
module_executed = True
|
||||
|
||||
else:
|
||||
@@ -291,8 +291,8 @@ class ActionModule(ActionBase):
|
||||
|
||||
# Execute the file module.
|
||||
module_return = self._execute_module(module_name='file',
|
||||
module_args=new_module_args, task_vars=task_vars,
|
||||
tmp=tmp, delete_remote_tmp=delete_remote_tmp)
|
||||
module_args=new_module_args, task_vars=task_vars,
|
||||
tmp=tmp, delete_remote_tmp=delete_remote_tmp)
|
||||
module_executed = True
|
||||
|
||||
if not module_return.get('checksum'):
|
||||
|
||||
@@ -27,6 +27,7 @@ import urlparse
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.plugins.action.eos import ActionModule as _ActionModule
|
||||
|
||||
|
||||
class ActionModule(_ActionModule):
|
||||
|
||||
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'
|
||||
return result
|
||||
|
||||
source = self._task.args.get('src', None)
|
||||
dest = self._task.args.get('dest', None)
|
||||
flat = boolean(self._task.args.get('flat'))
|
||||
fail_on_missing = boolean(self._task.args.get('fail_on_missing'))
|
||||
source = self._task.args.get('src', None)
|
||||
dest = self._task.args.get('dest', None)
|
||||
flat = boolean(self._task.args.get('flat'))
|
||||
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_md5 is the deprecated way to specify validate_checksum
|
||||
@@ -120,7 +120,7 @@ class ActionModule(ActionBase):
|
||||
target_name = self._play_context.remote_addr
|
||||
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'):
|
||||
result['changed'] = False
|
||||
@@ -175,8 +175,8 @@ class ActionModule(ActionBase):
|
||||
|
||||
if validate_checksum and new_checksum != remote_checksum:
|
||||
result.update(dict(failed=True, md5sum=new_md5,
|
||||
msg="checksum mismatch", file=source, dest=dest, remote_md5sum=None,
|
||||
checksum=new_checksum, remote_checksum=remote_checksum))
|
||||
msg="checksum mismatch", file=source, dest=dest, remote_md5sum=None,
|
||||
checksum=new_checksum, remote_checksum=remote_checksum))
|
||||
else:
|
||||
result.update({'changed': True, 'md5sum': new_md5, 'dest': dest,
|
||||
'remote_md5sum': None, 'checksum': new_checksum,
|
||||
|
||||
@@ -23,7 +23,7 @@ from ansible.plugins.action import ActionBase
|
||||
class ActionModule(ActionBase):
|
||||
''' 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
|
||||
|
||||
def run(self, tmp=None, task_vars=None):
|
||||
@@ -38,7 +38,7 @@ class ActionModule(ActionBase):
|
||||
return result
|
||||
|
||||
group_name = self._task.args.get('key')
|
||||
group_name = group_name.replace(' ','-')
|
||||
group_name = group_name.replace(' ', '-')
|
||||
|
||||
result['changed'] = False
|
||||
result['add_group'] = group_name
|
||||
|
||||
@@ -27,6 +27,7 @@ import urlparse
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.plugins.action.ios import ActionModule as _ActionModule
|
||||
|
||||
|
||||
class ActionModule(_ActionModule):
|
||||
|
||||
def run(self, tmp=None, task_vars=None):
|
||||
|
||||
@@ -27,6 +27,7 @@ import urlparse
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.plugins.action.iosxr import ActionModule as _ActionModule
|
||||
|
||||
|
||||
class ActionModule(_ActionModule):
|
||||
|
||||
def run(self, tmp=None, task_vars=None):
|
||||
@@ -100,4 +101,3 @@ class ActionModule(_ActionModule):
|
||||
searchpath.append(os.path.dirname(source))
|
||||
self._templar.environment.loader.searchpath = searchpath
|
||||
self._task.args['src'] = self._templar.template(template_data)
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ class ActionModule(_ActionModule):
|
||||
path = unfrackpath("$HOME/.ansible/pc")
|
||||
# use play_context.connection instea of play_context.port to avoid
|
||||
# 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)
|
||||
return cp % dict(directory=path)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import urlparse
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.plugins.action.junos import ActionModule as _ActionModule
|
||||
|
||||
|
||||
class ActionModule(_ActionModule):
|
||||
|
||||
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.
|
||||
self._supports_check_mode = True
|
||||
self._supports_async = True
|
||||
self._supports_async = True
|
||||
|
||||
results = super(ActionModule, self).run(tmp, task_vars)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import urlparse
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.plugins.action.nxos import ActionModule as _ActionModule
|
||||
|
||||
|
||||
class ActionModule(_ActionModule):
|
||||
|
||||
def run(self, tmp=None, task_vars=None):
|
||||
|
||||
@@ -22,7 +22,6 @@ __metaclass__ = type
|
||||
from ansible.plugins.action import ActionBase
|
||||
from ansible.plugins.action.net_config import ActionModule as NetActionModule
|
||||
|
||||
|
||||
class ActionModule(NetActionModule, ActionBase):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class ActionModule(NetActionModule, ActionBase):
|
||||
self._handle_template()
|
||||
|
||||
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'):
|
||||
contents = json.dumps(result['_backup'], indent=4)
|
||||
@@ -48,5 +48,3 @@ class ActionModule(NetActionModule, ActionBase):
|
||||
del result['_backup']
|
||||
|
||||
return result
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class ActionModule(ActionBase):
|
||||
''' handler for package operations '''
|
||||
|
||||
self._supports_check_mode = True
|
||||
self._supports_async = True
|
||||
self._supports_async = True
|
||||
|
||||
result = super(ActionModule, self).run(tmp, task_vars)
|
||||
|
||||
@@ -42,12 +42,12 @@ class ActionModule(ActionBase):
|
||||
|
||||
if module == 'auto':
|
||||
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)
|
||||
else:
|
||||
module = self._templar.template('{{ansible_facts["ansible_pkg_mgr"]}}')
|
||||
except:
|
||||
pass # could not get it from template!
|
||||
pass # could not get it from template!
|
||||
|
||||
if module == 'auto':
|
||||
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)
|
||||
|
||||
src = self._task.args.get('src', None)
|
||||
src = self._task.args.get('src', None)
|
||||
remote_src = boolean(self._task.args.get('remote_src', 'no'))
|
||||
|
||||
if src is None:
|
||||
@@ -61,7 +61,7 @@ class ActionModule(ActionBase):
|
||||
tmp_src = self._connection._shell.join_path(tmp, os.path.basename(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.update(
|
||||
|
||||
@@ -59,13 +59,13 @@ class ActionModule(ActionBase):
|
||||
prompt = None
|
||||
seconds = None
|
||||
result.update(dict(
|
||||
changed = False,
|
||||
rc = 0,
|
||||
stderr = '',
|
||||
stdout = '',
|
||||
start = None,
|
||||
stop = None,
|
||||
delta = None,
|
||||
changed=False,
|
||||
rc=0,
|
||||
stderr='',
|
||||
stdout='',
|
||||
start=None,
|
||||
stop=None,
|
||||
delta=None,
|
||||
))
|
||||
|
||||
# Is 'args' empty, then this is the default prompted pause
|
||||
@@ -163,7 +163,6 @@ class ActionModule(ActionBase):
|
||||
else:
|
||||
raise AnsibleError('user requested abort!')
|
||||
|
||||
|
||||
except AnsibleTimeoutExceeded:
|
||||
# this is the exception we expect when the alarm signal
|
||||
# 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,
|
||||
# and everything else is an argument to the script which we need later
|
||||
# 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]
|
||||
args = ' '.join(parts[1:])
|
||||
args = ' '.join(parts[1:])
|
||||
|
||||
try:
|
||||
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 '''
|
||||
|
||||
self._supports_check_mode = True
|
||||
self._supports_async = True
|
||||
self._supports_async = True
|
||||
|
||||
result = super(ActionModule, self).run(tmp, task_vars)
|
||||
|
||||
@@ -41,12 +41,12 @@ class ActionModule(ActionBase):
|
||||
|
||||
if module == 'auto':
|
||||
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)
|
||||
else:
|
||||
module = self._templar.template('{{ansible_facts["ansible_service_mgr"]}}')
|
||||
except:
|
||||
pass # could not get it from template!
|
||||
pass # could not get it from template!
|
||||
|
||||
if module == 'auto':
|
||||
facts = self._execute_module(module_name='setup', module_args=dict(gather_subset='!all', filter='ansible_service_mgr'), task_vars=task_vars)
|
||||
|
||||
@@ -28,7 +28,7 @@ class ActionModule(ActionBase):
|
||||
|
||||
TRANSFERS_FILES = False
|
||||
|
||||
#TODO: document this in non-empty set_stats.py module
|
||||
# TODO: document this in non-empty set_stats.py module
|
||||
def run(self, tmp=None, task_vars=None):
|
||||
if task_vars is None:
|
||||
task_vars = dict()
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import glob
|
||||
|
||||
from ansible.plugins.action.sros import ActionModule as _ActionModule
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.module_utils.six.moves.urllib.parse import urlsplit
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.plugins.action.sros import ActionModule as _ActionModule
|
||||
from ansible.utils.vars import merge_hash
|
||||
|
||||
PRIVATE_KEYS_RE = re.compile('__.+__')
|
||||
@@ -110,4 +110,3 @@ class ActionModule(_ActionModule):
|
||||
searchpath.append(os.path.dirname(source))
|
||||
self._templar.environment.loader.searchpath = searchpath
|
||||
self._task.args['src'] = self._templar.template(template_data)
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ class ActionModule(ActionBase):
|
||||
return path
|
||||
|
||||
# If using docker, do not add user information
|
||||
if self._remote_transport not in [ 'docker' ] and user:
|
||||
if self._remote_transport not in ['docker'] and user:
|
||||
user_prefix = '%s@' % (user, )
|
||||
|
||||
if self._host_is_ipv6_address(host):
|
||||
@@ -308,8 +308,7 @@ class ActionModule(ActionBase):
|
||||
src = _tmp_args.get('src', None)
|
||||
dest = _tmp_args.get('dest', None)
|
||||
if src is None or dest is None:
|
||||
return dict(failed=True,
|
||||
msg="synchronize requires both src and dest parameters are set")
|
||||
return dict(failed=True, msg="synchronize requires both src and dest parameters are set")
|
||||
|
||||
if not dest_is_local:
|
||||
# Private key handling
|
||||
@@ -384,7 +383,7 @@ class ActionModule(ActionBase):
|
||||
|
||||
# If launching synchronize against docker container
|
||||
# use rsync_opts to support container to override rsh options
|
||||
if self._remote_transport in [ 'docker' ]:
|
||||
if self._remote_transport in ['docker']:
|
||||
# Replicate what we do in the module argumentspec handling for lists
|
||||
if not isinstance(_tmp_args.get('rsync_opts'), MutableSequence):
|
||||
tmp_rsync_opts = _tmp_args.get('rsync_opts', [])
|
||||
|
||||
@@ -23,11 +23,12 @@ from ansible import constants as C
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.module_utils._text import to_bytes, to_native, to_text
|
||||
from ansible.plugins.action import ActionBase
|
||||
from ansible.utils.hashing import checksum_s
|
||||
from ansible.template import generate_ansible_template_vars
|
||||
from ansible.utils.hashing import checksum_s
|
||||
|
||||
boolean = C.mk_boolean
|
||||
|
||||
|
||||
class ActionModule(ActionBase):
|
||||
|
||||
TRANSFERS_FILES = True
|
||||
@@ -56,9 +57,9 @@ class ActionModule(ActionBase):
|
||||
result = super(ActionModule, self).run(tmp, task_vars)
|
||||
|
||||
source = self._task.args.get('src', None)
|
||||
dest = self._task.args.get('dest', None)
|
||||
force = boolean(self._task.args.get('force', True))
|
||||
state = self._task.args.get('state', None)
|
||||
dest = self._task.args.get('dest', None)
|
||||
force = boolean(self._task.args.get('force', True))
|
||||
state = self._task.args.get('state', None)
|
||||
newline_sequence = self._task.args.get('newline_sequence', self.DEFAULT_NEWLINE_SEQUENCE)
|
||||
variable_start_string = self._task.args.get('variable_start_string', None)
|
||||
variable_end_string = self._task.args.get('variable_end_string', None)
|
||||
@@ -191,7 +192,7 @@ class ActionModule(ActionBase):
|
||||
dest=dest,
|
||||
original_basename=os.path.basename(source),
|
||||
follow=True,
|
||||
),
|
||||
),
|
||||
)
|
||||
result.update(self._execute_module(module_name='copy', module_args=new_module_args, task_vars=task_vars, tmp=tmp, delete_remote_tmp=False))
|
||||
|
||||
|
||||
@@ -38,8 +38,8 @@ class ActionModule(ActionBase):
|
||||
|
||||
result = super(ActionModule, self).run(tmp, task_vars)
|
||||
|
||||
source = self._task.args.get('src', None)
|
||||
dest = self._task.args.get('dest', None)
|
||||
source = self._task.args.get('src', None)
|
||||
dest = self._task.args.get('dest', None)
|
||||
remote_src = boolean(self._task.args.get('remote_src', False))
|
||||
creates = self._task.args.get('creates', None)
|
||||
decrypt = self._task.args.get('decrypt', True)
|
||||
@@ -73,7 +73,7 @@ class ActionModule(ActionBase):
|
||||
self._remove_tmp_path(tmp)
|
||||
return result
|
||||
|
||||
dest = self._remote_expand_user(dest) # CCTODO: Fix path for Windows hosts.
|
||||
dest = self._remote_expand_user(dest) # CCTODO: Fix path for Windows hosts.
|
||||
source = os.path.expanduser(source)
|
||||
|
||||
if not remote_src:
|
||||
|
||||
26
lib/ansible/plugins/cache/__init__.py
vendored
26
lib/ansible/plugins/cache/__init__.py
vendored
@@ -86,13 +86,13 @@ class BaseFileCacheModule(BaseCacheModule):
|
||||
self._cache_dir = os.path.expanduser(os.path.expandvars(C.CACHE_PLUGIN_CONNECTION))
|
||||
|
||||
if not self._cache_dir:
|
||||
raise AnsibleError("error, '%s' cache plugin requires the 'fact_caching_connection' config option"
|
||||
" to be set (to a writeable directory path)" % self.plugin_name)
|
||||
raise AnsibleError("error, '%s' cache plugin requires the 'fact_caching_connection' config option "
|
||||
"to be set (to a writeable directory path)" % self.plugin_name)
|
||||
|
||||
if not os.path.exists(self._cache_dir):
|
||||
try:
|
||||
os.makedirs(self._cache_dir)
|
||||
except (OSError,IOError) as e:
|
||||
except (OSError, IOError) as e:
|
||||
raise AnsibleError("error in '%s' cache plugin while trying to create cache dir %s : %s" % (self.plugin_name, self._cache_dir, to_bytes(e)))
|
||||
else:
|
||||
for x in (os.R_OK, os.W_OK, os.X_OK):
|
||||
@@ -118,12 +118,12 @@ class BaseFileCacheModule(BaseCacheModule):
|
||||
self._cache[key] = value
|
||||
return value
|
||||
except ValueError as e:
|
||||
display.warning("error in '%s' cache plugin while trying to read %s : %s."
|
||||
" Most likely a corrupt file, so erasing and failing." % (self.plugin_name, cachefile, to_bytes(e)))
|
||||
display.warning("error in '%s' cache plugin while trying to read %s : %s. "
|
||||
"Most likely a corrupt file, so erasing and failing." % (self.plugin_name, cachefile, to_bytes(e)))
|
||||
self.delete(key)
|
||||
raise AnsibleError("The cache file %s was corrupt, or did not otherwise contain valid data."
|
||||
" It has been removed, so you can re-run your command now." % cachefile)
|
||||
except (OSError,IOError) as e:
|
||||
raise AnsibleError("The cache file %s was corrupt, or did not otherwise contain valid data. "
|
||||
"It has been removed, so you can re-run your command now." % cachefile)
|
||||
except (OSError, IOError) as e:
|
||||
display.warning("error in '%s' cache plugin while trying to read %s : %s" % (self.plugin_name, cachefile, to_bytes(e)))
|
||||
raise KeyError
|
||||
except Exception as e:
|
||||
@@ -136,7 +136,7 @@ class BaseFileCacheModule(BaseCacheModule):
|
||||
cachefile = "%s/%s" % (self._cache_dir, key)
|
||||
try:
|
||||
self._dump(value, cachefile)
|
||||
except (OSError,IOError) as e:
|
||||
except (OSError, IOError) as e:
|
||||
display.warning("error in '%s' cache plugin while trying to write to %s : %s" % (self.plugin_name, cachefile, to_bytes(e)))
|
||||
|
||||
def has_expired(self, key):
|
||||
@@ -147,7 +147,7 @@ class BaseFileCacheModule(BaseCacheModule):
|
||||
cachefile = "%s/%s" % (self._cache_dir, key)
|
||||
try:
|
||||
st = os.stat(cachefile)
|
||||
except (OSError,IOError) as e:
|
||||
except (OSError, IOError) as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
return False
|
||||
else:
|
||||
@@ -179,7 +179,7 @@ class BaseFileCacheModule(BaseCacheModule):
|
||||
try:
|
||||
os.stat(cachefile)
|
||||
return True
|
||||
except (OSError,IOError) as e:
|
||||
except (OSError, IOError) as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
return False
|
||||
else:
|
||||
@@ -194,7 +194,7 @@ class BaseFileCacheModule(BaseCacheModule):
|
||||
try:
|
||||
os.remove("%s/%s" % (self._cache_dir, key))
|
||||
except (OSError, IOError):
|
||||
pass #TODO: only pass on non existing?
|
||||
pass # TODO: only pass on non existing?
|
||||
|
||||
def flush(self):
|
||||
self._cache = {}
|
||||
@@ -236,6 +236,7 @@ class BaseFileCacheModule(BaseCacheModule):
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class FactCache(MutableMapping):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -247,7 +248,6 @@ class FactCache(MutableMapping):
|
||||
# Backwards compat: self._display isn't really needed, just import the global display and use that.
|
||||
self._display = display
|
||||
|
||||
|
||||
def __getitem__(self, key):
|
||||
if not self._plugin.contains(key):
|
||||
raise KeyError
|
||||
|
||||
1
lib/ansible/plugins/cache/base.py
vendored
1
lib/ansible/plugins/cache/base.py
vendored
@@ -19,4 +19,3 @@ __metaclass__ = type
|
||||
|
||||
# moved actual classes to __init__ kept here for backward compat with 3rd parties
|
||||
from ansible.plugins.cache import BaseCacheModule, BaseFileCacheModule
|
||||
|
||||
|
||||
1
lib/ansible/plugins/cache/jsonfile.py
vendored
1
lib/ansible/plugins/cache/jsonfile.py
vendored
@@ -37,6 +37,7 @@ except ImportError:
|
||||
from ansible.parsing.utils.jsonify import jsonify
|
||||
from ansible.plugins.cache import BaseFileCacheModule
|
||||
|
||||
|
||||
class CacheModule(BaseFileCacheModule):
|
||||
"""
|
||||
A caching module backed by json files.
|
||||
|
||||
1
lib/ansible/plugins/cache/memory.py
vendored
1
lib/ansible/plugins/cache/memory.py
vendored
@@ -30,6 +30,7 @@ __metaclass__ = type
|
||||
|
||||
from ansible.plugins.cache import BaseCacheModule
|
||||
|
||||
|
||||
class CacheModule(BaseCacheModule):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
1
lib/ansible/plugins/cache/pickle.py
vendored
1
lib/ansible/plugins/cache/pickle.py
vendored
@@ -36,6 +36,7 @@ except ImportError:
|
||||
from ansible.module_utils.six import PY3
|
||||
from ansible.plugins.cache import BaseFileCacheModule
|
||||
|
||||
|
||||
class CacheModule(BaseFileCacheModule):
|
||||
"""
|
||||
A caching module backed by pickle files.
|
||||
|
||||
3
lib/ansible/plugins/cache/redis.py
vendored
3
lib/ansible/plugins/cache/redis.py
vendored
@@ -30,6 +30,7 @@ try:
|
||||
except ImportError:
|
||||
raise AnsibleError("The 'redis' python module is required for the redis fact cache, 'pip install redis'")
|
||||
|
||||
|
||||
class CacheModule(BaseCacheModule):
|
||||
"""
|
||||
A caching module backed by redis.
|
||||
@@ -65,7 +66,7 @@ class CacheModule(BaseCacheModule):
|
||||
|
||||
def set(self, key, value):
|
||||
value2 = json.dumps(value)
|
||||
if self._timeout > 0: # a timeout of 0 is handled as meaning 'never expire'
|
||||
if self._timeout > 0: # a timeout of 0 is handled as meaning 'never expire'
|
||||
self._cache.setex(self._make_key(key), int(self._timeout), value2)
|
||||
else:
|
||||
self._cache.set(self._make_key(key), value2)
|
||||
|
||||
1
lib/ansible/plugins/cache/yaml.py
vendored
1
lib/ansible/plugins/cache/yaml.py
vendored
@@ -37,6 +37,7 @@ from ansible.parsing.yaml.loader import AnsibleLoader
|
||||
from ansible.parsing.yaml.dumper import AnsibleDumper
|
||||
from ansible.plugins.cache import BaseFileCacheModule
|
||||
|
||||
|
||||
class CacheModule(BaseFileCacheModule):
|
||||
"""
|
||||
A caching module backed by yaml files.
|
||||
|
||||
@@ -213,7 +213,6 @@ class CallbackBase:
|
||||
if remove_key in result:
|
||||
del result[remove_key]
|
||||
|
||||
|
||||
def set_play_context(self, play_context):
|
||||
pass
|
||||
|
||||
@@ -280,7 +279,7 @@ class CallbackBase:
|
||||
def on_file_diff(self, host, diff):
|
||||
pass
|
||||
|
||||
####### V2 METHODS, by default they call v1 counterparts if possible ######
|
||||
# V2 METHODS, by default they call v1 counterparts if possible
|
||||
def v2_on_any(self, *args, **kwargs):
|
||||
self.on_any(args, kwargs)
|
||||
|
||||
@@ -295,7 +294,7 @@ class CallbackBase:
|
||||
def v2_runner_on_skipped(self, result):
|
||||
if C.DISPLAY_SKIPPED_HOSTS:
|
||||
host = result._host.get_name()
|
||||
self.runner_on_skipped(host, self._get_item(getattr(result._result,'results',{})))
|
||||
self.runner_on_skipped(host, self._get_item(getattr(result._result, 'results', {})))
|
||||
|
||||
def v2_runner_on_unreachable(self, result):
|
||||
host = result._host.get_name()
|
||||
@@ -307,7 +306,7 @@ class CallbackBase:
|
||||
def v2_runner_on_async_poll(self, result):
|
||||
host = result._host.get_name()
|
||||
jid = result._result.get('ansible_job_id')
|
||||
#FIXME, get real clock
|
||||
# FIXME, get real clock
|
||||
clock = 0
|
||||
self.runner_on_async_poll(host, result._result, jid, clock)
|
||||
|
||||
@@ -322,7 +321,7 @@ class CallbackBase:
|
||||
self.runner_on_async_failed(host, result._result, jid)
|
||||
|
||||
def v2_runner_on_file_diff(self, result, diff):
|
||||
pass #no v1 correspondance
|
||||
pass # no v1 correspondance
|
||||
|
||||
def v2_playbook_on_start(self, playbook):
|
||||
self.playbook_on_start()
|
||||
@@ -341,10 +340,10 @@ class CallbackBase:
|
||||
self.playbook_on_task_start(task.name, is_conditional)
|
||||
|
||||
def v2_playbook_on_cleanup_task_start(self, task):
|
||||
pass #no v1 correspondance
|
||||
pass # no v1 correspondance
|
||||
|
||||
def v2_playbook_on_handler_task_start(self, task):
|
||||
pass #no v1 correspondance
|
||||
pass # no v1 correspondance
|
||||
|
||||
def v2_playbook_on_vars_prompt(self, varname, private=True, prompt=None, encrypt=None, confirm=False, salt_size=None, salt=None, default=None):
|
||||
self.playbook_on_vars_prompt(varname, private, prompt, encrypt, confirm, salt_size, salt, default)
|
||||
@@ -372,7 +371,7 @@ class CallbackBase:
|
||||
self.on_file_diff(host, result._result['diff'])
|
||||
|
||||
def v2_playbook_on_include(self, included_file):
|
||||
pass #no v1 correspondance
|
||||
pass # no v1 correspondance
|
||||
|
||||
def v2_runner_item_on_ok(self, result):
|
||||
pass
|
||||
|
||||
@@ -21,6 +21,7 @@ __metaclass__ = type
|
||||
|
||||
from ansible.plugins.callback.default import CallbackModule as CallbackModule_default
|
||||
|
||||
|
||||
class CallbackModule(CallbackModule_default):
|
||||
|
||||
CALLBACK_VERSION = 2.0
|
||||
@@ -76,4 +77,3 @@ class CallbackModule(CallbackModule_default):
|
||||
def v2_runner_item_on_failed(self, result):
|
||||
self.display_task_banner()
|
||||
self.super_ref.v2_runner_item_on_failed(result)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ __metaclass__ = type
|
||||
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
|
||||
class CallbackModule(CallbackBase):
|
||||
"""
|
||||
This is a very trivial example of how any callback function can get at play and task objects.
|
||||
|
||||
@@ -30,6 +30,7 @@ from ansible import constants as C
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
from ansible.utils.color import colorize, hostcolor
|
||||
|
||||
|
||||
class CallbackModule(CallbackBase):
|
||||
|
||||
'''
|
||||
@@ -100,7 +101,7 @@ class CallbackModule(CallbackBase):
|
||||
self._process_items(result)
|
||||
else:
|
||||
|
||||
if (self._display.verbosity > 0 or '_ansible_verbose_always' in result._result) and not '_ansible_verbose_override' in result._result:
|
||||
if (self._display.verbosity > 0 or '_ansible_verbose_always' in result._result) and '_ansible_verbose_override' not in result._result:
|
||||
msg += " => %s" % (self._dump_results(result._result),)
|
||||
self._display.display(msg, color=color)
|
||||
|
||||
@@ -113,7 +114,7 @@ class CallbackModule(CallbackBase):
|
||||
self._process_items(result)
|
||||
else:
|
||||
msg = "skipping: [%s]" % result._host.get_name()
|
||||
if (self._display.verbosity > 0 or '_ansible_verbose_always' in result._result) and not '_ansible_verbose_override' in result._result:
|
||||
if (self._display.verbosity > 0 or '_ansible_verbose_always' in result._result) and '_ansible_verbose_override' not in result._result:
|
||||
msg += " => %s" % self._dump_results(result._result)
|
||||
self._display.display(msg, color=C.COLOR_SKIP)
|
||||
|
||||
@@ -209,7 +210,7 @@ class CallbackModule(CallbackBase):
|
||||
|
||||
msg += " => (item=%s)" % (self._get_item(result._result),)
|
||||
|
||||
if (self._display.verbosity > 0 or '_ansible_verbose_always' in result._result) and not '_ansible_verbose_override' in result._result:
|
||||
if (self._display.verbosity > 0 or '_ansible_verbose_always' in result._result) and '_ansible_verbose_override' not in result._result:
|
||||
msg += " => %s" % self._dump_results(result._result)
|
||||
self._display.display(msg, color=color)
|
||||
|
||||
@@ -230,7 +231,7 @@ class CallbackModule(CallbackBase):
|
||||
def v2_runner_item_on_skipped(self, result):
|
||||
if C.DISPLAY_SKIPPED_HOSTS:
|
||||
msg = "skipping: [%s] => (item=%s) " % (result._host.get_name(), self._get_item(result._result))
|
||||
if (self._display.verbosity > 0 or '_ansible_verbose_always' in result._result) and not '_ansible_verbose_override' in result._result:
|
||||
if (self._display.verbosity > 0 or '_ansible_verbose_always' in result._result) and '_ansible_verbose_override' not in result._result:
|
||||
msg += " => %s" % self._dump_results(result._result)
|
||||
self._display.display(msg, color=C.COLOR_SKIP)
|
||||
|
||||
@@ -269,16 +270,16 @@ class CallbackModule(CallbackBase):
|
||||
if C.SHOW_CUSTOM_STATS and stats.custom:
|
||||
self._display.banner("CUSTOM STATS: ")
|
||||
# per host
|
||||
#TODO: come up with 'pretty format'
|
||||
# TODO: come up with 'pretty format'
|
||||
for k in sorted(stats.custom.keys()):
|
||||
if k == '_run':
|
||||
continue
|
||||
self._display.display('\t%s: %s' % (k, self._dump_results(stats.custom[k], indent=1).replace('\n','')))
|
||||
self._display.display('\t%s: %s' % (k, self._dump_results(stats.custom[k], indent=1).replace('\n', '')))
|
||||
|
||||
# print per run custom stats
|
||||
if '_run' in stats.custom:
|
||||
self._display.display("", screen_only=True)
|
||||
self._display.display('\tRUN: %s' % self._dump_results(stats.custom['_run'], indent=1).replace('\n',''))
|
||||
self._display.display('\tRUN: %s' % self._dump_results(stats.custom['_run'], indent=1).replace('\n', ''))
|
||||
self._display.display("", screen_only=True)
|
||||
|
||||
def v2_playbook_on_start(self, playbook):
|
||||
@@ -291,13 +292,13 @@ class CallbackModule(CallbackBase):
|
||||
for option in dir(self._options):
|
||||
if option.startswith('_') or option in ['read_file', 'ensure_value', 'read_module']:
|
||||
continue
|
||||
val = getattr(self._options,option)
|
||||
val = getattr(self._options, option)
|
||||
if val:
|
||||
self._display.vvvv('%s: %s' % (option,val))
|
||||
self._display.vvvv('%s: %s' % (option, val))
|
||||
|
||||
def v2_runner_retry(self, result):
|
||||
task_name = result.task_name or result._task
|
||||
msg = "FAILED - RETRYING: %s (%d retries left)." % (task_name, result._result['retries'] - result._result['attempts'])
|
||||
if (self._display.verbosity > 2 or '_ansible_verbose_always' in result._result) and not '_ansible_verbose_override' in result._result:
|
||||
if (self._display.verbosity > 2 or '_ansible_verbose_always' in result._result) and '_ansible_verbose_override' not in result._result:
|
||||
msg += "Result was: %s" % self._dump_results(result._result)
|
||||
self._display.display(msg, color=C.COLOR_DEBUG)
|
||||
|
||||
@@ -71,18 +71,18 @@ import sys
|
||||
|
||||
|
||||
# FIXME: Importing constants as C simply does not work, beats me :-/
|
||||
#from ansible import constants as C
|
||||
# from ansible import constants as C
|
||||
class C:
|
||||
COLOR_HIGHLIGHT = 'white'
|
||||
COLOR_VERBOSE = 'blue'
|
||||
COLOR_WARN = 'bright purple'
|
||||
COLOR_ERROR = 'red'
|
||||
COLOR_DEBUG = 'dark gray'
|
||||
COLOR_DEPRECATE = 'purple'
|
||||
COLOR_SKIP = 'cyan'
|
||||
COLOR_HIGHLIGHT = 'white'
|
||||
COLOR_VERBOSE = 'blue'
|
||||
COLOR_WARN = 'bright purple'
|
||||
COLOR_ERROR = 'red'
|
||||
COLOR_DEBUG = 'dark gray'
|
||||
COLOR_DEPRECATE = 'purple'
|
||||
COLOR_SKIP = 'cyan'
|
||||
COLOR_UNREACHABLE = 'bright red'
|
||||
COLOR_OK = 'green'
|
||||
COLOR_CHANGED = 'yellow'
|
||||
COLOR_OK = 'green'
|
||||
COLOR_CHANGED = 'yellow'
|
||||
|
||||
|
||||
# Taken from Dstat
|
||||
@@ -136,15 +136,16 @@ class vt100:
|
||||
|
||||
|
||||
colors = dict(
|
||||
ok = vt100.darkgreen,
|
||||
changed = vt100.darkyellow,
|
||||
skipped = vt100.darkcyan,
|
||||
ignored = vt100.cyanbg + vt100.red,
|
||||
failed = vt100.darkred,
|
||||
unreachable = vt100.red,
|
||||
ok=vt100.darkgreen,
|
||||
changed=vt100.darkyellow,
|
||||
skipped=vt100.darkcyan,
|
||||
ignored=vt100.cyanbg + vt100.red,
|
||||
failed=vt100.darkred,
|
||||
unreachable=vt100.red,
|
||||
)
|
||||
|
||||
states = ( 'skipped', 'ok', 'changed', 'failed', 'unreachable' )
|
||||
states = ('skipped', 'ok', 'changed', 'failed', 'unreachable')
|
||||
|
||||
|
||||
class CallbackModule_dense(CallbackModule_default):
|
||||
|
||||
@@ -156,7 +157,6 @@ class CallbackModule_dense(CallbackModule_default):
|
||||
CALLBACK_TYPE = 'stdout'
|
||||
CALLBACK_NAME = 'dense'
|
||||
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# From CallbackModule
|
||||
|
||||
@@ -123,11 +123,17 @@ class CallbackModule(CallbackBase):
|
||||
level = 'err'
|
||||
else:
|
||||
level = 'notice' if 'changed' in msg and msg['changed'] else 'info'
|
||||
logs.append({"log": {
|
||||
'sources': {'source': source},
|
||||
'messages': {'message': json.dumps(msg)},
|
||||
'level': level
|
||||
}})
|
||||
logs.append({
|
||||
"log": {
|
||||
'sources': {
|
||||
'source': source
|
||||
},
|
||||
'messages': {
|
||||
'message': json.dumps(msg)
|
||||
},
|
||||
'level': level
|
||||
}
|
||||
})
|
||||
return logs
|
||||
|
||||
def send_reports(self, stats):
|
||||
@@ -154,8 +160,8 @@ class CallbackModule(CallbackBase):
|
||||
"metrics": metrics,
|
||||
"status": status,
|
||||
"logs": log,
|
||||
}
|
||||
}
|
||||
}
|
||||
# To be changed to /api/v2/config_reports in 1.11. Maybe we
|
||||
# could make a GET request to get the Foreman version & do
|
||||
# this automatically.
|
||||
|
||||
@@ -58,7 +58,7 @@ class CallbackModule(CallbackBase):
|
||||
if not HAS_PRETTYTABLE:
|
||||
self.disabled = True
|
||||
self._display.warning('The `prettytable` python module is not installed. '
|
||||
'Disabling the HipChat callback plugin.')
|
||||
'Disabling the HipChat callback plugin.')
|
||||
|
||||
self.msg_uri = 'https://api.hipchat.com/v1/rooms/message'
|
||||
self.token = os.getenv('HIPCHAT_TOKEN')
|
||||
@@ -69,8 +69,8 @@ class CallbackModule(CallbackBase):
|
||||
if self.token is None:
|
||||
self.disabled = True
|
||||
self._display.warning('HipChat token could not be loaded. The HipChat '
|
||||
'token can be provided using the `HIPCHAT_TOKEN` '
|
||||
'environment variable.')
|
||||
'token can be provided using the `HIPCHAT_TOKEN` '
|
||||
'environment variable.')
|
||||
|
||||
self.printed_playbook = False
|
||||
self.playbook_name = None
|
||||
|
||||
@@ -39,8 +39,8 @@ class CallbackModule(CallbackBase):
|
||||
super(CallbackModule, self).__init__(display=display)
|
||||
|
||||
if not HAS_XMPP:
|
||||
self._display.warning("The required python xmpp library (xmpppy) is not installed."
|
||||
" pip install git+https://github.com/ArchipelProject/xmpppy")
|
||||
self._display.warning("The required python xmpp library (xmpppy) is not installed. "
|
||||
"pip install git+https://github.com/ArchipelProject/xmpppy")
|
||||
self.disabled = True
|
||||
|
||||
self.serv = os.getenv('JABBER_SERV')
|
||||
@@ -48,15 +48,15 @@ class CallbackModule(CallbackBase):
|
||||
self.j_pass = os.getenv('JABBER_PASS')
|
||||
self.j_to = os.getenv('JABBER_TO')
|
||||
|
||||
if (self.j_user or self.j_pass or self.serv ) is None:
|
||||
if (self.j_user or self.j_pass or self.serv) is None:
|
||||
self.disabled = True
|
||||
self._display.warning ('Jabber CallBack want JABBER_USER and JABBER_PASS env variables')
|
||||
self._display.warning('Jabber CallBack want JABBER_USER and JABBER_PASS env variables')
|
||||
|
||||
def send_msg(self, msg):
|
||||
"""Send message"""
|
||||
jid = xmpp.JID(self.j_user)
|
||||
client = xmpp.Client(self.serv,debug=[])
|
||||
client.connect(server=(self.serv,5222))
|
||||
client = xmpp.Client(self.serv, debug=[])
|
||||
client.connect(server=(self.serv, 5222))
|
||||
client.auth(jid.getNode(), self.j_pass, resource=jid.getResource())
|
||||
message = xmpp.Message(self.j_to, msg)
|
||||
message.setAttr('type', 'chat')
|
||||
@@ -93,5 +93,4 @@ class CallbackModule(CallbackBase):
|
||||
self.send_msg("%s: Failures detected \n%s \nHost: %s\n Failed at:\n%s" % (name, self.task, h, out))
|
||||
else:
|
||||
out = self.debug
|
||||
self.send_msg("Great! \n Playbook %s completed:\n%s \n Last task debug:\n %s" % (name,s, out))
|
||||
|
||||
self.send_msg("Great! \n Playbook %s completed:\n%s \n Last task debug:\n %s" % (name, s, out))
|
||||
|
||||
@@ -44,8 +44,8 @@ class CallbackModule(CallbackBase):
|
||||
CALLBACK_NAME = 'log_plays'
|
||||
CALLBACK_NEEDS_WHITELIST = True
|
||||
|
||||
TIME_FORMAT="%b %d %Y %H:%M:%S"
|
||||
MSG_FORMAT="%(now)s - %(category)s - %(data)s\n\n"
|
||||
TIME_FORMAT = "%b %d %Y %H:%M:%S"
|
||||
MSG_FORMAT = "%(now)s - %(category)s - %(data)s\n\n"
|
||||
|
||||
def __init__(self):
|
||||
|
||||
|
||||
@@ -160,10 +160,10 @@ class PlainTextSocketAppender(object):
|
||||
|
||||
try:
|
||||
import ssl
|
||||
HAS_SSL=True
|
||||
HAS_SSL = True
|
||||
except ImportError: # for systems without TLS support.
|
||||
SocketAppender = PlainTextSocketAppender
|
||||
HAS_SSL=False
|
||||
HAS_SSL = False
|
||||
else:
|
||||
|
||||
class TLSSocketAppender(PlainTextSocketAppender):
|
||||
@@ -199,14 +199,14 @@ class CallbackModule(CallbackBase):
|
||||
self._display.warning("Unable to import ssl module. Will send over port 80.")
|
||||
|
||||
if not HAS_CERTIFI:
|
||||
self.disabled =True
|
||||
self.disabled = True
|
||||
self._display.warning('The `certifi` python module is not installed. '
|
||||
'Disabling the Logentries callback plugin.')
|
||||
'Disabling the Logentries callback plugin.')
|
||||
|
||||
if not HAS_FLATDICT:
|
||||
self.disabled =True
|
||||
self.disabled = True
|
||||
self._display.warning('The `flatdict` python module is not installed. '
|
||||
'Disabling the Logentries callback plugin.')
|
||||
'Disabling the Logentries callback plugin.')
|
||||
|
||||
config_path = os.path.abspath(os.path.dirname(__file__))
|
||||
config = configparser.ConfigParser()
|
||||
|
||||
@@ -33,6 +33,7 @@ except ImportError:
|
||||
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
|
||||
class CallbackModule(CallbackBase):
|
||||
"""
|
||||
ansible logstash callback plugin
|
||||
@@ -69,9 +70,9 @@ class CallbackModule(CallbackBase):
|
||||
if not HAS_LOGSTASH:
|
||||
self.disabled = True
|
||||
self._display.warning("The required python-logstash is not installed. "
|
||||
"pip install python-logstash")
|
||||
"pip install python-logstash")
|
||||
else:
|
||||
self.logger = logging.getLogger('python-logstash-logger')
|
||||
self.logger = logging.getLogger('python-logstash-logger')
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
|
||||
self.handler = logstash.TCPLogstashHandler(
|
||||
@@ -95,7 +96,7 @@ class CallbackModule(CallbackBase):
|
||||
'ansible_type': "start",
|
||||
'ansible_playbook': self.playbook,
|
||||
}
|
||||
self.logger.info("ansible start", extra = data)
|
||||
self.logger.info("ansible start", extra=data)
|
||||
|
||||
def v2_playbook_on_stats(self, stats):
|
||||
summarize_stat = {}
|
||||
@@ -115,7 +116,7 @@ class CallbackModule(CallbackBase):
|
||||
'ansible_playbook': self.playbook,
|
||||
'ansible_result': json.dumps(summarize_stat),
|
||||
}
|
||||
self.logger.info("ansible stats", extra = data)
|
||||
self.logger.info("ansible stats", extra=data)
|
||||
|
||||
def v2_runner_on_ok(self, result, **kwargs):
|
||||
data = {
|
||||
@@ -128,7 +129,7 @@ class CallbackModule(CallbackBase):
|
||||
'ansible_task': result._task,
|
||||
'ansible_result': self._dump_results(result._result)
|
||||
}
|
||||
self.logger.info("ansible ok", extra = data)
|
||||
self.logger.info("ansible ok", extra=data)
|
||||
|
||||
def v2_runner_on_skipped(self, result, **kwargs):
|
||||
data = {
|
||||
@@ -140,7 +141,7 @@ class CallbackModule(CallbackBase):
|
||||
'ansible_task': result._task,
|
||||
'ansible_host': result._host.name
|
||||
}
|
||||
self.logger.info("ansible skipped", extra = data)
|
||||
self.logger.info("ansible skipped", extra=data)
|
||||
|
||||
def v2_playbook_on_import_for_host(self, result, imported_file):
|
||||
data = {
|
||||
@@ -152,7 +153,7 @@ class CallbackModule(CallbackBase):
|
||||
'ansible_host': result._host.name,
|
||||
'imported_file': imported_file
|
||||
}
|
||||
self.logger.info("ansible import", extra = data)
|
||||
self.logger.info("ansible import", extra=data)
|
||||
|
||||
def v2_playbook_on_not_import_for_host(self, result, missing_file):
|
||||
data = {
|
||||
@@ -164,7 +165,7 @@ class CallbackModule(CallbackBase):
|
||||
'ansible_host': result._host.name,
|
||||
'missing_file': missing_file
|
||||
}
|
||||
self.logger.info("ansible import", extra = data)
|
||||
self.logger.info("ansible import", extra=data)
|
||||
|
||||
def v2_runner_on_failed(self, result, **kwargs):
|
||||
data = {
|
||||
@@ -178,7 +179,7 @@ class CallbackModule(CallbackBase):
|
||||
'ansible_result': self._dump_results(result._result)
|
||||
}
|
||||
self.errors += 1
|
||||
self.logger.error("ansible failed", extra = data)
|
||||
self.logger.error("ansible failed", extra=data)
|
||||
|
||||
def v2_runner_on_unreachable(self, result, **kwargs):
|
||||
data = {
|
||||
@@ -191,7 +192,7 @@ class CallbackModule(CallbackBase):
|
||||
'ansible_task': result._task,
|
||||
'ansible_result': self._dump_results(result._result)
|
||||
}
|
||||
self.logger.error("ansbile unreachable", extra = data)
|
||||
self.logger.error("ansbile unreachable", extra=data)
|
||||
|
||||
def v2_runner_on_async_failed(self, result, **kwargs):
|
||||
data = {
|
||||
@@ -205,4 +206,4 @@ class CallbackModule(CallbackBase):
|
||||
'ansible_result': self._dump_results(result._result)
|
||||
}
|
||||
self.errors += 1
|
||||
self.logger.error("ansible async", extra = data)
|
||||
self.logger.error("ansible async", extra=data)
|
||||
|
||||
@@ -32,11 +32,11 @@ from ansible.plugins.callback import CallbackBase
|
||||
def mail(subject='Ansible error mail', sender=None, to=None, cc=None, bcc=None, body=None, smtphost=None):
|
||||
|
||||
if sender is None:
|
||||
sender='<root>'
|
||||
sender = '<root>'
|
||||
if to is None:
|
||||
to='root'
|
||||
to = 'root'
|
||||
if smtphost is None:
|
||||
smtphost=os.getenv('SMTPHOST', 'localhost')
|
||||
smtphost = os.getenv('SMTPHOST', 'localhost')
|
||||
|
||||
if body is None:
|
||||
body = subject
|
||||
|
||||
@@ -38,9 +38,9 @@ class CallbackModule(CallbackBase):
|
||||
''' output the result of a command run '''
|
||||
|
||||
buf = "%s | %s | rc=%s >>\n" % (host, caption, result.get('rc', -1))
|
||||
buf += result.get('stdout','')
|
||||
buf += result.get('stderr','')
|
||||
buf += result.get('msg','')
|
||||
buf += result.get('stdout', '')
|
||||
buf += result.get('stderr', '')
|
||||
buf += result.get('msg', '')
|
||||
|
||||
return buf + "\n"
|
||||
|
||||
|
||||
@@ -34,10 +34,10 @@ class CallbackModule(CallbackBase):
|
||||
CALLBACK_TYPE = 'stdout'
|
||||
CALLBACK_NAME = 'oneline'
|
||||
|
||||
def _command_generic_msg(self, hostname, result, caption):
|
||||
stdout = result.get('stdout','').replace('\n', '\\n').replace('\r', '\\r')
|
||||
def _command_generic_msg(self, hostname, result, caption):
|
||||
stdout = result.get('stdout', '').replace('\n', '\\n').replace('\r', '\\r')
|
||||
if 'stderr' in result and result['stderr']:
|
||||
stderr = result.get('stderr','').replace('\n', '\\n').replace('\r', '\\r')
|
||||
stderr = result.get('stderr', '').replace('\n', '\\n').replace('\r', '\\r')
|
||||
return "%s | %s | rc=%s | (stdout) %s (stderr) %s" % (hostname, caption, result.get('rc', -1), stdout, stderr)
|
||||
else:
|
||||
return "%s | %s | rc=%s | (stdout) %s" % (hostname, caption, result.get('rc', -1), stdout)
|
||||
@@ -49,26 +49,25 @@ class CallbackModule(CallbackBase):
|
||||
error = result._result['exception'].strip().split('\n')[-1]
|
||||
msg = "An exception occurred during task execution. To see the full traceback, use -vvv. The error was: %s" % error
|
||||
else:
|
||||
msg = "An exception occurred during task execution. The full traceback is:\n" + result._result['exception'].replace('\n','')
|
||||
msg = "An exception occurred during task execution. The full traceback is:\n" + result._result['exception'].replace('\n', '')
|
||||
|
||||
if result._task.action in C.MODULE_NO_JSON and 'module_stderr' not in result._result:
|
||||
self._display.display(self._command_generic_msg(result._host.get_name(), result._result,'FAILED'), color=C.COLOR_ERROR)
|
||||
self._display.display(self._command_generic_msg(result._host.get_name(), result._result, 'FAILED'), color=C.COLOR_ERROR)
|
||||
else:
|
||||
self._display.display(msg, color=C.COLOR_ERROR)
|
||||
|
||||
self._display.display("%s | FAILED! => %s" % (result._host.get_name(), self._dump_results(result._result, indent=0).replace('\n','')),
|
||||
self._display.display("%s | FAILED! => %s" % (result._host.get_name(), self._dump_results(result._result, indent=0).replace('\n', '')),
|
||||
color=C.COLOR_ERROR)
|
||||
|
||||
def v2_runner_on_ok(self, result):
|
||||
if result._task.action in C.MODULE_NO_JSON:
|
||||
self._display.display(self._command_generic_msg(result._host.get_name(), result._result,'SUCCESS'), color=C.COLOR_OK)
|
||||
self._display.display(self._command_generic_msg(result._host.get_name(), result._result, 'SUCCESS'), color=C.COLOR_OK)
|
||||
else:
|
||||
self._display.display("%s | SUCCESS => %s" % (result._host.get_name(), self._dump_results(result._result, indent=0).replace('\n','')),
|
||||
self._display.display("%s | SUCCESS => %s" % (result._host.get_name(), self._dump_results(result._result, indent=0).replace('\n', '')),
|
||||
color=C.COLOR_OK)
|
||||
|
||||
|
||||
def v2_runner_on_unreachable(self, result):
|
||||
self._display.display("%s | UNREACHABLE!: %s" % (result._host.get_name(), result._result.get('msg','')), color=C.COLOR_UNREACHABLE)
|
||||
self._display.display("%s | UNREACHABLE!: %s" % (result._host.get_name(), result._result.get('msg', '')), color=C.COLOR_UNREACHABLE)
|
||||
|
||||
def v2_runner_on_skipped(self, result):
|
||||
self._display.display("%s | SKIPPED" % (result._host.get_name()), color=C.COLOR_SKIP)
|
||||
|
||||
@@ -25,11 +25,12 @@ import os
|
||||
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
FAILED_VOICE="Zarvox"
|
||||
REGULAR_VOICE="Trinoids"
|
||||
HAPPY_VOICE="Cellos"
|
||||
LASER_VOICE="Princess"
|
||||
SAY_CMD="/usr/bin/say"
|
||||
FAILED_VOICE = "Zarvox"
|
||||
REGULAR_VOICE = "Trinoids"
|
||||
HAPPY_VOICE = "Cellos"
|
||||
LASER_VOICE = "Princess"
|
||||
SAY_CMD = "/usr/bin/say"
|
||||
|
||||
|
||||
class CallbackModule(CallbackBase):
|
||||
"""
|
||||
@@ -48,7 +49,7 @@ class CallbackModule(CallbackBase):
|
||||
# ansible will not call any callback if disabled is set to True
|
||||
if not os.path.exists(SAY_CMD):
|
||||
self.disabled = True
|
||||
self._display.warning("%s does not exist, plugin %s disabled" % (SAY_CMD, os.path.basename(__file__)) )
|
||||
self._display.warning("%s does not exist, plugin %s disabled" % (SAY_CMD, os.path.basename(__file__)))
|
||||
|
||||
def say(self, msg, voice):
|
||||
subprocess.call([SAY_CMD, msg, "--voice=%s" % (voice)])
|
||||
|
||||
@@ -37,7 +37,9 @@ t0 = tn = time.time()
|
||||
|
||||
def secondsToStr(t):
|
||||
# http://bytes.com/topic/python/answers/635958-handy-short-cut-formatting-elapsed-time-floating-point-seconds
|
||||
rediv = lambda ll, b: list(divmod(ll[0], b)) + ll[1:]
|
||||
def rediv(ll, b):
|
||||
return list(divmod(ll[0], b)) + ll[1:]
|
||||
|
||||
return "%d:%02d:%02d.%03d" % tuple(reduce(rediv, [[t * 1000, ], 1000, 60, 60]))
|
||||
|
||||
|
||||
@@ -104,7 +106,7 @@ class CallbackModule(CallbackBase):
|
||||
self.current = task._uuid
|
||||
self.stats[self.current] = {'time': time.time(), 'name': task.get_name()}
|
||||
if self._display.verbosity >= 2:
|
||||
self.stats[self.current][ 'path'] = task.get_path()
|
||||
self.stats[self.current]['path'] = task.get_path()
|
||||
|
||||
def v2_playbook_on_task_start(self, task, is_conditional):
|
||||
self._record_task(task)
|
||||
@@ -127,7 +129,7 @@ class CallbackModule(CallbackBase):
|
||||
if self.sort_order != 'none':
|
||||
results = sorted(
|
||||
self.stats.items(),
|
||||
key=lambda x:x[1]['time'],
|
||||
key=lambda x: x[1]['time'],
|
||||
reverse=self.sort_order,
|
||||
)
|
||||
|
||||
@@ -136,7 +138,7 @@ class CallbackModule(CallbackBase):
|
||||
|
||||
# Print the timings
|
||||
for uuid, result in results:
|
||||
msg=u"{0:-<{2}}{1:->9}".format(result['name'] + u' ',u' {0:.02f}s'.format(result['time']), self._display.columns - 9)
|
||||
msg = u"{0:-<{2}}{1:->9}".format(result['name'] + u' ', u' {0:.02f}s'.format(result['time']), self._display.columns - 9)
|
||||
if 'path' in result:
|
||||
msg += u"\n{0:-<{1}}".format(result['path'] + u' ', self._display.columns)
|
||||
self._display.display(msg)
|
||||
|
||||
@@ -106,7 +106,7 @@ class CallbackModule(CallbackBase):
|
||||
lines = text.splitlines()
|
||||
result_lines = []
|
||||
for l in lines:
|
||||
result_lines.append("{}{}".format(' '*indent_level, l))
|
||||
result_lines.append("{}{}".format(' ' * indent_level, l))
|
||||
return '\n'.join(result_lines)
|
||||
|
||||
def _print_diff(self, diff, indent_level):
|
||||
@@ -121,7 +121,7 @@ class CallbackModule(CallbackBase):
|
||||
diff = dict_diff(diff['before'], diff['after'])
|
||||
if diff:
|
||||
diff = colorize(str(diff), 'changed')
|
||||
print(self._indent_text(diff, indent_level+4))
|
||||
print(self._indent_text(diff, indent_level + 4))
|
||||
|
||||
def _print_host_or_item(self, host_or_item, changed, msg, diff, is_host, error, stdout, stderr):
|
||||
if is_host:
|
||||
@@ -144,7 +144,7 @@ class CallbackModule(CallbackBase):
|
||||
msg = colorize(msg, color)
|
||||
|
||||
line_length = 120
|
||||
spaces = ' ' * (40-len(name)-indent_level)
|
||||
spaces = ' ' * (40 - len(name) - indent_level)
|
||||
line = "{} * {}{}- {}".format(' ' * indent_level, name, spaces, change_string)
|
||||
|
||||
if len(msg) < 50:
|
||||
@@ -152,16 +152,16 @@ class CallbackModule(CallbackBase):
|
||||
print("{} {}---------".format(line, '-' * (line_length - len(line))))
|
||||
else:
|
||||
print("{} {}".format(line, '-' * (line_length - len(line))))
|
||||
print(self._indent_text(msg, indent_level+4))
|
||||
print(self._indent_text(msg, indent_level + 4))
|
||||
|
||||
if diff is not None:
|
||||
self._print_diff(diff, indent_level)
|
||||
if stdout is not None:
|
||||
stdout = colorize(stdout, 'failed')
|
||||
print(self._indent_text(stdout, indent_level+4))
|
||||
print(self._indent_text(stdout, indent_level + 4))
|
||||
if stderr is not None:
|
||||
stderr = colorize(stderr, 'failed')
|
||||
print(self._indent_text(stderr, indent_level+4))
|
||||
print(self._indent_text(stderr, indent_level + 4))
|
||||
|
||||
def v2_playbook_on_play_start(self, play):
|
||||
"""Run on start of the play."""
|
||||
@@ -236,7 +236,7 @@ class CallbackModule(CallbackBase):
|
||||
self.last_skipped = False
|
||||
|
||||
line_length = 120
|
||||
spaces = ' ' * (31-len(result._host.name)-4)
|
||||
spaces = ' ' * (31 - len(result._host.name) - 4)
|
||||
|
||||
line = " * {}{}- {}".format(colorize(result._host.name, 'not_so_bold'),
|
||||
spaces,
|
||||
@@ -255,4 +255,3 @@ class CallbackModule(CallbackBase):
|
||||
v2_playbook_on_handler_task_start = v2_playbook_on_task_start
|
||||
v2_runner_on_failed = v2_runner_on_ok
|
||||
v2_runner_on_unreachable = v2_runner_on_ok
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ __metaclass__ = type
|
||||
|
||||
from ansible.plugins.callback.default import CallbackModule as CallbackModule_default
|
||||
|
||||
|
||||
class CallbackModule(CallbackModule_default):
|
||||
|
||||
'''
|
||||
|
||||
@@ -68,7 +68,6 @@ class CallbackModule(CallbackBase):
|
||||
else:
|
||||
self._options = None
|
||||
|
||||
|
||||
super(CallbackModule, self).__init__(display=display)
|
||||
|
||||
if not HAS_PRETTYTABLE:
|
||||
|
||||
@@ -12,6 +12,7 @@ import socket
|
||||
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
|
||||
class CallbackModule(CallbackBase):
|
||||
"""
|
||||
logs ansible-playbook and ansible runs to a syslog server in json format
|
||||
@@ -33,35 +34,33 @@ class CallbackModule(CallbackBase):
|
||||
|
||||
super(CallbackModule, self).__init__()
|
||||
|
||||
self.logger = logging.getLogger('ansible logger')
|
||||
self.logger = logging.getLogger('ansible logger')
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
|
||||
self.handler = logging.handlers.SysLogHandler(
|
||||
address = (os.getenv('SYSLOG_SERVER','localhost'),
|
||||
int(os.getenv('SYSLOG_PORT',514))),
|
||||
facility= os.getenv('SYSLOG_FACILITY',logging.handlers.SysLogHandler.LOG_USER)
|
||||
address=(os.getenv('SYSLOG_SERVER', 'localhost'), int(os.getenv('SYSLOG_PORT', 514))),
|
||||
facility=os.getenv('SYSLOG_FACILITY', logging.handlers.SysLogHandler.LOG_USER)
|
||||
)
|
||||
self.logger.addHandler(self.handler)
|
||||
self.hostname = socket.gethostname()
|
||||
|
||||
|
||||
def runner_on_failed(self, host, res, ignore_errors=False):
|
||||
self.logger.error('%s ansible-command: task execution FAILED; host: %s; message: %s' % (self.hostname,host,self._dump_results(res)))
|
||||
self.logger.error('%s ansible-command: task execution FAILED; host: %s; message: %s' % (self.hostname, host, self._dump_results(res)))
|
||||
|
||||
def runner_on_ok(self, host, res):
|
||||
self.logger.info('%s ansible-command: task execution OK; host: %s; message: %s' % (self.hostname,host,self._dump_results(res)))
|
||||
self.logger.info('%s ansible-command: task execution OK; host: %s; message: %s' % (self.hostname, host, self._dump_results(res)))
|
||||
|
||||
def runner_on_skipped(self, host, item=None):
|
||||
self.logger.info('%s ansible-command: task execution SKIPPED; host: %s; message: %s' % (self.hostname,host, 'skipped'))
|
||||
self.logger.info('%s ansible-command: task execution SKIPPED; host: %s; message: %s' % (self.hostname, host, 'skipped'))
|
||||
|
||||
def runner_on_unreachable(self, host, res):
|
||||
self.logger.error('%s ansible-command: task execution UNREACHABLE; host: %s; message: %s' % (self.hostname,host,self._dump_results(res)))
|
||||
self.logger.error('%s ansible-command: task execution UNREACHABLE; host: %s; message: %s' % (self.hostname, host, self._dump_results(res)))
|
||||
|
||||
def runner_on_async_failed(self, host, res, jid):
|
||||
self.logger.error('%s ansible-command: task execution FAILED; host: %s; message: %s' % (self.hostname,host,self._dump_results(res)))
|
||||
self.logger.error('%s ansible-command: task execution FAILED; host: %s; message: %s' % (self.hostname, host, self._dump_results(res)))
|
||||
|
||||
def playbook_on_import_for_host(self, host, imported_file):
|
||||
self.logger.info('%s ansible-command: playbook IMPORTED; host: %s; message: imported file %s' % (self.hostname,host,imported_file))
|
||||
self.logger.info('%s ansible-command: playbook IMPORTED; host: %s; message: imported file %s' % (self.hostname, host, imported_file))
|
||||
|
||||
def playbook_on_not_import_for_host(self, host, missing_file):
|
||||
self.logger.info('%s ansible-command: playbook NOT IMPORTED; host: %s; message: missing file %s' % (self.hostname,host,missing_file))
|
||||
self.logger.info('%s ansible-command: playbook NOT IMPORTED; host: %s; message: missing file %s' % (self.hostname, host, missing_file))
|
||||
|
||||
@@ -59,8 +59,8 @@ class ConnectionBase(with_metaclass(ABCMeta, object)):
|
||||
'''
|
||||
|
||||
has_pipelining = False
|
||||
has_native_async = False # eg, winrm
|
||||
always_pipeline_modules = False # eg, winrm
|
||||
has_native_async = False # eg, winrm
|
||||
always_pipeline_modules = False # eg, winrm
|
||||
become_methods = C.BECOME_METHODS
|
||||
# When running over this connection type, prefer modules written in a certain language
|
||||
# as discovered by the specified file extension. An empty string as the
|
||||
|
||||
@@ -44,7 +44,7 @@ except ImportError:
|
||||
# ((1400-8)/4)*3) = 1044
|
||||
# which leaves room for the TCP/IP header. We set this to a
|
||||
# multiple of the value to speed up file reads.
|
||||
CHUNK_SIZE=1044*20
|
||||
CHUNK_SIZE = 1044 * 20
|
||||
|
||||
|
||||
class Connection(ConnectionBase):
|
||||
@@ -73,7 +73,7 @@ class Connection(ConnectionBase):
|
||||
host=self._play_context.remote_addr)
|
||||
while tries > 0:
|
||||
try:
|
||||
self.conn.connect((self._play_context.remote_addr,self._play_context.accelerate_port))
|
||||
self.conn.connect((self._play_context.remote_addr, self._play_context.accelerate_port))
|
||||
break
|
||||
except socket.error:
|
||||
display.vvvv("connection to %s failed, retrying..." % self._play_context.remote_addr, host=self._play_context.remote_addr)
|
||||
@@ -107,11 +107,11 @@ class Connection(ConnectionBase):
|
||||
sock.close()
|
||||
|
||||
def send_data(self, data):
|
||||
packed_len = struct.pack('!Q',len(data))
|
||||
packed_len = struct.pack('!Q', len(data))
|
||||
return self.conn.sendall(packed_len + data)
|
||||
|
||||
def recv_data(self):
|
||||
header_len = 8 # size of a packed unsigned long long
|
||||
header_len = 8 # size of a packed unsigned long long
|
||||
data = b""
|
||||
try:
|
||||
display.vvvv("in recv_data(), waiting for the header", host=self._play_context.remote_addr)
|
||||
@@ -122,7 +122,7 @@ class Connection(ConnectionBase):
|
||||
return None
|
||||
data += d
|
||||
display.vvvv("got the header, unpacking", host=self._play_context.remote_addr)
|
||||
data_len = struct.unpack('!Q',data[:header_len])[0]
|
||||
data_len = struct.unpack('!Q', data[:header_len])[0]
|
||||
data = data[header_len:]
|
||||
display.vvvv("data received so far (expecting %d): %d" % (data_len, len(data)), host=self._play_context.remote_addr)
|
||||
while len(data) < data_len:
|
||||
@@ -252,7 +252,7 @@ class Connection(ConnectionBase):
|
||||
response = keyczar_decrypt(self.key, response)
|
||||
response = json.loads(response)
|
||||
|
||||
if response.get('failed',False):
|
||||
if response.get('failed', False):
|
||||
raise AnsibleError("failed to put the file in the requested location")
|
||||
finally:
|
||||
fd.close()
|
||||
@@ -263,7 +263,7 @@ class Connection(ConnectionBase):
|
||||
response = keyczar_decrypt(self.key, response)
|
||||
response = json.loads(response)
|
||||
|
||||
if response.get('failed',False):
|
||||
if response.get('failed', False):
|
||||
raise AnsibleError("failed to put the file in the requested location")
|
||||
|
||||
def fetch_file(self, in_path, out_path):
|
||||
|
||||
@@ -96,7 +96,7 @@ class Connection(ConnectionBase):
|
||||
display.vvv("EXEC %s" % (local_cmd), host=self.chroot)
|
||||
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
|
||||
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
return p
|
||||
|
||||
|
||||
@@ -235,7 +235,7 @@ class Connection(ConnectionBase):
|
||||
with open(to_bytes(in_path, errors='surrogate_or_strict'), 'rb') as in_file:
|
||||
try:
|
||||
p = subprocess.Popen(args, stdin=in_file,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except OSError:
|
||||
raise AnsibleError("docker connection requires dd command in the container to put files")
|
||||
stdout, stderr = p.communicate()
|
||||
@@ -257,7 +257,7 @@ class Connection(ConnectionBase):
|
||||
args = [to_bytes(i, errors='surrogate_or_strict') for i in args]
|
||||
|
||||
p = subprocess.Popen(args, stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
p.communicate()
|
||||
|
||||
# Rename if needed
|
||||
|
||||
@@ -43,6 +43,7 @@ except ImportError:
|
||||
from ansible.utils.display import Display
|
||||
display = Display()
|
||||
|
||||
|
||||
class Connection(object):
|
||||
''' Func-based connections '''
|
||||
|
||||
|
||||
@@ -65,4 +65,3 @@ class Connection(Jail):
|
||||
raise AnsibleError(u"iocage returned an error: {}".format(stdout))
|
||||
|
||||
return stdout.strip('\n')
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class Connection(ConnectionBase):
|
||||
super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
|
||||
|
||||
self.jail = self._play_context.remote_addr
|
||||
if self.modified_jailname_key in kwargs :
|
||||
if self.modified_jailname_key in kwargs:
|
||||
self.jail = kwargs[self.modified_jailname_key]
|
||||
|
||||
if os.geteuid() != 0:
|
||||
@@ -122,7 +122,7 @@ class Connection(ConnectionBase):
|
||||
display.vvv("EXEC %s" % (local_cmd,), host=self.jail)
|
||||
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
|
||||
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
return p
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ class Connection(ConnectionBase):
|
||||
display.vvv("EXEC %s" % (local_cmd,), host=self.lxc)
|
||||
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
|
||||
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
return p
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ class Connection(ConnectionBase):
|
||||
p = subprocess.Popen(
|
||||
cmd,
|
||||
shell=isinstance(cmd, (text_type, binary_type)),
|
||||
executable=executable, #cwd=...
|
||||
executable=executable, # cwd=...
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
|
||||
@@ -68,7 +68,7 @@ class Connection(ConnectionBase):
|
||||
raise errors.AnsibleError("%s is not running" % self.container_name)
|
||||
|
||||
def _communicate(self, pid, in_data, stdin, stdout, stderr):
|
||||
buf = { stdout: [], stderr: [] }
|
||||
buf = {stdout: [], stderr: []}
|
||||
read_fds = [stdout, stderr]
|
||||
if in_data:
|
||||
write_fds = [stdin]
|
||||
@@ -109,7 +109,7 @@ class Connection(ConnectionBase):
|
||||
|
||||
read_stdout, write_stdout = None, None
|
||||
read_stderr, write_stderr = None, None
|
||||
read_stdin, write_stdin = None, None
|
||||
read_stdin, write_stdin = None, None
|
||||
|
||||
try:
|
||||
read_stdout, write_stdout = os.pipe()
|
||||
|
||||
@@ -52,7 +52,7 @@ except ImportError:
|
||||
display = Display()
|
||||
|
||||
|
||||
AUTHENTICITY_MSG="""
|
||||
AUTHENTICITY_MSG = """
|
||||
paramiko: The authenticity of host '%s' can't be established.
|
||||
The %s key fingerprint is %s.
|
||||
Are you sure you want to continue connecting (yes/no)?
|
||||
@@ -62,12 +62,12 @@ Are you sure you want to continue connecting (yes/no)?
|
||||
SETTINGS_REGEX = re.compile(r'(\w+)(?:\s*=\s*|\s+)(.+)')
|
||||
|
||||
# prevent paramiko warning noise -- see http://stackoverflow.com/questions/3920502/
|
||||
HAVE_PARAMIKO=False
|
||||
HAVE_PARAMIKO = False
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
try:
|
||||
import paramiko
|
||||
HAVE_PARAMIKO=True
|
||||
HAVE_PARAMIKO = True
|
||||
logging.getLogger("paramiko").setLevel(logging.WARNING)
|
||||
except ImportError:
|
||||
pass
|
||||
@@ -109,7 +109,7 @@ class MyAddPolicy(object):
|
||||
|
||||
self.connection.connection_unlock()
|
||||
|
||||
if inp not in ['yes','y','']:
|
||||
if inp not in ['yes', 'y', '']:
|
||||
raise AnsibleError("host connection rejected by user")
|
||||
|
||||
key._added_by_ansible_this_time = True
|
||||
@@ -213,11 +213,11 @@ class Connection(ConnectionBase):
|
||||
if C.HOST_KEY_CHECKING:
|
||||
for ssh_known_hosts in ("/etc/ssh/ssh_known_hosts", "/etc/openssh/ssh_known_hosts"):
|
||||
try:
|
||||
#TODO: check if we need to look at several possible locations, possible for loop
|
||||
# TODO: check if we need to look at several possible locations, possible for loop
|
||||
ssh.load_system_host_keys(ssh_known_hosts)
|
||||
break
|
||||
except IOError:
|
||||
pass # file was not found, but not required to function
|
||||
pass # file was not found, but not required to function
|
||||
ssh.load_system_host_keys()
|
||||
|
||||
sock_kwarg = self._parse_proxy_command(port)
|
||||
@@ -305,10 +305,10 @@ class Connection(ConnectionBase):
|
||||
display.debug("chunk is: %s" % chunk)
|
||||
if not chunk:
|
||||
if b'unknown user' in become_output:
|
||||
raise AnsibleError( 'user %s does not exist' % self._play_context.become_user)
|
||||
raise AnsibleError('user %s does not exist' % self._play_context.become_user)
|
||||
else:
|
||||
break
|
||||
#raise AnsibleError('ssh connection closed waiting for password prompt')
|
||||
# raise AnsibleError('ssh connection closed waiting for password prompt')
|
||||
become_output += chunk
|
||||
|
||||
# need to check every line because we might get lectured
|
||||
@@ -441,7 +441,7 @@ class Connection(ConnectionBase):
|
||||
# (This doesn't acquire the connection lock because it needs
|
||||
# to exclude only other known_hosts writers, not connections
|
||||
# that are starting up.)
|
||||
lockfile = self.keyfile.replace("known_hosts",".known_hosts.lock")
|
||||
lockfile = self.keyfile.replace("known_hosts", ".known_hosts.lock")
|
||||
dirname = os.path.dirname(self.keyfile)
|
||||
makedirs_safe(dirname)
|
||||
|
||||
@@ -457,7 +457,7 @@ class Connection(ConnectionBase):
|
||||
# gather information about the current key file, so
|
||||
# we can ensure the new file has the correct mode/owner
|
||||
|
||||
key_dir = os.path.dirname(self.keyfile)
|
||||
key_dir = os.path.dirname(self.keyfile)
|
||||
if os.path.exists(self.keyfile):
|
||||
key_stat = os.stat(self.keyfile)
|
||||
mode = key_stat.st_mode
|
||||
|
||||
@@ -135,6 +135,7 @@ class AnsibleControlPersistBrokenPipeError(AnsibleError):
|
||||
''' ControlPersist broken pipe '''
|
||||
pass
|
||||
|
||||
|
||||
def _ssh_retry(func):
|
||||
"""
|
||||
Decorator to retry ssh/scp/sftp in the case of a connection failure
|
||||
@@ -365,12 +366,14 @@ class Connection(ConnectionBase):
|
||||
|
||||
user = self._play_context.remote_user
|
||||
if user:
|
||||
self._add_args(b_command,
|
||||
(b"-o", b"User=" + to_bytes(self._play_context.remote_user, errors='surrogate_or_strict')),
|
||||
self._add_args(
|
||||
b_command,
|
||||
(b"-o", b"User=" + to_bytes(self._play_context.remote_user, errors='surrogate_or_strict')),
|
||||
u"ANSIBLE_REMOTE_USER/remote_user/ansible_user/user/-u set"
|
||||
)
|
||||
|
||||
self._add_args(b_command,
|
||||
self._add_args(
|
||||
b_command,
|
||||
(b"-o", b"ConnectTimeout=" + to_bytes(self._play_context.timeout, errors='surrogate_or_strict', nonstring='simplerepr')),
|
||||
u"ANSIBLE_TIMEOUT/timeout set"
|
||||
)
|
||||
@@ -459,7 +462,7 @@ class Connection(ConnectionBase):
|
||||
display_line = to_text(b_line).rstrip('\r\n')
|
||||
suppress_output = False
|
||||
|
||||
#display.debug("Examining line (source=%s, state=%s): '%s'" % (source, state, display_line))
|
||||
# display.debug("Examining line (source=%s, state=%s): '%s'" % (source, state, display_line))
|
||||
if self._play_context.prompt and self.check_password_prompt(b_line):
|
||||
display.debug("become_prompt: (source=%s, state=%s): '%s'" % (source, state, display_line))
|
||||
self._flags['become_prompt'] = True
|
||||
@@ -594,7 +597,7 @@ class Connection(ConnectionBase):
|
||||
for fd in (p.stdout, p.stderr):
|
||||
fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK)
|
||||
|
||||
### TODO: bcoca would like to use SelectSelector() when open
|
||||
# TODO: bcoca would like to use SelectSelector() when open
|
||||
# filehandles is low, then switch to more efficient ones when higher.
|
||||
# select is faster when filehandles is low.
|
||||
selector = selectors.DefaultSelector()
|
||||
@@ -839,8 +842,8 @@ class Connection(ConnectionBase):
|
||||
if returncode == 255:
|
||||
raise AnsibleConnectionFailure("Failed to connect to the host via %s: %s" % (method, to_native(stderr)))
|
||||
else:
|
||||
raise AnsibleError("failed to transfer file to {0} {1}:\n{2}\n{3}"\
|
||||
.format(to_native(in_path), to_native(out_path), to_native(stdout), to_native(stderr)))
|
||||
raise AnsibleError("failed to transfer file to %s %s:\n%s\n%s" %
|
||||
(to_native(in_path), to_native(out_path), to_native(stdout), to_native(stderr)))
|
||||
|
||||
#
|
||||
# Main public methods
|
||||
@@ -852,7 +855,6 @@ class Connection(ConnectionBase):
|
||||
|
||||
display.vvv(u"ESTABLISH SSH CONNECTION FOR USER: {0}".format(self._play_context.remote_user), host=self._play_context.remote_addr)
|
||||
|
||||
|
||||
# we can only use tty when we are not pipelining the modules. piping
|
||||
# data into /usr/bin/python inside a tty automatically invokes the
|
||||
# python interactive-mode but the modules are not compatible with the
|
||||
|
||||
@@ -74,15 +74,15 @@ class Connection(ConnectionBase):
|
||||
become_methods = ['runas']
|
||||
allow_executable = False
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
self.has_pipelining = True
|
||||
self.has_pipelining = True
|
||||
self.always_pipeline_modules = True
|
||||
self.has_native_async = True
|
||||
self.protocol = None
|
||||
self.shell_id = None
|
||||
self.delegate = None
|
||||
self._shell_type = 'powershell'
|
||||
self.protocol = None
|
||||
self.shell_id = None
|
||||
self.delegate = None
|
||||
self._shell_type = 'powershell'
|
||||
# FUTURE: Add runas support
|
||||
|
||||
super(Connection, self).__init__(*args, **kwargs)
|
||||
@@ -109,13 +109,13 @@ class Connection(ConnectionBase):
|
||||
self._become_user = self._play_context.become_user
|
||||
self._become_pass = self._play_context.become_pass
|
||||
|
||||
self._kinit_cmd = hostvars.get('ansible_winrm_kinit_cmd', 'kinit')
|
||||
self._kinit_cmd = hostvars.get('ansible_winrm_kinit_cmd', 'kinit')
|
||||
|
||||
if hasattr(winrm, 'FEATURE_SUPPORTED_AUTHTYPES'):
|
||||
self._winrm_supported_authtypes = set(winrm.FEATURE_SUPPORTED_AUTHTYPES)
|
||||
else:
|
||||
# for legacy versions of pywinrm, use the values we know are supported
|
||||
self._winrm_supported_authtypes = set(['plaintext','ssl','kerberos'])
|
||||
self._winrm_supported_authtypes = set(['plaintext', 'ssl', 'kerberos'])
|
||||
|
||||
# TODO: figure out what we want to do with auto-transport selection in the face of NTLM/Kerb/CredSSP/Cert/Basic
|
||||
transport_selector = 'ssl' if self._winrm_scheme == 'https' else 'plaintext'
|
||||
@@ -191,7 +191,7 @@ class Connection(ConnectionBase):
|
||||
Establish a WinRM connection over HTTP/HTTPS.
|
||||
'''
|
||||
display.vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" %
|
||||
(self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host)
|
||||
(self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host)
|
||||
netloc = '%s:%d' % (self._winrm_host, self._winrm_port)
|
||||
endpoint = urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', ''))
|
||||
errors = []
|
||||
@@ -320,7 +320,7 @@ class Connection(ConnectionBase):
|
||||
payload_bytes = to_bytes(payload)
|
||||
byte_count = len(payload_bytes)
|
||||
for i in range(0, byte_count, buffer_size):
|
||||
yield payload_bytes[i:i+buffer_size], i+buffer_size >= byte_count
|
||||
yield payload_bytes[i:i + buffer_size], i + buffer_size >= byte_count
|
||||
|
||||
def exec_command(self, cmd, in_data=None, sudoable=True):
|
||||
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
|
||||
@@ -349,7 +349,6 @@ class Connection(ConnectionBase):
|
||||
|
||||
return (result.status_code, result.std_out, result.std_err)
|
||||
|
||||
|
||||
def exec_command_old(self, cmd, in_data=None, sudoable=True):
|
||||
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
|
||||
cmd_parts = shlex.split(to_bytes(cmd), posix=False)
|
||||
@@ -406,7 +405,7 @@ class Connection(ConnectionBase):
|
||||
in_size = os.path.getsize(to_bytes(in_path, errors='surrogate_or_strict'))
|
||||
offset = 0
|
||||
with open(to_bytes(in_path, errors='surrogate_or_strict'), 'rb') as in_file:
|
||||
for out_data in iter((lambda:in_file.read(buffer_size)), ''):
|
||||
for out_data in iter((lambda: in_file.read(buffer_size)), ''):
|
||||
offset += len(out_data)
|
||||
self._display.vvvvv('WINRM PUT "%s" to "%s" (offset=%d size=%d)' % (in_path, out_path, offset, len(out_data)), host=self._winrm_host)
|
||||
# yes, we're double-encoding over the wire in this case- we want to ensure that the data shipped to the end PS pipeline is still b64-encoded
|
||||
|
||||
@@ -71,8 +71,8 @@ class Connection(ConnectionBase):
|
||||
|
||||
def list_zones(self):
|
||||
process = subprocess.Popen([self.zoneadm_cmd, 'list', '-ip'],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
zones = []
|
||||
for l in process.stdout.readlines():
|
||||
@@ -84,13 +84,13 @@ class Connection(ConnectionBase):
|
||||
return zones
|
||||
|
||||
def get_zone_path(self):
|
||||
#solaris10vm# zoneadm -z cswbuild list -p
|
||||
#-:cswbuild:installed:/zones/cswbuild:479f3c4b-d0c6-e97b-cd04-fd58f2c0238e:native:shared
|
||||
# solaris10vm# zoneadm -z cswbuild list -p
|
||||
# -:cswbuild:installed:/zones/cswbuild:479f3c4b-d0c6-e97b-cd04-fd58f2c0238e:native:shared
|
||||
process = subprocess.Popen([self.zoneadm_cmd, '-z', to_bytes(self.zone), 'list', '-p'],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
#stdout, stderr = p.communicate()
|
||||
# stdout, stderr = p.communicate()
|
||||
path = process.stdout.readlines()[0].split(':')[3]
|
||||
return path + '/root'
|
||||
|
||||
@@ -109,7 +109,7 @@ class Connection(ConnectionBase):
|
||||
compared to exec_command() it looses some niceties like being able to
|
||||
return the process's exit code immediately.
|
||||
'''
|
||||
# Note: zlogin invokes a shell (just like ssh does) so we do not pass
|
||||
# NOTE: zlogin invokes a shell (just like ssh does) so we do not pass
|
||||
# this through /bin/sh -c here. Instead it goes through the shell
|
||||
# that zlogin selects.
|
||||
local_cmd = [self.zlogin_cmd, self.zone, cmd]
|
||||
@@ -117,7 +117,7 @@ class Connection(ConnectionBase):
|
||||
|
||||
display.vvv("EXEC %s" % (local_cmd), host=self.zone)
|
||||
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
return p
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
|
||||
@@ -72,20 +72,24 @@ class AnsibleJSONEncoder(json.JSONEncoder):
|
||||
else:
|
||||
return super(AnsibleJSONEncoder, self).default(o)
|
||||
|
||||
|
||||
def to_yaml(a, *args, **kw):
|
||||
'''Make verbose, human readable yaml'''
|
||||
transformed = yaml.dump(a, Dumper=AnsibleDumper, allow_unicode=True, **kw)
|
||||
return to_text(transformed)
|
||||
|
||||
|
||||
def to_nice_yaml(a, indent=4, *args, **kw):
|
||||
'''Make verbose, human readable yaml'''
|
||||
transformed = yaml.dump(a, Dumper=AnsibleDumper, indent=indent, allow_unicode=True, default_flow_style=False, **kw)
|
||||
return to_text(transformed)
|
||||
|
||||
|
||||
def to_json(a, *args, **kw):
|
||||
''' Convert the value to JSON '''
|
||||
return json.dumps(a, cls=AnsibleJSONEncoder, *args, **kw)
|
||||
|
||||
|
||||
def to_nice_json(a, indent=4, *args, **kw):
|
||||
'''Make verbose, human readable JSON'''
|
||||
# python-2.6's json encoder is buggy (can't encode hostvars)
|
||||
@@ -109,6 +113,7 @@ def to_nice_json(a, indent=4, *args, **kw):
|
||||
# Fallback to the to_json filter
|
||||
return to_json(a, *args, **kw)
|
||||
|
||||
|
||||
def to_bool(a):
|
||||
''' return a bool for the arg '''
|
||||
if a is None or isinstance(a, bool):
|
||||
@@ -119,11 +124,12 @@ def to_bool(a):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def to_datetime(string, format="%Y-%d-%m %H:%M:%S"):
|
||||
return datetime.strptime(string, format)
|
||||
|
||||
|
||||
def strftime(string_format, second = None):
|
||||
def strftime(string_format, second=None):
|
||||
''' return a date string using string. See https://docs.python.org/2/library/time.html#time.strftime for format '''
|
||||
if second is not None:
|
||||
try:
|
||||
@@ -132,13 +138,16 @@ def strftime(string_format, second = None):
|
||||
raise errors.AnsibleFilterError('Invalid value for epoch value (%s)' % second)
|
||||
return time.strftime(string_format, time.localtime(second))
|
||||
|
||||
|
||||
def quote(a):
|
||||
''' return its argument quoted for shell usage '''
|
||||
return shlex_quote(a)
|
||||
|
||||
|
||||
def fileglob(pathname):
|
||||
''' return list of matched regular files for glob '''
|
||||
return [ g for g in glob.glob(pathname) if os.path.isfile(g) ]
|
||||
return [g for g in glob.glob(pathname) if os.path.isfile(g)]
|
||||
|
||||
|
||||
def regex_replace(value='', pattern='', replacement='', ignorecase=False):
|
||||
''' Perform a `re.sub` returning a string '''
|
||||
@@ -152,6 +161,7 @@ def regex_replace(value='', pattern='', replacement='', ignorecase=False):
|
||||
_re = re.compile(pattern, flags=flags)
|
||||
return _re.sub(replacement, value)
|
||||
|
||||
|
||||
def regex_findall(value, regex, multiline=False, ignorecase=False):
|
||||
''' Perform re.findall and return the list of matches '''
|
||||
flags = 0
|
||||
@@ -161,6 +171,7 @@ def regex_findall(value, regex, multiline=False, ignorecase=False):
|
||||
flags |= re.M
|
||||
return re.findall(regex, value, flags)
|
||||
|
||||
|
||||
def regex_search(value, regex, *args, **kwargs):
|
||||
''' Perform re.search and return the list of matches or a backref '''
|
||||
|
||||
@@ -191,6 +202,7 @@ def regex_search(value, regex, *args, **kwargs):
|
||||
items.append(match.group(item))
|
||||
return items
|
||||
|
||||
|
||||
def ternary(value, true_val, false_val):
|
||||
''' value ? true_val : false_val '''
|
||||
if value:
|
||||
@@ -199,16 +211,17 @@ def ternary(value, true_val, false_val):
|
||||
return false_val
|
||||
|
||||
|
||||
|
||||
def regex_escape(string):
|
||||
'''Escape all regular expressions special characters from STRING.'''
|
||||
return re.escape(string)
|
||||
|
||||
|
||||
def from_yaml(data):
|
||||
if isinstance(data, string_types):
|
||||
return yaml.safe_load(data)
|
||||
return data
|
||||
|
||||
|
||||
@environmentfilter
|
||||
def rand(environment, end, start=None, step=None, seed=None):
|
||||
if seed is None:
|
||||
@@ -228,6 +241,7 @@ def rand(environment, end, start=None, step=None, seed=None):
|
||||
else:
|
||||
raise errors.AnsibleFilterError('random can only be used on sequences and integers')
|
||||
|
||||
|
||||
def randomize_list(mylist, seed=None):
|
||||
try:
|
||||
mylist = list(mylist)
|
||||
@@ -240,9 +254,10 @@ def randomize_list(mylist, seed=None):
|
||||
pass
|
||||
return mylist
|
||||
|
||||
|
||||
def get_hash(data, hashtype='sha1'):
|
||||
|
||||
try: # see if hash is supported
|
||||
try: # see if hash is supported
|
||||
h = hashlib.new(hashtype)
|
||||
except:
|
||||
return None
|
||||
@@ -250,14 +265,15 @@ def get_hash(data, hashtype='sha1'):
|
||||
h.update(to_bytes(data, errors='surrogate_then_strict'))
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def get_encrypted_password(password, hashtype='sha512', salt=None):
|
||||
|
||||
# TODO: find a way to construct dynamically from system
|
||||
cryptmethod= {
|
||||
'md5': '1',
|
||||
cryptmethod = {
|
||||
'md5': '1',
|
||||
'blowfish': '2a',
|
||||
'sha256': '5',
|
||||
'sha512': '6',
|
||||
'sha256': '5',
|
||||
'sha512': '6',
|
||||
}
|
||||
|
||||
if hashtype in cryptmethod:
|
||||
@@ -273,7 +289,7 @@ def get_encrypted_password(password, hashtype='sha512', salt=None):
|
||||
if not HAS_PASSLIB:
|
||||
if sys.platform.startswith('darwin'):
|
||||
raise errors.AnsibleFilterError('|password_hash requires the passlib python module to generate password hashes on Mac OS X/Darwin')
|
||||
saltstring = "$%s$%s" % (cryptmethod[hashtype],salt)
|
||||
saltstring = "$%s$%s" % (cryptmethod[hashtype], salt)
|
||||
encrypted = crypt.crypt(password, saltstring)
|
||||
else:
|
||||
if hashtype == 'blowfish':
|
||||
@@ -287,9 +303,11 @@ def get_encrypted_password(password, hashtype='sha512', salt=None):
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def to_uuid(string):
|
||||
return str(uuid.uuid5(UUID_NAMESPACE_ANSIBLE, str(string)))
|
||||
|
||||
|
||||
def mandatory(a):
|
||||
from jinja2.runtime import Undefined
|
||||
|
||||
@@ -298,6 +316,7 @@ def mandatory(a):
|
||||
raise errors.AnsibleFilterError('Mandatory variable not defined.')
|
||||
return a
|
||||
|
||||
|
||||
def combine(*terms, **kwargs):
|
||||
recursive = kwargs.get('recursive', False)
|
||||
if len(kwargs) > 1 or (len(kwargs) == 1 and 'recursive' not in kwargs):
|
||||
@@ -312,6 +331,7 @@ def combine(*terms, **kwargs):
|
||||
else:
|
||||
return dict(itertools.chain(*map(iteritems, terms)))
|
||||
|
||||
|
||||
def comment(text, style='plain', **kw):
|
||||
# Predefined comment types
|
||||
comment_styles = {
|
||||
@@ -394,6 +414,7 @@ def comment(text, style='plain', **kw):
|
||||
str_postfix,
|
||||
str_end)
|
||||
|
||||
|
||||
def extract(item, container, morekeys=None):
|
||||
from jinja2.runtime import Undefined
|
||||
|
||||
@@ -410,6 +431,7 @@ def extract(item, container, morekeys=None):
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def failed(*a, **kw):
|
||||
''' Test if task result yields failed '''
|
||||
item = a[0]
|
||||
@@ -422,26 +444,31 @@ def failed(*a, **kw):
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def success(*a, **kw):
|
||||
''' Test if task result yields success '''
|
||||
return not failed(*a, **kw)
|
||||
|
||||
|
||||
def changed(*a, **kw):
|
||||
''' Test if task result yields changed '''
|
||||
item = a[0]
|
||||
if not isinstance(item, MutableMapping):
|
||||
raise errors.AnsibleFilterError("|changed expects a dictionary")
|
||||
if not 'changed' in item:
|
||||
if 'changed' not in item:
|
||||
changed = False
|
||||
if ('results' in item # some modules return a 'results' key
|
||||
and isinstance(item['results'], MutableSequence)
|
||||
and isinstance(item['results'][0], MutableMapping)):
|
||||
if (
|
||||
'results' in item and # some modules return a 'results' key
|
||||
isinstance(item['results'], MutableSequence) and
|
||||
isinstance(item['results'][0], MutableMapping)
|
||||
):
|
||||
for result in item['results']:
|
||||
changed = changed or result.get('changed', False)
|
||||
else:
|
||||
changed = item.get('changed', False)
|
||||
return changed
|
||||
|
||||
|
||||
def skipped(*a, **kw):
|
||||
''' Test if task result yields skipped '''
|
||||
item = a[0]
|
||||
@@ -504,7 +531,7 @@ class FilterModule(object):
|
||||
'to_nice_yaml': to_nice_yaml,
|
||||
'from_yaml': from_yaml,
|
||||
|
||||
#date
|
||||
# date
|
||||
'to_datetime': to_datetime,
|
||||
|
||||
# path
|
||||
@@ -567,18 +594,18 @@ class FilterModule(object):
|
||||
'extract': extract,
|
||||
|
||||
# failure testing
|
||||
'failed' : failed,
|
||||
'failure' : failed,
|
||||
'success' : success,
|
||||
'succeeded' : success,
|
||||
'failed': failed,
|
||||
'failure': failed,
|
||||
'success': success,
|
||||
'succeeded': success,
|
||||
|
||||
# changed testing
|
||||
'changed' : changed,
|
||||
'change' : changed,
|
||||
'changed': changed,
|
||||
'change': changed,
|
||||
|
||||
# skip testing
|
||||
'skipped' : skipped,
|
||||
'skip' : skipped,
|
||||
'skipped': skipped,
|
||||
'skip': skipped,
|
||||
|
||||
# debug
|
||||
'type_debug': lambda o: o.__class__.__name__,
|
||||
|
||||
@@ -36,7 +36,6 @@ from ansible import errors
|
||||
|
||||
|
||||
# ---- IP address and network query helpers ----
|
||||
|
||||
def _empty_ipaddr_query(v, vtype):
|
||||
# We don't have any query to process, so just check what type the user
|
||||
# expects, and return the IP address in a correct format
|
||||
@@ -46,6 +45,7 @@ def _empty_ipaddr_query(v, vtype):
|
||||
elif vtype == 'network':
|
||||
return str(v)
|
||||
|
||||
|
||||
def _6to4_query(v, vtype, value):
|
||||
if v.version == 4:
|
||||
|
||||
@@ -76,6 +76,7 @@ def _6to4_query(v, vtype, value):
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def _ip_query(v):
|
||||
if v.size == 1:
|
||||
return str(v.ip)
|
||||
@@ -84,22 +85,27 @@ def _ip_query(v):
|
||||
if v.ip != v.network or not v.broadcast:
|
||||
return str(v.ip)
|
||||
|
||||
|
||||
def _gateway_query(v):
|
||||
if v.size > 1:
|
||||
if v.ip != v.network:
|
||||
return str(v.ip) + '/' + str(v.prefixlen)
|
||||
|
||||
|
||||
def _bool_ipaddr_query(v):
|
||||
if v:
|
||||
return True
|
||||
|
||||
|
||||
def _broadcast_query(v):
|
||||
if v.size > 1:
|
||||
return str(v.broadcast)
|
||||
|
||||
|
||||
def _cidr_query(v):
|
||||
return str(v)
|
||||
|
||||
|
||||
def _cidr_lookup_query(v, iplist, value):
|
||||
try:
|
||||
if v in iplist:
|
||||
@@ -107,6 +113,7 @@ def _cidr_lookup_query(v, iplist, value):
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
def _host_query(v):
|
||||
if v.size == 1:
|
||||
return str(v)
|
||||
@@ -114,15 +121,18 @@ def _host_query(v):
|
||||
if v.ip != v.network:
|
||||
return str(v.ip) + '/' + str(v.prefixlen)
|
||||
|
||||
|
||||
def _hostmask_query(v):
|
||||
return str(v.hostmask)
|
||||
|
||||
|
||||
def _int_query(v, vtype):
|
||||
if vtype == 'address':
|
||||
return int(v.ip)
|
||||
elif vtype == 'network':
|
||||
return str(int(v.ip)) + '/' + str(int(v.prefixlen))
|
||||
|
||||
|
||||
def _ipv4_query(v, value):
|
||||
if v.version == 6:
|
||||
try:
|
||||
@@ -132,12 +142,14 @@ def _ipv4_query(v, value):
|
||||
else:
|
||||
return value
|
||||
|
||||
|
||||
def _ipv6_query(v, value):
|
||||
if v.version == 4:
|
||||
return str(v.ipv6())
|
||||
else:
|
||||
return value
|
||||
|
||||
|
||||
def _link_local_query(v, value):
|
||||
v_ip = netaddr.IPAddress(str(v.ip))
|
||||
if v.version == 4:
|
||||
@@ -148,34 +160,42 @@ def _link_local_query(v, value):
|
||||
if ipaddr(str(v_ip), 'fe80::/10'):
|
||||
return value
|
||||
|
||||
|
||||
def _loopback_query(v, value):
|
||||
v_ip = netaddr.IPAddress(str(v.ip))
|
||||
if v_ip.is_loopback():
|
||||
return value
|
||||
|
||||
|
||||
def _multicast_query(v, value):
|
||||
if v.is_multicast():
|
||||
return value
|
||||
|
||||
|
||||
def _net_query(v):
|
||||
if v.size > 1:
|
||||
if v.ip == v.network:
|
||||
return str(v.network) + '/' + str(v.prefixlen)
|
||||
|
||||
|
||||
def _netmask_query(v):
|
||||
return str(v.netmask)
|
||||
|
||||
|
||||
def _network_query(v):
|
||||
if v.size > 1:
|
||||
return str(v.network)
|
||||
|
||||
|
||||
def _prefix_query(v):
|
||||
return int(v.prefixlen)
|
||||
|
||||
|
||||
def _private_query(v, value):
|
||||
if v.is_private():
|
||||
return value
|
||||
|
||||
|
||||
def _public_query(v, value):
|
||||
v_ip = netaddr.IPAddress(str(v.ip))
|
||||
if (v_ip.is_unicast() and not v_ip.is_private() and
|
||||
@@ -183,16 +203,20 @@ def _public_query(v, value):
|
||||
not v_ip.is_hostmask()):
|
||||
return value
|
||||
|
||||
|
||||
def _revdns_query(v):
|
||||
v_ip = netaddr.IPAddress(str(v.ip))
|
||||
return v_ip.reverse_dns
|
||||
|
||||
|
||||
def _size_query(v):
|
||||
return v.size
|
||||
|
||||
|
||||
def _subnet_query(v):
|
||||
return str(v.cidr)
|
||||
|
||||
|
||||
def _type_query(v):
|
||||
if v.size == 1:
|
||||
return 'address'
|
||||
@@ -202,13 +226,16 @@ def _type_query(v):
|
||||
else:
|
||||
return 'network'
|
||||
|
||||
|
||||
def _unicast_query(v, value):
|
||||
if v.is_unicast():
|
||||
return value
|
||||
|
||||
|
||||
def _version_query(v):
|
||||
return v.version
|
||||
|
||||
|
||||
def _wrap_query(v, vtype, value):
|
||||
if v.version == 6:
|
||||
if vtype == 'address':
|
||||
@@ -224,41 +251,48 @@ def _bare_query(v):
|
||||
v.dialect = netaddr.mac_bare
|
||||
return str(v)
|
||||
|
||||
|
||||
def _bool_hwaddr_query(v):
|
||||
if v:
|
||||
return True
|
||||
|
||||
|
||||
def _int_hwaddr_query(v):
|
||||
return int(v)
|
||||
|
||||
|
||||
def _cisco_query(v):
|
||||
v.dialect = netaddr.mac_cisco
|
||||
return str(v)
|
||||
|
||||
|
||||
def _empty_hwaddr_query(v, value):
|
||||
if v:
|
||||
return value
|
||||
|
||||
|
||||
def _linux_query(v):
|
||||
v.dialect = mac_linux
|
||||
return str(v)
|
||||
|
||||
|
||||
def _postgresql_query(v):
|
||||
v.dialect = netaddr.mac_pgsql
|
||||
return str(v)
|
||||
|
||||
|
||||
def _unix_query(v):
|
||||
v.dialect = netaddr.mac_unix
|
||||
return str(v)
|
||||
|
||||
|
||||
def _win_query(v):
|
||||
v.dialect = netaddr.mac_eui48
|
||||
return str(v)
|
||||
|
||||
|
||||
# ---- IP address and network filters ----
|
||||
|
||||
def ipaddr(value, query = '', version = False, alias = 'ipaddr'):
|
||||
def ipaddr(value, query='', version=False, alias='ipaddr'):
|
||||
''' Check if string is an IP address or network and filter it '''
|
||||
|
||||
query_func_extra_args = {
|
||||
@@ -276,7 +310,8 @@ def ipaddr(value, query = '', version = False, alias = 'ipaddr'):
|
||||
'public': ('value',),
|
||||
'unicast': ('value',),
|
||||
'wrap': ('vtype', 'value'),
|
||||
}
|
||||
}
|
||||
|
||||
query_func_map = {
|
||||
'': _empty_ipaddr_query,
|
||||
'6to4': _6to4_query,
|
||||
@@ -316,7 +351,7 @@ def ipaddr(value, query = '', version = False, alias = 'ipaddr'):
|
||||
'v6': _ipv6_query,
|
||||
'version': _version_query,
|
||||
'wrap': _wrap_query,
|
||||
}
|
||||
}
|
||||
|
||||
vtype = None
|
||||
|
||||
@@ -421,7 +456,7 @@ def ipaddr(value, query = '', version = False, alias = 'ipaddr'):
|
||||
# that string is a valid subnet, if so, we can check later if given IP
|
||||
# address/network is inside that specific subnet
|
||||
try:
|
||||
### ?? 6to4 and link-local were True here before. Should they still?
|
||||
# ?? 6to4 and link-local were True here before. Should they still?
|
||||
if query and (query not in query_func_map or query == 'cidr_lookup') and ipaddr(query, 'network'):
|
||||
iplist = netaddr.IPSet([netaddr.IPNetwork(query)])
|
||||
query = 'cidr_lookup'
|
||||
@@ -463,19 +498,19 @@ def ipaddr(value, query = '', version = False, alias = 'ipaddr'):
|
||||
return False
|
||||
|
||||
|
||||
def ipwrap(value, query = ''):
|
||||
def ipwrap(value, query=''):
|
||||
try:
|
||||
if isinstance(value, (list, tuple, types.GeneratorType)):
|
||||
_ret = []
|
||||
for element in value:
|
||||
if ipaddr(element, query, version = False, alias = 'ipwrap'):
|
||||
if ipaddr(element, query, version=False, alias='ipwrap'):
|
||||
_ret.append(ipaddr(element, 'wrap'))
|
||||
else:
|
||||
_ret.append(element)
|
||||
|
||||
return _ret
|
||||
else:
|
||||
_ret = ipaddr(value, query, version = False, alias = 'ipwrap')
|
||||
_ret = ipaddr(value, query, version=False, alias='ipwrap')
|
||||
if _ret:
|
||||
return ipaddr(_ret, 'wrap')
|
||||
else:
|
||||
@@ -485,12 +520,12 @@ def ipwrap(value, query = ''):
|
||||
return value
|
||||
|
||||
|
||||
def ipv4(value, query = ''):
|
||||
return ipaddr(value, query, version = 4, alias = 'ipv4')
|
||||
def ipv4(value, query=''):
|
||||
return ipaddr(value, query, version=4, alias='ipv4')
|
||||
|
||||
|
||||
def ipv6(value, query = ''):
|
||||
return ipaddr(value, query, version = 6, alias = 'ipv6')
|
||||
def ipv6(value, query=''):
|
||||
return ipaddr(value, query, version=6, alias='ipv6')
|
||||
|
||||
|
||||
# Split given subnet into smaller subnets or find out the biggest subnet of
|
||||
@@ -511,7 +546,7 @@ def ipv6(value, query = ''):
|
||||
#
|
||||
# - address | ipsubnet(cidr, index)
|
||||
# returns next indexed subnet which contains given address
|
||||
def ipsubnet(value, query = '', index = 'x'):
|
||||
def ipsubnet(value, query='', index='x'):
|
||||
''' Manipulate IPv4/IPv6 subnets '''
|
||||
|
||||
try:
|
||||
@@ -563,6 +598,7 @@ def ipsubnet(value, query = '', index = 'x'):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
# Returns the nth host within a network described by value.
|
||||
# Usage:
|
||||
#
|
||||
@@ -594,11 +630,12 @@ def nthhost(value, query=''):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
# Returns the SLAAC address within a network for a given HW/MAC address.
|
||||
# Usage:
|
||||
#
|
||||
# - prefix | slaac(mac)
|
||||
def slaac(value, query = ''):
|
||||
def slaac(value, query=''):
|
||||
''' Get the SLAAC address within given network '''
|
||||
try:
|
||||
vtype = ipaddr(value, 'type')
|
||||
@@ -618,7 +655,7 @@ def slaac(value, query = ''):
|
||||
return False
|
||||
|
||||
try:
|
||||
mac = hwaddr(query, alias = 'slaac')
|
||||
mac = hwaddr(query, alias='slaac')
|
||||
|
||||
eui = netaddr.EUI(mac)
|
||||
except:
|
||||
@@ -628,13 +665,13 @@ def slaac(value, query = ''):
|
||||
|
||||
|
||||
# ---- HWaddr / MAC address filters ----
|
||||
|
||||
def hwaddr(value, query = '', alias = 'hwaddr'):
|
||||
def hwaddr(value, query='', alias='hwaddr'):
|
||||
''' Check if string is a HW/MAC address and filter it '''
|
||||
|
||||
query_func_extra_args = {
|
||||
'': ('value',),
|
||||
}
|
||||
}
|
||||
|
||||
query_func_map = {
|
||||
'': _empty_hwaddr_query,
|
||||
'bare': _bare_query,
|
||||
@@ -648,7 +685,7 @@ def hwaddr(value, query = '', alias = 'hwaddr'):
|
||||
'psql': _postgresql_query,
|
||||
'unix': _unix_query,
|
||||
'win': _win_query,
|
||||
}
|
||||
}
|
||||
|
||||
try:
|
||||
v = netaddr.EUI(value)
|
||||
@@ -666,23 +703,26 @@ def hwaddr(value, query = '', alias = 'hwaddr'):
|
||||
|
||||
return False
|
||||
|
||||
def macaddr(value, query = ''):
|
||||
return hwaddr(value, query, alias = 'macaddr')
|
||||
|
||||
def macaddr(value, query=''):
|
||||
return hwaddr(value, query, alias='macaddr')
|
||||
|
||||
|
||||
def _need_netaddr(f_name, *args, **kwargs):
|
||||
raise errors.AnsibleFilterError('The {0} filter requires python-netaddr be'
|
||||
' installed on the ansible controller'.format(f_name))
|
||||
raise errors.AnsibleFilterError('The %s filter requires python-netaddr be '
|
||||
'installed on the ansible controller' % f_name)
|
||||
|
||||
|
||||
def ip4_hex(arg):
|
||||
''' Convert an IPv4 address to Hexadecimal notation '''
|
||||
numbers = list(map(int, arg.split('.')))
|
||||
return '{:02x}{:02x}{:02x}{:02x}'.format(*numbers)
|
||||
|
||||
# ---- Ansible filters ----
|
||||
|
||||
# ---- Ansible filters ----
|
||||
class FilterModule(object):
|
||||
''' IP address and network manipulation filters '''
|
||||
filter_map = {
|
||||
filter_map = {
|
||||
# IP addresses and networks
|
||||
'ipaddr': ipaddr,
|
||||
'ipwrap': ipwrap,
|
||||
|
||||
@@ -39,6 +39,7 @@ def json_query(data, expr):
|
||||
|
||||
return jmespath.search(expr, data)
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
''' Query filter '''
|
||||
|
||||
|
||||
@@ -20,16 +20,16 @@ from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
import math
|
||||
import collections
|
||||
import itertools
|
||||
import math
|
||||
|
||||
from ansible import errors
|
||||
from ansible.module_utils import basic
|
||||
|
||||
|
||||
def unique(a):
|
||||
if isinstance(a,collections.Hashable):
|
||||
if isinstance(a, collections.Hashable):
|
||||
c = set(a)
|
||||
else:
|
||||
c = []
|
||||
@@ -38,38 +38,44 @@ def unique(a):
|
||||
c.append(x)
|
||||
return c
|
||||
|
||||
|
||||
def intersect(a, b):
|
||||
if isinstance(a,collections.Hashable) and isinstance(b,collections.Hashable):
|
||||
if isinstance(a, collections.Hashable) and isinstance(b, collections.Hashable):
|
||||
c = set(a) & set(b)
|
||||
else:
|
||||
c = unique(filter(lambda x: x in b, a))
|
||||
return c
|
||||
|
||||
|
||||
def difference(a, b):
|
||||
if isinstance(a,collections.Hashable) and isinstance(b,collections.Hashable):
|
||||
if isinstance(a, collections.Hashable) and isinstance(b, collections.Hashable):
|
||||
c = set(a) - set(b)
|
||||
else:
|
||||
c = unique(filter(lambda x: x not in b, a))
|
||||
return c
|
||||
|
||||
|
||||
def symmetric_difference(a, b):
|
||||
if isinstance(a,collections.Hashable) and isinstance(b,collections.Hashable):
|
||||
if isinstance(a, collections.Hashable) and isinstance(b, collections.Hashable):
|
||||
c = set(a) ^ set(b)
|
||||
else:
|
||||
c = unique(filter(lambda x: x not in intersect(a,b), union(a,b)))
|
||||
c = unique(filter(lambda x: x not in intersect(a, b), union(a, b)))
|
||||
return c
|
||||
|
||||
|
||||
def union(a, b):
|
||||
if isinstance(a,collections.Hashable) and isinstance(b,collections.Hashable):
|
||||
if isinstance(a, collections.Hashable) and isinstance(b, collections.Hashable):
|
||||
c = set(a) | set(b)
|
||||
else:
|
||||
c = unique(a + b)
|
||||
return c
|
||||
|
||||
|
||||
def min(a):
|
||||
_min = __builtins__.get('min')
|
||||
return _min(a)
|
||||
|
||||
|
||||
def max(a):
|
||||
_max = __builtins__.get('max')
|
||||
return _max(a)
|
||||
@@ -97,7 +103,7 @@ def inversepower(x, base=2):
|
||||
if base == 2:
|
||||
return math.sqrt(x)
|
||||
else:
|
||||
return math.pow(x, 1.0/float(base))
|
||||
return math.pow(x, 1.0 / float(base))
|
||||
except TypeError as e:
|
||||
raise errors.AnsibleFilterError('root() can only be used on numbers: %s' % str(e))
|
||||
|
||||
@@ -109,6 +115,7 @@ def human_readable(size, isbits=False, unit=None):
|
||||
except:
|
||||
raise errors.AnsibleFilterError("human_readable() can't interpret following string: %s" % size)
|
||||
|
||||
|
||||
def human_to_bytes(size, default_unit=None, isbits=False):
|
||||
''' Return bytes count from a human readable string '''
|
||||
try:
|
||||
@@ -116,14 +123,15 @@ def human_to_bytes(size, default_unit=None, isbits=False):
|
||||
except:
|
||||
raise errors.AnsibleFilterError("human_to_bytes() can't interpret following string: %s" % size)
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
''' Ansible math jinja2 filters '''
|
||||
|
||||
def filters(self):
|
||||
filters = {
|
||||
# general math
|
||||
'min' : min,
|
||||
'max' : max,
|
||||
'min': min,
|
||||
'max': max,
|
||||
|
||||
# exponents and logarithms
|
||||
'log': logarithm,
|
||||
@@ -131,7 +139,7 @@ class FilterModule(object):
|
||||
'root': inversepower,
|
||||
|
||||
# set theory
|
||||
'unique' : unique,
|
||||
'unique': unique,
|
||||
'intersect': intersect,
|
||||
'difference': difference,
|
||||
'symmetric_difference': symmetric_difference,
|
||||
@@ -142,8 +150,8 @@ class FilterModule(object):
|
||||
'combinations': itertools.combinations,
|
||||
|
||||
# computer theory
|
||||
'human_readable' : human_readable,
|
||||
'human_to_bytes' : human_to_bytes,
|
||||
'human_readable': human_readable,
|
||||
'human_to_bytes': human_to_bytes,
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -85,8 +85,7 @@ class BaseInventoryPlugin(object):
|
||||
def _compose(self, template, variables):
|
||||
''' helper method for pluigns to compose variables for Ansible based on jinja2 expression and inventory vars'''
|
||||
t = Templar(loader=self.loader, variables=variables)
|
||||
return t.do_template('%s%s%s' % (t.environment.variable_start_string,template,t.environment.variable_end_string), disable_lookups=True)
|
||||
|
||||
return t.do_template('%s%s%s' % (t.environment.variable_start_string, template, t.environment.variable_end_string), disable_lookups=True)
|
||||
|
||||
|
||||
class BaseFileInventoryPlugin(BaseInventoryPlugin):
|
||||
@@ -100,8 +99,8 @@ class BaseFileInventoryPlugin(BaseInventoryPlugin):
|
||||
super(BaseFileInventoryPlugin, self).__init__(cache=None)
|
||||
|
||||
|
||||
#### Helper methods ####
|
||||
def detect_range(line = None):
|
||||
# Helper methods
|
||||
def detect_range(line=None):
|
||||
'''
|
||||
A helper function that checks a given host line to see if it contains
|
||||
a range pattern described in the docstring above.
|
||||
@@ -110,7 +109,8 @@ def detect_range(line = None):
|
||||
'''
|
||||
return '[' in line
|
||||
|
||||
def expand_hostname_range(line = None):
|
||||
|
||||
def expand_hostname_range(line=None):
|
||||
'''
|
||||
A helper function that expands a given line that contains a pattern
|
||||
specified in top docstring, and returns a list that consists of the
|
||||
@@ -137,7 +137,7 @@ def expand_hostname_range(line = None):
|
||||
# - also add an optional third parameter which contains the step. (Default: 1)
|
||||
# so range can be [01:10:2] -> 01 03 05 07 09
|
||||
|
||||
(head, nrange, tail) = line.replace('[','|',1).replace(']','|',1).split('|')
|
||||
(head, nrange, tail) = line.replace('[', '|', 1).replace(']', '|', 1).split('|')
|
||||
bounds = nrange.split(":")
|
||||
if len(bounds) != 2 and len(bounds) != 3:
|
||||
raise AnsibleError("host range must be begin:end or begin:end:step")
|
||||
@@ -152,10 +152,13 @@ def expand_hostname_range(line = None):
|
||||
if not end:
|
||||
raise AnsibleError("host range must specify end value")
|
||||
if beg[0] == '0' and len(beg) > 1:
|
||||
rlen = len(beg) # range length formatting hint
|
||||
rlen = len(beg) # range length formatting hint
|
||||
if rlen != len(end):
|
||||
raise AnsibleError("host range must specify equal-length begin and end formats")
|
||||
fill = lambda _: str(_).zfill(rlen) # range sequence
|
||||
|
||||
def fill(x):
|
||||
return str(x).zfill(rlen) # range sequence
|
||||
|
||||
else:
|
||||
fill = str
|
||||
|
||||
@@ -164,17 +167,16 @@ def expand_hostname_range(line = None):
|
||||
i_end = string.ascii_letters.index(end)
|
||||
if i_beg > i_end:
|
||||
raise AnsibleError("host range must have begin <= end")
|
||||
seq = list(string.ascii_letters[i_beg:i_end+1:int(step)])
|
||||
seq = list(string.ascii_letters[i_beg:i_end + 1:int(step)])
|
||||
except ValueError: # not an alpha range
|
||||
seq = range(int(beg), int(end)+1, int(step))
|
||||
seq = range(int(beg), int(end) + 1, int(step))
|
||||
|
||||
for rseq in seq:
|
||||
hname = ''.join((head, fill(rseq), tail))
|
||||
|
||||
if detect_range(hname):
|
||||
all_hosts.extend( expand_hostname_range( hname ) )
|
||||
all_hosts.extend(expand_hostname_range(hname))
|
||||
else:
|
||||
all_hosts.append(hname)
|
||||
|
||||
return all_hosts
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ class InventoryModule(BaseFileInventoryPlugin):
|
||||
for line in b_data.splitlines():
|
||||
if line and line[0] in self.b_COMMENT_MARKERS:
|
||||
# Replace is okay for comment lines
|
||||
#data.append(to_text(line, errors='surrogate_then_replace'))
|
||||
# data.append(to_text(line, errors='surrogate_then_replace'))
|
||||
# Currently we only need these lines for accurate lineno in errors
|
||||
data.append(u'')
|
||||
else:
|
||||
@@ -141,7 +141,6 @@ class InventoryModule(BaseFileInventoryPlugin):
|
||||
except Exception as e:
|
||||
raise AnsibleParserError(e)
|
||||
|
||||
|
||||
def _raise_error(self, message):
|
||||
raise AnsibleError("%s:%d: " % (self._filename, self.lineno) + message)
|
||||
|
||||
@@ -281,7 +280,7 @@ class InventoryModule(BaseFileInventoryPlugin):
|
||||
|
||||
self._raise_error("Expected key=value, got: %s" % (line))
|
||||
|
||||
def _parse_host_definition(self, line ):
|
||||
def _parse_host_definition(self, line):
|
||||
'''
|
||||
Takes a single line and tries to parse it as a host definition. Returns
|
||||
a list of Hosts if successful, or raises an error.
|
||||
|
||||
@@ -80,7 +80,7 @@ class InventoryModule(BaseInventoryPlugin):
|
||||
# Support inventory scripts that are not prefixed with some
|
||||
# path information but happen to be in the current working
|
||||
# directory when '.' is not in PATH.
|
||||
cmd = [ path, "--list" ]
|
||||
cmd = [path, "--list"]
|
||||
|
||||
try:
|
||||
cache_key = self.get_cache_prefix(path)
|
||||
@@ -95,7 +95,7 @@ class InventoryModule(BaseInventoryPlugin):
|
||||
|
||||
path = to_native(path)
|
||||
if stderr:
|
||||
err = to_native(stderr) + "\n"
|
||||
err = to_native(stderr) + "\n"
|
||||
|
||||
if sp.returncode != 0:
|
||||
raise AnsibleError("Inventory script (%s) had an execution error: %s " % (path, err))
|
||||
@@ -140,14 +140,13 @@ class InventoryModule(BaseInventoryPlugin):
|
||||
try:
|
||||
got = processed.get(host, {})
|
||||
except AttributeError as e:
|
||||
raise AnsibleError("Improperly formatted host information for %s: %s" % (host,to_native(e)))
|
||||
raise AnsibleError("Improperly formatted host information for %s: %s" % (host, to_native(e)))
|
||||
|
||||
self.populate_host_vars(host, got, group)
|
||||
|
||||
except Exception as e:
|
||||
raise AnsibleParserError(to_native(e))
|
||||
|
||||
|
||||
def _parse_group(self, group, data):
|
||||
|
||||
self.inventory.add_group(group)
|
||||
@@ -155,7 +154,7 @@ class InventoryModule(BaseInventoryPlugin):
|
||||
if not isinstance(data, dict):
|
||||
data = {'hosts': data}
|
||||
# is not those subkeys, then simplified syntax, host with vars
|
||||
elif not any(k in data for k in ('hosts','vars','children')):
|
||||
elif not any(k in data for k in ('hosts', 'vars', 'children')):
|
||||
data = {'hosts': [group], 'vars': data}
|
||||
|
||||
if 'hosts' in data:
|
||||
|
||||
@@ -71,6 +71,7 @@ from ansible.module_utils._text import to_bytes, to_text
|
||||
from ansible.parsing.utils.addresses import parse_address
|
||||
from ansible.plugins.inventory import BaseFileInventoryPlugin, detect_range, expand_hostname_range
|
||||
|
||||
|
||||
class InventoryModule(BaseFileInventoryPlugin):
|
||||
|
||||
NAME = 'yaml'
|
||||
@@ -120,7 +121,7 @@ class InventoryModule(BaseFileInventoryPlugin):
|
||||
self.inventory.add_group(group)
|
||||
|
||||
if isinstance(group_data, dict):
|
||||
#make sure they are dicts
|
||||
# make sure they are dicts
|
||||
for section in ['vars', 'children', 'hosts']:
|
||||
if section in group_data and isinstance(group_data[section], string_types):
|
||||
group_data[section] = {group_data[section]: None}
|
||||
@@ -178,4 +179,4 @@ class InventoryModule(BaseFileInventoryPlugin):
|
||||
'''
|
||||
Compiles the regular expressions required to parse the inventory and stores them in self.patterns.
|
||||
'''
|
||||
self.patterns['groupname'] = re.compile( r'''^[A-Za-z_][A-Za-z0-9_]*$''')
|
||||
self.patterns['groupname'] = re.compile(r'''^[A-Za-z_][A-Za-z0-9_]*$''')
|
||||
|
||||
@@ -60,7 +60,7 @@ class LookupBase(with_metaclass(ABCMeta, object)):
|
||||
results = []
|
||||
for x in a:
|
||||
for y in b:
|
||||
results.append(LookupBase._flatten([x,y]))
|
||||
results.append(LookupBase._flatten([x, y]))
|
||||
return results
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -51,6 +51,7 @@ from ansible.errors import AnsibleError
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.utils.listify import listify_lookup_plugin_terms
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
"""
|
||||
Create the cartesian product of lists
|
||||
@@ -79,4 +80,3 @@ class LookupModule(LookupBase):
|
||||
raise AnsibleError("with_cartesian requires at least one element in each list")
|
||||
|
||||
return [self._flatten(x) for x in product(*my_list)]
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ class CSVRecoder:
|
||||
def next(self):
|
||||
return self.reader.next().encode("utf-8")
|
||||
|
||||
|
||||
class CSVReader:
|
||||
"""
|
||||
A CSV reader which will iterate over lines in the CSV file "f",
|
||||
@@ -56,6 +57,7 @@ class CSVReader:
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def read_csv(self, filename, key, delimiter, encoding='utf-8', dflt=None, col=1):
|
||||
@@ -81,11 +83,11 @@ class LookupModule(LookupBase):
|
||||
key = params[0]
|
||||
|
||||
paramvals = {
|
||||
'col' : "1", # column to return
|
||||
'default' : None,
|
||||
'delimiter' : "TAB",
|
||||
'file' : 'ansible.csv',
|
||||
'encoding' : 'utf-8',
|
||||
'col': "1", # column to return
|
||||
'default': None,
|
||||
'delimiter': "TAB",
|
||||
'file': 'ansible.csv',
|
||||
'encoding': 'utf-8',
|
||||
}
|
||||
|
||||
# parameters specified?
|
||||
|
||||
@@ -22,6 +22,7 @@ import collections
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def run(self, terms, variables=None, **kwargs):
|
||||
|
||||
@@ -29,11 +29,12 @@ try:
|
||||
import dns.reversename
|
||||
import dns.rdataclass
|
||||
from dns.rdatatype import (A, AAAA, CNAME, DLV, DNAME, DNSKEY, DS, HINFO, LOC,
|
||||
MX, NAPTR, NS, NSEC3PARAM, PTR, RP, SOA, SPF, SRV, SSHFP, TLSA, TXT)
|
||||
MX, NAPTR, NS, NSEC3PARAM, PTR, RP, SOA, SPF, SRV, SSHFP, TLSA, TXT)
|
||||
HAVE_DNS = True
|
||||
except ImportError:
|
||||
HAVE_DNS = False
|
||||
|
||||
|
||||
def make_rdata_dict(rdata):
|
||||
''' While the 'dig' lookup plugin supports anything which dnspython supports
|
||||
out of the box, the following supported_types list describes which
|
||||
@@ -42,28 +43,28 @@ def make_rdata_dict(rdata):
|
||||
Note: adding support for RRSIG is hard work. :)
|
||||
'''
|
||||
supported_types = {
|
||||
A : ['address'],
|
||||
AAAA : ['address'],
|
||||
CNAME : ['target'],
|
||||
DNAME : ['target'],
|
||||
DLV : ['algorithm', 'digest_type', 'key_tag', 'digest'],
|
||||
DNSKEY : ['flags', 'algorithm', 'protocol', 'key'],
|
||||
DS : ['algorithm', 'digest_type', 'key_tag', 'digest'],
|
||||
HINFO : ['cpu', 'os'],
|
||||
LOC : ['latitude', 'longitude', 'altitude', 'size', 'horizontal_precision', 'vertical_precision'],
|
||||
MX : ['preference', 'exchange'],
|
||||
NAPTR : ['order', 'preference', 'flags', 'service', 'regexp', 'replacement'],
|
||||
NS : ['target'],
|
||||
NSEC3PARAM : ['algorithm', 'flags', 'iterations', 'salt'],
|
||||
PTR : ['target'],
|
||||
RP : ['mbox', 'txt'],
|
||||
# RRSIG : ['algorithm', 'labels', 'original_ttl', 'expiration', 'inception', 'signature'],
|
||||
SOA : ['mname', 'rname', 'serial', 'refresh', 'retry', 'expire', 'minimum'],
|
||||
SPF : ['strings'],
|
||||
SRV : ['priority', 'weight', 'port', 'target'],
|
||||
SSHFP : ['algorithm', 'fp_type', 'fingerprint'],
|
||||
TLSA : ['usage', 'selector', 'mtype', 'cert'],
|
||||
TXT : ['strings'],
|
||||
A: ['address'],
|
||||
AAAA: ['address'],
|
||||
CNAME: ['target'],
|
||||
DNAME: ['target'],
|
||||
DLV: ['algorithm', 'digest_type', 'key_tag', 'digest'],
|
||||
DNSKEY: ['flags', 'algorithm', 'protocol', 'key'],
|
||||
DS: ['algorithm', 'digest_type', 'key_tag', 'digest'],
|
||||
HINFO: ['cpu', 'os'],
|
||||
LOC: ['latitude', 'longitude', 'altitude', 'size', 'horizontal_precision', 'vertical_precision'],
|
||||
MX: ['preference', 'exchange'],
|
||||
NAPTR: ['order', 'preference', 'flags', 'service', 'regexp', 'replacement'],
|
||||
NS: ['target'],
|
||||
NSEC3PARAM: ['algorithm', 'flags', 'iterations', 'salt'],
|
||||
PTR: ['target'],
|
||||
RP: ['mbox', 'txt'],
|
||||
# RRSIG: ['algorithm', 'labels', 'original_ttl', 'expiration', 'inception', 'signature'],
|
||||
SOA: ['mname', 'rname', 'serial', 'refresh', 'retry', 'expire', 'minimum'],
|
||||
SPF: ['strings'],
|
||||
SRV: ['priority', 'weight', 'port', 'target'],
|
||||
SSHFP: ['algorithm', 'fp_type', 'fingerprint'],
|
||||
TLSA: ['usage', 'selector', 'mtype', 'cert'],
|
||||
TXT: ['strings'],
|
||||
}
|
||||
|
||||
rd = {}
|
||||
@@ -71,7 +72,7 @@ def make_rdata_dict(rdata):
|
||||
if rdata.rdtype in supported_types:
|
||||
fields = supported_types[rdata.rdtype]
|
||||
for f in fields:
|
||||
val = rdata.__getattribute__(f)
|
||||
val = rdata.__getattribute__(f)
|
||||
|
||||
if isinstance(val, dns.name.Name):
|
||||
val = dns.name.Name.to_text(val)
|
||||
@@ -89,11 +90,11 @@ def make_rdata_dict(rdata):
|
||||
if rdata.rdtype == TLSA and f == 'cert':
|
||||
val = dns.rdata._hexify(rdata.cert).replace(' ', '')
|
||||
|
||||
|
||||
rd[f] = val
|
||||
rd[f] = val
|
||||
|
||||
return rd
|
||||
|
||||
|
||||
# ==============================================================
|
||||
# dig: Lookup DNS records
|
||||
#
|
||||
@@ -127,8 +128,8 @@ class LookupModule(LookupBase):
|
||||
myres.use_edns(0, ednsflags=dns.flags.DO, payload=edns_size)
|
||||
|
||||
domain = None
|
||||
qtype = 'A'
|
||||
flat = True
|
||||
qtype = 'A'
|
||||
flat = True
|
||||
rdclass = dns.rdataclass.from_text('IN')
|
||||
|
||||
for t in terms:
|
||||
@@ -201,10 +202,10 @@ class LookupModule(LookupBase):
|
||||
else:
|
||||
try:
|
||||
rd = make_rdata_dict(rdata)
|
||||
rd['owner'] = answers.canonical_name.to_text()
|
||||
rd['type'] = dns.rdatatype.to_text(rdata.rdtype)
|
||||
rd['ttl'] = answers.rrset.ttl
|
||||
rd['class'] = dns.rdataclass.to_text(rdata.rdclass)
|
||||
rd['owner'] = answers.canonical_name.to_text()
|
||||
rd['type'] = dns.rdatatype.to_text(rdata.rdtype)
|
||||
rd['ttl'] = answers.rrset.ttl
|
||||
rd['class'] = dns.rdataclass.to_text(rdata.rdclass)
|
||||
|
||||
ret.append(rd)
|
||||
except Exception as e:
|
||||
|
||||
@@ -17,17 +17,18 @@
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
HAVE_DNS=False
|
||||
HAVE_DNS = False
|
||||
try:
|
||||
import dns.resolver
|
||||
from dns.exception import DNSException
|
||||
HAVE_DNS=True
|
||||
HAVE_DNS = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
|
||||
|
||||
# ==============================================================
|
||||
# DNSTXT: DNS TXT records
|
||||
@@ -63,4 +64,3 @@ class LookupModule(LookupBase):
|
||||
ret.append(''.join(string))
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import os
|
||||
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def run(self, terms, variables, **kwargs):
|
||||
|
||||
@@ -74,12 +74,13 @@ ANSIBLE_ETCD_VERSION = 'v1'
|
||||
if os.getenv('ANSIBLE_ETCD_VERSION') is not None:
|
||||
ANSIBLE_ETCD_VERSION = os.environ['ANSIBLE_ETCD_VERSION']
|
||||
|
||||
|
||||
class Etcd:
|
||||
def __init__(self, url=ANSIBLE_ETCD_URL, version=ANSIBLE_ETCD_VERSION,
|
||||
validate_certs=True):
|
||||
self.url = url
|
||||
self.version = version
|
||||
self.baseurl = '%s/%s/keys' % (self.url,self.version)
|
||||
self.baseurl = '%s/%s/keys' % (self.url, self.version)
|
||||
self.validate_certs = validate_certs
|
||||
|
||||
def get(self, key):
|
||||
@@ -111,6 +112,7 @@ class Etcd:
|
||||
|
||||
return value
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def run(self, terms, variables, **kwargs):
|
||||
|
||||
@@ -22,10 +22,10 @@ import pwd
|
||||
import grp
|
||||
import stat
|
||||
|
||||
HAVE_SELINUX=False
|
||||
HAVE_SELINUX = False
|
||||
try:
|
||||
import selinux
|
||||
HAVE_SELINUX=True
|
||||
HAVE_SELINUX = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
@@ -38,6 +38,7 @@ except ImportError:
|
||||
from ansible.utils.display import Display
|
||||
display = Display()
|
||||
|
||||
|
||||
# If selinux fails to find a default, return an array of None
|
||||
def selinux_context(path):
|
||||
context = [None, None, None, None]
|
||||
@@ -119,7 +120,7 @@ class LookupModule(LookupBase):
|
||||
relpath = os.path.relpath(os.path.join(root, entry), path)
|
||||
|
||||
# Skip if relpath was already processed (from another root)
|
||||
if relpath not in [ entry['path'] for entry in ret ]:
|
||||
if relpath not in [entry['path'] for entry in ret]:
|
||||
props = file_props(path, relpath)
|
||||
if props is not None:
|
||||
ret.append(props)
|
||||
|
||||
@@ -34,11 +34,11 @@ __metaclass__ = type
|
||||
# first file found with os.path.exists() is returned
|
||||
# no file matches raises ansibleerror
|
||||
# EXAMPLES
|
||||
# - name: copy first existing file found to /some/file
|
||||
# action: copy src=$item dest=/some/file
|
||||
# with_first_found:
|
||||
# - files: foo ${inventory_hostname} bar
|
||||
# paths: /tmp/production /tmp/staging
|
||||
# - name: copy first existing file found to /some/file
|
||||
# action: copy src=$item dest=/some/file
|
||||
# with_first_found:
|
||||
# - files: foo ${inventory_hostname} bar
|
||||
# paths: /tmp/production /tmp/staging
|
||||
|
||||
# that will look for files in this order:
|
||||
# /tmp/production/foo
|
||||
@@ -48,10 +48,10 @@ __metaclass__ = type
|
||||
# ${inventory_hostname}
|
||||
# bar
|
||||
|
||||
# - name: copy first existing file found to /some/file
|
||||
# action: copy src=$item dest=/some/file
|
||||
# with_first_found:
|
||||
# - files: /some/place/foo ${inventory_hostname} /some/place/else
|
||||
# - name: copy first existing file found to /some/file
|
||||
# action: copy src=$item dest=/some/file
|
||||
# with_first_found:
|
||||
# - files: /some/place/foo ${inventory_hostname} /some/place/else
|
||||
|
||||
# that will look for files in this order:
|
||||
# /some/place/foo
|
||||
@@ -59,47 +59,47 @@ __metaclass__ = type
|
||||
# /some/place/else
|
||||
|
||||
# example - including tasks:
|
||||
# tasks:
|
||||
# - include: $item
|
||||
# with_first_found:
|
||||
# - files: generic
|
||||
# paths: tasks/staging tasks/production
|
||||
# tasks:
|
||||
# - include: $item
|
||||
# with_first_found:
|
||||
# - files: generic
|
||||
# paths: tasks/staging tasks/production
|
||||
# this will include the tasks in the file generic where it is found first (staging or production)
|
||||
|
||||
# example simple file lists
|
||||
#tasks:
|
||||
#- name: first found file
|
||||
# action: copy src=$item dest=/etc/file.cfg
|
||||
# with_first_found:
|
||||
# - files: foo.${inventory_hostname} foo
|
||||
# tasks:
|
||||
# - name: first found file
|
||||
# action: copy src=$item dest=/etc/file.cfg
|
||||
# with_first_found:
|
||||
# - files: foo.${inventory_hostname} foo
|
||||
|
||||
|
||||
# example skipping if no matched files
|
||||
# First_found also offers the ability to control whether or not failing
|
||||
# to find a file returns an error or not
|
||||
#
|
||||
#- name: first found file - or skip
|
||||
# action: copy src=$item dest=/etc/file.cfg
|
||||
# with_first_found:
|
||||
# - files: foo.${inventory_hostname}
|
||||
# skip: true
|
||||
# - name: first found file - or skip
|
||||
# action: copy src=$item dest=/etc/file.cfg
|
||||
# with_first_found:
|
||||
# - files: foo.${inventory_hostname}
|
||||
# skip: true
|
||||
|
||||
# example a role with default configuration and configuration per host
|
||||
# you can set multiple terms with their own files and paths to look through.
|
||||
# consider a role that sets some configuration per host falling back on a default config.
|
||||
#
|
||||
#- name: some configuration template
|
||||
# template: src={{ item }} dest=/etc/file.cfg mode=0444 owner=root group=root
|
||||
# with_first_found:
|
||||
# - files:
|
||||
# - ${inventory_hostname}/etc/file.cfg
|
||||
# paths:
|
||||
# - ../../../templates.overwrites
|
||||
# - ../../../templates
|
||||
# - files:
|
||||
# - etc/file.cfg
|
||||
# paths:
|
||||
# - templates
|
||||
# - name: some configuration template
|
||||
# template: src={{ item }} dest=/etc/file.cfg mode=0444 owner=root group=root
|
||||
# with_first_found:
|
||||
# - files:
|
||||
# - ${inventory_hostname}/etc/file.cfg
|
||||
# paths:
|
||||
# - ../../../templates.overwrites
|
||||
# - ../../../templates
|
||||
# - files:
|
||||
# - etc/file.cfg
|
||||
# paths:
|
||||
# - templates
|
||||
|
||||
# the above will return an empty list if the files cannot be found at all
|
||||
# if skip is unspecificed or if it is set to false then it will return a list
|
||||
@@ -110,13 +110,13 @@ __metaclass__ = type
|
||||
# first_available_file with with_first_found and leave the file listing in place
|
||||
#
|
||||
#
|
||||
# - name: with_first_found like first_available_file
|
||||
# action: copy src=$item dest=/tmp/faftest
|
||||
# with_first_found:
|
||||
# - ../files/foo
|
||||
# - ../files/bar
|
||||
# - ../files/baz
|
||||
# ignore_errors: true
|
||||
# - name: with_first_found like first_available_file
|
||||
# action: copy src=$item dest=/tmp/faftest
|
||||
# with_first_found:
|
||||
# - ../files/foo
|
||||
# - ../files/bar
|
||||
# - ../files/baz
|
||||
# ignore_errors: true
|
||||
|
||||
import os
|
||||
|
||||
@@ -145,7 +145,7 @@ class LookupModule(LookupBase):
|
||||
if isinstance(term, dict):
|
||||
files = term.get('files', [])
|
||||
paths = term.get('paths', [])
|
||||
skip = boolean(term.get('skip', False))
|
||||
skip = boolean(term.get('skip', False))
|
||||
|
||||
filelist = files
|
||||
if isinstance(files, string_types):
|
||||
@@ -191,4 +191,3 @@ class LookupModule(LookupBase):
|
||||
else:
|
||||
raise AnsibleLookupError("No file was found when using with_first_found. Use the 'skip: true' option to allow this task to be skipped if no "
|
||||
"files are found")
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ class LookupModule(LookupBase):
|
||||
# make sure term is not a list of one (list of one..) item
|
||||
# return the final non list item if so
|
||||
|
||||
if isinstance(term,list) and len(term) == 1:
|
||||
if isinstance(term, list) and len(term) == 1:
|
||||
term = term[0]
|
||||
if isinstance(term,list):
|
||||
if isinstance(term, list):
|
||||
term = self._check_list_of_one_list(term)
|
||||
|
||||
return term
|
||||
@@ -50,7 +50,7 @@ class LookupModule(LookupBase):
|
||||
# convert a variable to a list
|
||||
term2 = listify_lookup_plugin_terms(term, templar=self._templar, loader=self._loader)
|
||||
# but avoid converting a plain string to a list of one string
|
||||
if term2 != [ term ]:
|
||||
if term2 != [term]:
|
||||
term = term2
|
||||
|
||||
if isinstance(term, list):
|
||||
@@ -62,11 +62,9 @@ class LookupModule(LookupBase):
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def run(self, terms, variables, **kwargs):
|
||||
|
||||
if not isinstance(terms, list):
|
||||
raise AnsibleError("with_flattened expects a list")
|
||||
|
||||
return self._do_flatten(terms, variables)
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
# necessarily be an error if a bad endpoint is specified.
|
||||
#
|
||||
# Requires hvac library. Install with pip.
|
||||
#
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
@@ -46,6 +45,7 @@ ANSIBLE_HASHI_VAULT_ADDR = 'http://127.0.0.1:8200'
|
||||
if os.getenv('VAULT_ADDR') is not None:
|
||||
ANSIBLE_HASHI_VAULT_ADDR = os.environ['VAULT_ADDR']
|
||||
|
||||
|
||||
class HashiVault:
|
||||
def __init__(self, **kwargs):
|
||||
try:
|
||||
@@ -62,7 +62,7 @@ class HashiVault:
|
||||
|
||||
s_f = s.split(':')
|
||||
self.secret = s_f[0]
|
||||
if len(s_f)>=2:
|
||||
if len(s_f) >= 2:
|
||||
self.secret_field = s_f[1]
|
||||
else:
|
||||
self.secret_field = 'value'
|
||||
@@ -108,7 +108,7 @@ class HashiVault:
|
||||
if data is None:
|
||||
raise AnsibleError("The secret %s doesn't seem to exist" % self.secret)
|
||||
|
||||
if self.secret_field=='': # secret was specified with trailing ':'
|
||||
if self.secret_field == '': # secret was specified with trailing ':'
|
||||
return data['data']
|
||||
|
||||
if self.secret_field not in data['data']:
|
||||
@@ -153,4 +153,3 @@ class LookupModule(LookupBase):
|
||||
ret.append(value)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ __metaclass__ = type
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def __init__(self, basedir=None, **kwargs):
|
||||
@@ -32,4 +33,3 @@ class LookupModule(LookupBase):
|
||||
|
||||
items = self._flatten(terms)
|
||||
return list(zip(range(len(items)), items))
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ def _parse_params(term):
|
||||
params[k] = ''
|
||||
|
||||
thiskey = 'key'
|
||||
for idp,phrase in enumerate(term.split()):
|
||||
for idp, phrase in enumerate(term.split()):
|
||||
for k in keys:
|
||||
if ('%s=' % k) in phrase:
|
||||
thiskey = k
|
||||
@@ -81,7 +81,7 @@ class LookupModule(LookupBase):
|
||||
|
||||
basedir = self.get_basedir(variables)
|
||||
self.basedir = basedir
|
||||
self.cp = configparser.ConfigParser()
|
||||
self.cp = configparser.ConfigParser()
|
||||
|
||||
ret = []
|
||||
for term in terms:
|
||||
@@ -89,11 +89,11 @@ class LookupModule(LookupBase):
|
||||
key = params[0]
|
||||
|
||||
paramvals = {
|
||||
'file' : 'ansible.ini',
|
||||
're' : False,
|
||||
'default' : None,
|
||||
'section' : "global",
|
||||
'type' : "ini",
|
||||
'file': 'ansible.ini',
|
||||
're': False,
|
||||
'default': None,
|
||||
'section': "global",
|
||||
'type': "ini",
|
||||
}
|
||||
|
||||
# parameters specified?
|
||||
|
||||
@@ -19,14 +19,15 @@
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.inventory.manager import split_host_pattern, order_patterns
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def get_hosts(self, variables, pattern):
|
||||
hosts = []
|
||||
if pattern[0] in ('!','&'):
|
||||
if pattern[0] in ('!', '&'):
|
||||
obj = pattern[1:]
|
||||
else:
|
||||
obj = pattern
|
||||
@@ -47,9 +48,9 @@ class LookupModule(LookupBase):
|
||||
for p in patterns:
|
||||
that = self.get_hosts(variables, p)
|
||||
if p.startswith("!"):
|
||||
host_list = [ h for h in host_list if h not in that]
|
||||
host_list = [h for h in host_list if h not in that]
|
||||
elif p.startswith("&"):
|
||||
host_list = [ h for h in host_list if h in that ]
|
||||
host_list = [h for h in host_list if h in that]
|
||||
else:
|
||||
host_list.extend(that)
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ __metaclass__ = type
|
||||
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def run(self, terms, **kwargs):
|
||||
|
||||
return self._flatten(terms)
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
'''
|
||||
@@ -56,20 +54,20 @@ except ImportError:
|
||||
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def run(self, terms, **kwargs):
|
||||
if not HAS_KEYRING:
|
||||
raise AnsibleError(u"Can't LOOKUP(keyring): missing required python library 'keyring'")
|
||||
|
||||
display.vvvv(u"keyring: %s" % keyring.get_keyring() )
|
||||
display.vvvv(u"keyring: %s" % keyring.get_keyring())
|
||||
ret = []
|
||||
for term in terms:
|
||||
(servicename, username) = (term.split()[0], term.split()[1])
|
||||
display.vvvv(u"username: %s, servicename: %s " %(username,servicename))
|
||||
password = keyring.get_password(servicename,username)
|
||||
display.vvvv(u"username: %s, servicename: %s " % (username, servicename))
|
||||
password = keyring.get_password(servicename, username)
|
||||
if password is None:
|
||||
raise AnsibleError(u"servicename: %s for user %s not found" % (servicename, username))
|
||||
ret.append(password.rstrip())
|
||||
return ret
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ from ansible.errors import AnsibleError
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.module_utils._text import to_text
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def run(self, terms, variables, **kwargs):
|
||||
|
||||
@@ -21,6 +21,7 @@ __metaclass__ = type
|
||||
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def run(self, terms, **kwargs):
|
||||
|
||||
@@ -134,7 +134,7 @@ class LookupModule(LookupBase):
|
||||
item[1] = ASCENDING
|
||||
elif sort_order == "DESCENDING":
|
||||
item[1] = DESCENDING
|
||||
#else the user knows what s/he is doing and we won't predict. PyMongo will return an error if necessary
|
||||
# else the user knows what s/he is doing and we won't predict. PyMongo will return an error if necessary
|
||||
|
||||
def convert_mongo_result_to_valid_json(self, result):
|
||||
if result is None:
|
||||
@@ -151,17 +151,16 @@ class LookupModule(LookupBase):
|
||||
elif isinstance(result, dict):
|
||||
new_dict = {}
|
||||
for key in result.keys():
|
||||
value = result[key] # python2 and 3 compatible....
|
||||
value = result[key] # python2 and 3 compatible....
|
||||
new_dict[key] = self.convert_mongo_result_to_valid_json(value)
|
||||
return new_dict
|
||||
elif isinstance(result, datetime.datetime):
|
||||
#epoch
|
||||
return (result - datetime.datetime(1970,1,1)).total_seconds()
|
||||
# epoch
|
||||
return (result - datetime.datetime(1970, 1, 1)). total_seconds()
|
||||
else:
|
||||
#failsafe
|
||||
# failsafe
|
||||
return "{}".format(result)
|
||||
|
||||
|
||||
def run(self, terms, variables, **kwargs):
|
||||
|
||||
ret = []
|
||||
@@ -226,7 +225,7 @@ class LookupModule(LookupBase):
|
||||
|
||||
try:
|
||||
client = MongoClient(connection_string, **extra_connection_parameters)
|
||||
results = client[database][collection].find( **term )
|
||||
results = client[database][collection].find(**term)
|
||||
|
||||
for result in results:
|
||||
result = self.convert_mongo_result_to_valid_json(result)
|
||||
@@ -235,6 +234,4 @@ class LookupModule(LookupBase):
|
||||
except ConnectionFailure as e:
|
||||
raise AnsibleError('unable to connect to database: %s' % str(e))
|
||||
|
||||
|
||||
|
||||
return ret
|
||||
|
||||
@@ -23,6 +23,7 @@ from ansible.errors import AnsibleError, AnsibleUndefinedVariable
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.utils.listify import listify_lookup_plugin_terms
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def _lookup_variables(self, terms, variables):
|
||||
@@ -47,10 +48,8 @@ class LookupModule(LookupBase):
|
||||
result = my_list.pop()
|
||||
while len(my_list) > 0:
|
||||
result2 = self._combine(result, my_list.pop())
|
||||
result = result2
|
||||
result = result2
|
||||
new_result = []
|
||||
for x in result:
|
||||
new_result.append(self._flatten(x))
|
||||
return new_result
|
||||
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ def _gen_candidate_chars(characters):
|
||||
# getattr from string expands things like "ascii_letters" and "digits"
|
||||
# into a set of characters.
|
||||
chars.append(to_text(getattr(string, to_native(chars_spec), chars_spec),
|
||||
errors='strict'))
|
||||
errors='strict'))
|
||||
chars = u''.join(chars).replace(u'"', u'').replace(u"'", u'')
|
||||
return chars
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ from distutils import util
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
|
||||
|
||||
# backhacked check_output with input for python 2.7
|
||||
# http://stackoverflow.com/questions/10103551/passing-data-to-subprocess-check-output
|
||||
def check_output2(*popenargs, **kwargs):
|
||||
@@ -41,7 +42,7 @@ def check_output2(*popenargs, **kwargs):
|
||||
inputdata = None
|
||||
process = subprocess.Popen(*popenargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
|
||||
try:
|
||||
out,err = process.communicate(inputdata)
|
||||
out, err = process.communicate(inputdata)
|
||||
except:
|
||||
process.kill()
|
||||
process.wait()
|
||||
@@ -51,9 +52,10 @@ def check_output2(*popenargs, **kwargs):
|
||||
cmd = kwargs.get("args")
|
||||
if cmd is None:
|
||||
cmd = popenargs[0]
|
||||
raise subprocess.CalledProcessError(retcode, cmd, out+err)
|
||||
raise subprocess.CalledProcessError(retcode, cmd, out + err)
|
||||
return out
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
def parse_params(self, term):
|
||||
# I went with the "traditional" param followed with space separated KV pairs.
|
||||
@@ -117,7 +119,7 @@ class LookupModule(LookupBase):
|
||||
newpass = self.paramvals['userpass']
|
||||
else:
|
||||
try:
|
||||
newpass = check_output2(['pwgen','-cns',str(self.paramvals['length']), '1']).rstrip()
|
||||
newpass = check_output2(['pwgen', '-cns', str(self.paramvals['length']), '1']).rstrip()
|
||||
except (subprocess.CalledProcessError) as e:
|
||||
raise AnsibleError(e)
|
||||
return newpass
|
||||
@@ -125,11 +127,11 @@ class LookupModule(LookupBase):
|
||||
def update_password(self):
|
||||
# generate new password, insert old lines from current result and return new password
|
||||
newpass = self.get_newpass()
|
||||
datetime= time.strftime("%d/%m/%Y %H:%M:%S")
|
||||
msg = newpass +'\n' + '\n'.join(self.passoutput[1:])
|
||||
msg+="\nlookup_pass: old password was {} (Updated on {})\n".format(self.password, datetime)
|
||||
datetime = time.strftime("%d/%m/%Y %H:%M:%S")
|
||||
msg = newpass + '\n' + '\n'.join(self.passoutput[1:])
|
||||
msg += "\nlookup_pass: old password was {} (Updated on {})\n".format(self.password, datetime)
|
||||
try:
|
||||
generate = check_output2(['pass','insert','-f','-m',self.passname], input=msg)
|
||||
generate = check_output2(['pass', 'insert', '-f', '-m', self.passname], input=msg)
|
||||
except (subprocess.CalledProcessError) as e:
|
||||
raise AnsibleError(e)
|
||||
return newpass
|
||||
@@ -141,7 +143,7 @@ class LookupModule(LookupBase):
|
||||
datetime = time.strftime("%d/%m/%Y %H:%M:%S")
|
||||
msg = newpass + '\n' + "lookup_pass: First generated by ansible on {}\n".format(datetime)
|
||||
try:
|
||||
generate = check_output2(['pass','insert','-f','-m',self.passname], input=msg)
|
||||
generate = check_output2(['pass', 'insert', '-f', '-m', self.passname], input=msg)
|
||||
except (subprocess.CalledProcessError) as e:
|
||||
raise AnsibleError(e)
|
||||
return newpass
|
||||
@@ -160,13 +162,14 @@ class LookupModule(LookupBase):
|
||||
def run(self, terms, variables, **kwargs):
|
||||
result = []
|
||||
self.paramvals = {
|
||||
'subkey':'password',
|
||||
'directory':variables.get('passwordstore'),
|
||||
'create':False,
|
||||
'subkey': 'password',
|
||||
'directory': variables.get('passwordstore'),
|
||||
'create': False,
|
||||
'returnall': False,
|
||||
'overwrite':False,
|
||||
'userpass':'',
|
||||
'length': 16}
|
||||
'overwrite': False,
|
||||
'userpass': '',
|
||||
'length': 16,
|
||||
}
|
||||
|
||||
for term in terms:
|
||||
self.parse_params(term) # parse the input into paramvals
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user