def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for template operations ''' # note: since this module just calls the copy module, the --check mode support # can be implemented entirely over there if not self.runner.is_playbook: raise errors.AnsibleError("in current versions of ansible, templates are only usable in playbooks") # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) source = options.get('src', None) dest = options.get('dest', None) if (source is None and 'first_available_file' not in inject) or dest is None: result = dict(failed=True, msg="src and dest are required") return ReturnData(conn=conn, comm_ok=False, result=result) # if we have first_available_file in our vars # look up the files and use the first one we find as src if 'first_available_file' in inject: found = False for fn in self.runner.module_vars.get('first_available_file'): fn_orig = fn fnt = template.template(self.runner.basedir, fn, inject) fnd = utils.path_dwim(self.runner.basedir, fnt) if not os.path.exists(fnd) and '_original_file' in inject: fnd = utils.path_dwim_relative(inject['_original_file'], 'templates', fnt, self.runner.basedir, check=False) if os.path.exists(fnd): source = fnd found = True break if not found: result = dict(failed=True, msg="could not find src in first_available_file list") return ReturnData(conn=conn, comm_ok=False, result=result) else: source = template.template(self.runner.basedir, source, inject) if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'templates', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) if dest.endswith("/"): # CCTODO: Fix path for Windows hosts. base = os.path.basename(source) dest = os.path.join(dest, base) # template the source data locally & get ready to transfer try: resultant = template.template_from_file(self.runner.basedir, source, inject, vault_password=self.runner.vault_pass) except Exception, e: result = dict(failed=True, msg=type(e).__name__ + ": " + str(e)) return ReturnData(conn=conn, comm_ok=False, result=result)
def run(self, terms, inject=None, **kwargs): terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) ret = [] # this can happen if the variable contains a string, strictly not desired for lookup # plugins, but users may try it, so make it work. if not isinstance(terms, list): terms = [ terms ] for term in terms: basedir_path = utils.path_dwim(self.basedir, term) relative_path = None playbook_path = None # Special handling of the file lookup, used primarily when the # lookup is done from a role. If the file isn't found in the # basedir of the current file, use dwim_relative to look in the # role/files/ directory, and finally the playbook directory # itself (which will be relative to the current working dir) if '_original_file' in inject: relative_path = utils.path_dwim_relative(inject['_original_file'], 'files', term, self.basedir, check=False) if 'playbook_dir' in inject: playbook_path = os.path.join(inject['playbook_dir'], term) for path in (basedir_path, relative_path, playbook_path): if path and os.path.exists(path): ret.append(path) break else: raise errors.AnsibleError("could not locate file in lookup: %s" % term) return ret
def run(self, terms, inject=None, **kwargs): terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) ret = [] # this can happen if the variable contains a string, strictly not desired for lookup # plugins, but users may try it, so make it work. if not isinstance(terms, list): terms = [ terms ] # We need to search for the term in the relative path, and return # the file path, instead of the contents due to how this lookup # is used in a playbook for term in terms: path = None if '_original_file' in inject: path = utils.path_dwim_relative(inject['_original_file'], 'templates', '', self.basedir, check=False) path = os.path.join(path, term) if path and os.path.exists(path): ret.append(path) break else: raise errors.AnsibleError("could not locate template in lookup: %s" % term) return ret
def run(self, terms, inject=None, **kwargs): terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) ret = [] # this can happen if the variable contains a string, strictly not desired for lookup # plugins, but users may try it, so make it work. if not isinstance(terms, list): terms = [ terms ] project_root = find_debops_project(required=False) config = read_config(project_root) places = [] if 'paths' in config and conf_template_paths in config['paths']: custom_places = config['paths'][conf_template_paths].split(':') for custom_path in custom_places: if os.path.isabs(custom_path): places.append(custom_path) else: places.append(os.path.join(project_root, custom_path)) for term in terms: if '_original_file' in inject: relative_path = utils.path_dwim_relative(inject['_original_file'], 'tasks', '', self.basedir, check=False) places.append(relative_path) for path in places: template = os.path.join(path, term) if template and os.path.exists(template): ret.append(template) break else: raise errors.AnsibleError("could not locate file in lookup: %s" % term) return ret
def test_all_role_templates_tested(ctrl, monkeypatch, request): instance = ctrl.instances['jailhost'] instance.config['roles'] = ' '.join(get_all_roles()) pb = instance.get_playbook() plays = [] monkeypatch.setattr('ansible.playbook.PlayBook._run_play', plays.append) pb.run() # import after running to avoid module import issues from ansible.utils import parse_kv, path_dwim_relative templates = [] for play, task in iter_tasks(plays): if task.module_name != 'template': continue module_args_dict = task.args if not module_args_dict and task.module_args: module_args_dict = parse_kv(task.module_args) template_path = path_dwim_relative( task.module_vars['_original_file'], 'templates', module_args_dict['src'], play.basedir) if not os.path.exists(template_path): # pragma: nocover - only on failure raise ValueError name = module_args_dict['src'].lower() for rep in ('-', '.'): name = name.replace(rep, '_') templates.append(( name, dict( path=task.module_vars.get('_original_file'), role_name=task.role_name, name=module_args_dict['src'], task_name=task.name))) test_names = [x.name for x in request.session.items] for name, info in templates: test_name = 'test_%s_%s' % (info['role_name'], name) if not any(x for x in test_names if x.startswith(test_name)): # pragma: nocover - only on failure pytest.fail("No test '{0}' for template '{name}' of task '{task_name}' in role '{role_name}' at '{path}'.".format(test_name, **info))
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): if not module_args: result = dict(failed=True, msg="No source file given") return ReturnData(conn=conn, comm_ok=True, result=result) source = template.template(self.runner.basedir, module_args, inject) if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'vars', source, self.runner.basedir, False) else: source = utils.path_dwim(self.runner.basedir, source) data = {} if os.path.exists(source): data = utils.parse_yaml_from_file(source, vault_password=self.runner.vault_pass) if data and type(data) != dict: raise errors.AnsibleError("%s must be stored as a dictionary/hash" % source) if not hasattr(conn.runner, 'mergeBuffer'): conn.runner.mergeBuffer = {} if conn.host in conn.runner.mergeBuffer: data = utils.merge_hash(conn.runner.mergeBuffer[conn.host], data) conn.runner.mergeBuffer[conn.host] = data result = dict(ansible_facts=data) return ReturnData(conn=conn, comm_ok=True, result=result)
def run(self, terms, inject=None, **kwargs): terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) ret = [] if not isinstance(terms, list): terms = [terms] for term in terms: basedir_path = utils.path_dwim(self.basedir, term) relative_path = None playbook_path = None if '_original_file' in inject: relative_path = utils.path_dwim_relative(inject['_original_file'], 'files', term, self.basedir, check=False) if 'playbook_dir' in inject: playbook_path = os.path.join(inject['playbook_dir'], term) for path in (basedir_path, relative_path, playbook_path): if path and os.path.exists(path): vaultlib = inject['_ploy_instance'].get_vault_lib() with open(path) as f: data = f.read() if vaultlib.is_encrypted(data): data = vaultlib.decrypt(data) try: data = data.decode('utf8') except UnicodeDecodeError as e: raise errors.AnsibleError("UnicodeDecodeError encrypted file lookup, only ascii and utf8 supported: %s\n%s" % (term, e)) ret.append(data) break else: raise errors.AnsibleError("could not locate encrypted file in lookup: %s" % term) return ret
def run(self, terms, inject=None, **kwargs): terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) ret = [] # this can happen if the variable contains a string, strictly not desired for lookup # plugins, but users may try it, so make it work. if not isinstance(terms, list): terms = [ terms ] places = [] for term in terms: if '_original_file' in inject: relative_path = utils.path_dwim_relative(inject['_original_file'], 'tasks', '', self.basedir, check=False) places.append(relative_path) for path in places: template = os.path.join(path, term) if template and os.path.exists(template): ret.append(template) break else: raise errors.AnsibleError("could not locate file in lookup: %s" % term) return ret
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): if not module_args: result = dict(failed=True, msg="No source file given") return ReturnData(conn=conn, comm_ok=True, result=result) source = module_args source = template.template(self.runner.basedir, source, inject) if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'vars', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) if os.path.exists(source): data = utils.parse_yaml_from_file(source, vault_password=self.runner.vault_pass) if data and type(data) != dict: raise errors.AnsibleError("%s must be stored as a dictionary/hash" % source) elif data is None: data = {} result = dict(ansible_facts=data) return ReturnData(conn=conn, comm_ok=True, result=result) else: result = dict(failed=True, msg="Source file not found.", file=source) return ReturnData(conn=conn, comm_ok=True, result=result)
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) src = options.get('src', None) dest = options.get('dest', None) delimiter = options.get('delimiter', None) remote_src = utils.boolean(options.get('remote_src', 'yes')) if src is None or dest is None: result = dict(failed=True, msg="src and dest are required") return ReturnData(conn=conn, comm_ok=False, result=result) if remote_src: return self.runner._execute_module(conn, tmp, 'assemble', module_args, inject=inject, complex_args=complex_args) elif '_original_file' in inject: src = utils.path_dwim_relative(inject['_original_file'], 'files', src, self.runner.basedir) else: # the source is local, so expand it here src = os.path.expanduser(src) # Does all work assembling the file path = self._assemble_from_fragments(src, delimiter) pathmd5 = utils.md5s(path) remote_md5 = self.runner._remote_md5(conn, tmp, dest) if pathmd5 != remote_md5: resultant = file(path).read() if self.runner.diff: dest_result = self.runner._execute_module(conn, tmp, 'slurp', "path=%s" % dest, inject=inject, persist_files=True) if 'content' in dest_result.result: dest_contents = dest_result.result['content'] if dest_result.result['encoding'] == 'base64': dest_contents = base64.b64decode(dest_contents) else: raise Exception("unknown encoding, failed: %s" % dest_result.result) xfered = self.runner._transfer_str(conn, tmp, 'src', resultant) # fix file permissions when the copy is done as a different user if self.runner.sudo and self.runner.sudo_user != 'root': self.runner._low_level_exec_command(conn, "chmod a+r %s" % xfered, tmp) # run the copy module module_args = "%s src=%s dest=%s original_basename=%s" % (module_args, pipes.quote(xfered), pipes.quote(dest), pipes.quote(os.path.basename(src))) if self.runner.noop_on_check(inject): return ReturnData(conn=conn, comm_ok=True, result=dict(changed=True), diff=dict(before_header=dest, after_header=src, after=resultant)) else: res = self.runner._execute_module(conn, tmp, 'copy', module_args, inject=inject) res.diff = dict(after=resultant) return res else: module_args = "%s src=%s dest=%s original_basename=%s" % (module_args, pipes.quote(xfered), pipes.quote(dest), pipes.quote(os.path.basename(src))) return self.runner._execute_module(conn, tmp, 'file', module_args, inject=inject)
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) source = options.get('src', None) dest = options.get('dest', None) copy = utils.boolean(options.get('copy', 'yes')) if source is None or dest is None: result = dict(failed=True, msg="src (or content) and dest are required") return ReturnData(conn=conn, result=result) dest = os.path.expanduser(dest) # CCTODO: Fix path for Windows hosts. source = template.template(self.runner.basedir, os.path.expanduser(source), inject) if copy: if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) remote_md5 = self.runner._remote_md5(conn, tmp, dest) if remote_md5 != '3': result = dict(failed=True, msg="dest '%s' must be an existing dir" % dest) return ReturnData(conn=conn, result=result) if copy: # transfer the file to a remote tmp location tmp_src = tmp + 'source' conn.put_file(source, tmp_src) # handle diff mode client side # handle check mode client side # fix file permissions when the copy is done as a different user if copy: if self.runner.sudo and self.runner.sudo_user != 'root' or self.runner.su and self.runner.su_user != 'root': if not self.runner.noop_on_check(inject): self.runner._remote_chmod(conn, 'a+r', tmp_src, tmp) # Build temporary module_args. new_module_args = dict( src=tmp_src, original_basename=os.path.basename(source), ) # make sure checkmod is passed on correctly if self.runner.noop_on_check(inject): new_module_args['CHECKMODE'] = True module_args = utils.merge_module_args(module_args, new_module_args) else: module_args = "%s original_basename=%s" % (module_args, pipes.quote(os.path.basename(source))) # make sure checkmod is passed on correctly if self.runner.noop_on_check(inject): module_args += " CHECKMODE=True" return self.runner._execute_module(conn, tmp, 'unarchive', module_args, inject=inject, complex_args=complex_args)
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): """Run the method""" if not self.runner.is_playbook: raise errors.AnsibleError("FAILED: `config_templates` are only available in playbooks") options = self.grab_options(complex_args, module_args) try: source = options["src"] dest = options["dest"] config_overrides = options.get("config_overrides", dict()) config_type = options["config_type"] assert config_type.lower() in ["ini", "json", "yaml"] except KeyError as exp: result = dict(failed=True, msg=exp) return ReturnData(conn=conn, comm_ok=False, result=result) source_template = template.template(self.runner.basedir, source, inject) if "_original_file" in inject: source_file = utils.path_dwim_relative( inject["_original_file"], "templates", source_template, self.runner.basedir ) else: source_file = utils.path_dwim(self.runner.basedir, source_template) # Open the template file and return the data as a string. This is # being done here so that the file can be a vault encrypted file. resultant = template.template_from_file( self.runner.basedir, source_file, inject, vault_password=self.runner.vault_pass ) if config_overrides: type_merger = getattr(self, CONFIG_TYPES.get(config_type)) resultant = type_merger(config_overrides=config_overrides, resultant=resultant) # Retemplate the resultant object as it may have new data within it # as provided by an override variable. template.template_from_string(basedir=self.runner.basedir, data=resultant, vars=inject, fail_on_undefined=True) # Access to protected method is unavoidable in Ansible 1.x. new_module_args = dict( src=self.runner._transfer_str(conn, tmp, "source", resultant), dest=dest, original_basename=os.path.basename(source), follow=True, ) module_args_tmp = utils.merge_module_args(module_args, new_module_args) # Remove data types that are not available to the copy module complex_args.pop("config_overrides") complex_args.pop("config_type") # Return the copy module status. Access to protected method is # unavoidable in Ansible 1.x. return self.runner._execute_module(conn, tmp, "copy", module_args_tmp, inject=inject, complex_args=complex_args)
def _get_absolute_path(self, path=None): if 'vars' in self.inject: if '_original_file' in self.inject['vars']: # roles path = utils.path_dwim_relative(self.inject['_original_file'], 'files', path, self.runner.basedir) elif 'inventory_dir' in self.inject['vars']: # non-roles abs_dir = os.path.abspath(self.inject['vars']['inventory_dir']) path = os.path.join(abs_dir, path) return path
def _get_absolute_path(self, path=None): if 'vars' in self.inject: if '_original_file' in self.inject['vars']: # roles original_path = path path = utils.path_dwim_relative(self.inject['_original_file'], 'files', path, self.runner.basedir) if original_path and original_path[-1] == '/' and path[-1] != '/': # make sure the dwim'd path ends in a trailing "/" # if the original path did path += '/' return path
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) source = options.get('src', None) content = options.get('content', None) dest = options.get('dest', None) raw = utils.boolean(options.get('raw', 'no')) force = utils.boolean(options.get('force', 'yes')) if (source is None and content is None and not 'first_available_file' in inject) or dest is None: result=dict(failed=True, msg="src (or content) and dest are required") return ReturnData(conn=conn, result=result) elif (source is not None or 'first_available_file' in inject) and content is not None: result=dict(failed=True, msg="src and content are mutually exclusive") return ReturnData(conn=conn, result=result) source_trailing_slash = False if source: source_trailing_slash = source.endswith("/") # if we have first_available_file in our vars # look up the files and use the first one we find as src if 'first_available_file' in inject: found = False for fn in inject.get('first_available_file'): fn_orig = fn fnt = template.template(self.runner.basedir, fn, inject) fnd = utils.path_dwim(self.runner.basedir, fnt) if not os.path.exists(fnd) and '_original_file' in inject: fnd = utils.path_dwim_relative(inject['_original_file'], 'files', fnt, self.runner.basedir, check=False) if os.path.exists(fnd): source = fnd found = True break if not found: results=dict(failed=True, msg="could not find src in first_available_file list") return ReturnData(conn=conn, result=results) elif content is not None: fd, tmp_content = tempfile.mkstemp() f = os.fdopen(fd, 'w') try: f.write(content) except Exception, err: os.remove(tmp_content) result = dict(failed=True, msg="could not write content temp file: %s" % err) return ReturnData(conn=conn, result=result) f.close() source = tmp_content
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' if self.runner.noop_on_check(inject): # in check mode, always skip this module return ReturnData(conn=conn, comm_ok=True, result=dict(skipped=True, msg='check mode not supported for this module')) # Decode the result of shlex.split() to UTF8 to get around a bug in that's been fixed in Python 2.7 but not Python 2.6. # See: http://bugs.python.org/issue6988 tokens = shlex.split(module_args.encode('utf8')) tokens = [s.decode('utf8') for s in tokens] source = tokens[0] # FIXME: error handling args = " ".join(tokens[1:]) source = template.template(self.runner.basedir, source, inject) if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) # transfer the file to a remote tmp location source = source.replace('\x00','') # why does this happen here? args = args.replace('\x00','') # why does this happen here? tmp_src = os.path.join(tmp, os.path.basename(source)) tmp_src = tmp_src.replace('\x00', '') conn.put_file(source, tmp_src) sudoable=True # set file permissions, more permisive when the copy is done as a different user if self.runner.sudo and self.runner.sudo_user != 'root': cmd_args_chmod = "chmod a+rx %s" % tmp_src sudoable=False else: cmd_args_chmod = "chmod +rx %s" % tmp_src self.runner._low_level_exec_command(conn, cmd_args_chmod, tmp, sudoable=sudoable) # add preparation steps to one ssh roundtrip executing the script env_string = self.runner._compute_environment_string(inject) module_args = env_string + tmp_src + ' ' + args handler = utils.plugins.action_loader.get('raw', self.runner) result = handler.run(conn, tmp, 'raw', module_args, inject) # clean up after if tmp.find("tmp") != -1 and not C.DEFAULT_KEEP_REMOTE_FILES: self.runner._low_level_exec_command(conn, 'rm -rf %s >/dev/null 2>&1' % tmp, tmp) result.result['changed'] = True return result
def _resolve_file_path(self, filepath, dirname, inject): ''' Resolve absolute path of the file. ''' basedir = self.runner.basedir filepath = template.template(basedir, filepath, inject) if '_original_file' in inject: origin_path = inject['_original_file'] filepath = utils.path_dwim_relative(origin_path, dirname, filepath, basedir) else: filepath = utils.path_dwim(basedir, filepath) return filepath
def run(self, terms, inject=None, **kwargs): terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) ret = [] # this can happen if the variable contains a string, strictly not desired for lookup # plugins, but users may try it, so make it work. if not isinstance(terms, list): terms = [ terms ] buffersize = 65536 for term in terms: basedir_path = utils.path_dwim(self.basedir, term) relative_path = None playbook_path = None # Special handling of the file lookup, used primarily when the # lookup is done from a role. If the file isn't found in the # basedir of the current file, use dwim_relative to look in the # role/files/ directory, and finally the playbook directory # itself (which will be relative to the current working dir) if '_original_file' in inject: relative_path = utils.path_dwim_relative(inject['_original_file'], 'files', term, self.basedir, check=False) if 'playbook_dir' in inject: playbook_path = os.path.join(inject['playbook_dir'], term) for path in (basedir_path, relative_path, playbook_path): if path and os.path.exists(path): afile = open(path, 'r') break else: raise errors.AnsibleError("could not locate file in lookup: %s" % term) # Read file buffered into hasher (good for memory). hasher = hashlib.md5() buffer = afile.read(buffersize) while(len(buffer) > 0): hasher.update(buffer) buffer = afile.read(buffersize) # Append hex digest to ret list. ret.append(hasher.hexdigest()) # Close file. afile.close() # Return hex digest. return ret
def get_paths(self, inject): paths = [] paths.append(utils.path_dwim(self.basedir, '')) if '_original_file' in inject: paths.append(utils.path_dwim_relative(inject['_original_file'], '', '', self.basedir, check=False)) if 'playbook_dir' in inject and paths[0] != inject['playbook_dir']: paths.append(inject['playbook_dir']) for path in C.get_config(C.p, C.DEFAULTS, 'lookup_file_paths', None, [], islist=True): path = utils.unfrackpath(path) if os.path.exists(path): paths.append(path) return paths
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) src = options.get('src', None) dest = options.get('dest', None) remote_src = utils.boolean(options.get('remote_src', 'no')) if src is None: result = dict(failed=True, msg="src is required") return ReturnData(conn=conn, comm_ok=False, result=result) if remote_src: return self.runner._execute_module(conn, tmp, 'patch', module_args, inject=inject, complex_args=complex_args) # Source is local if '_original_file' in inject: src = utils.path_dwim_relative(inject['_original_file'], 'files', src, self.runner.basedir) else: src = utils.path_dwim(self.runner.basedir, src) tmp_path = self.runner._make_tmp_path(conn) tmp_src = tmp_path + 'patch_source' conn.put_file(src, tmp_src) if self.runner.become and self.runner.become_user != 'root': if not self.runner.noop_on_check(inject): self.runner._remote_chmod(conn, 'a+r', tmp_src, tmp_path) new_module_args = dict( src=tmp_src, ) if self.runner.noop_on_check(inject): new_module_args['CHECKMODE'] = True module_args = utils.merge_module_args(module_args, new_module_args) data = self.runner._execute_module(conn, tmp, 'patch', module_args, inject=inject, complex_args=complex_args) if not C.DEFAULT_KEEP_REMOTE_FILES: self.runner._remove_tmp_path(conn, tmp_path) return data
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) src = options.get("src", None) dest = options.get("dest", None) remote_src = utils.boolean(options.get("remote_src", "no")) if src is None: result = dict(failed=True, msg="src is required") return ReturnData(conn=conn, comm_ok=False, result=result) if remote_src: return self.runner._execute_module( conn, tmp, "patch", module_args, inject=inject, complex_args=complex_args ) # Source is local if "_original_file" in inject: src = utils.path_dwim_relative(inject["_original_file"], "files", src, self.runner.basedir) else: src = utils.path_dwim(self.runner.basedir, src) if tmp is None or "-tmp-" not in tmp: tmp = self.runner._make_tmp_path(conn) tmp_src = conn.shell.join_path(tmp, os.path.basename(src)) conn.put_file(src, tmp_src) if self.runner.become and self.runner.become_user != "root": if not self.runner.noop_on_check(inject): self.runner._remote_chmod(conn, "a+r", tmp_src, tmp) new_module_args = dict(src=tmp_src) if self.runner.noop_on_check(inject): new_module_args["CHECKMODE"] = True module_args = utils.merge_module_args(module_args, new_module_args) return self.runner._execute_module(conn, tmp, "patch", module_args, inject=inject, complex_args=complex_args)
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) source = options.get('src', None) dest = options.get('dest', None) copy = utils.boolean(options.get('copy', 'yes')) if source is None or dest is None: result = dict(failed=True, msg="src (or content) and dest are required") return ReturnData(conn=conn, result=result) dest = os.path.expanduser(dest) source = template.template(self.runner.basedir, os.path.expanduser(source), inject) if copy: if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) remote_md5 = self.runner._remote_md5(conn, tmp, dest) if remote_md5 != '3': result = dict(failed=True, msg="dest '%s' must be an existing dir" % dest) return ReturnData(conn=conn, result=result) if copy: # transfer the file to a remote tmp location tmp_src = tmp + 'source' conn.put_file(source, tmp_src) # handle diff mode client side # handle check mode client side # fix file permissions when the copy is done as a different user if copy: if self.runner.sudo and self.runner.sudo_user != 'root': self.runner._low_level_exec_command(conn, "chmod a+r %s" % tmp_src, tmp) module_args = "%s src=%s original_basename=%s" % (module_args, pipes.quote(tmp_src), pipes.quote(os.path.basename(source))) else: module_args = "%s original_basename=%s" % (module_args, pipes.quote(os.path.basename(source))) return self.runner._execute_module(conn, tmp, 'unarchive', module_args, inject=inject, complex_args=complex_args)
def run(self, terms, inject=None, **kwargs): terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) ret = [] if not isinstance(terms, list): terms = [ terms ] for term in terms: playbook_path = None relative_path = None paramvals = {"file": None, "key": None} params = term.split() try: for param in params: name, value = param.split('=') assert(name in paramvals) paramvals[name] = value except (ValueError, AssertionError), e: # In case "file" or "key" are not present raise errors.AnsibleError(e) file = paramvals['file'] key = paramvals['key'] basedir_path = utils.path_dwim(self.basedir, file) # Search also in the role/files directory and in the playbook directory if '_original_file' in inject: relative_path = utils.path_dwim_relative(inject['_original_file'], 'files', file, self.basedir, check=False) if 'playbook_dir' in inject: playbook_path = os.path.join(inject['playbook_dir'], file) for path in (basedir_path, relative_path, playbook_path): if path and os.path.exists(path): res = self.read_shelve(path, key) if res is None: raise errors.AnsibleError("Key %s not found in shelve file %s" % (key, file)) # Convert the value read to string ret.append(str(res)) break else: raise errors.AnsibleError("Could not locate shelve file in lookup: %s" % file)
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' if self.runner.noop_on_check(inject): # in check mode, always skip this module return ReturnData(conn=conn, comm_ok=True, result=dict(skipped=True, msg='check mode not supported for this module')) tokens = shlex.split(module_args) source = tokens[0] # FIXME: error handling args = " ".join(tokens[1:]) source = template.template(self.runner.basedir, source, inject) if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) # transfer the file to a remote tmp location source = source.replace('\x00','') # why does this happen here? args = args.replace('\x00','') # why does this happen here? tmp_src = os.path.join(tmp, os.path.basename(source)) tmp_src = tmp_src.replace('\x00', '') conn.put_file(source, tmp_src) # fix file permissions when the copy is done as a different user if self.runner.sudo and self.runner.sudo_user != 'root': prepcmd = 'chmod a+rx %s' % tmp_src else: prepcmd = 'chmod +x %s' % tmp_src # add preparation steps to one ssh roundtrip executing the script env_string = self.runner._compute_environment_string(inject) module_args = prepcmd + '; ' + env_string + tmp_src + ' ' + args handler = utils.plugins.action_loader.get('raw', self.runner) result = handler.run(conn, tmp, 'raw', module_args, inject) # clean up after if tmp.find("tmp") != -1 and not C.DEFAULT_KEEP_REMOTE_FILES: self.runner._low_level_exec_command(conn, 'rm -rf %s >/dev/null 2>&1' % tmp, tmp) return result
def run(self, conn, tmp_path, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) if "-tmp-" not in tmp_path: tmp_path = self.runner._make_tmp_path(conn) self.tmp_path = tmp_path self.conn = conn self.facts = inject self._copy_setup_storage() # copy user defined partion file if needed partition = options.get('partition') if not partition is None and partition != 'auto': fnd = utils.path_dwim( os.path.sep.join((self.runner.basedir, 'files')), partition) if not os.path.exists(fnd): fnd = utils.path_dwim_relative( partition, 'files', partition, self.runner.basedir) self.conn.put_file( fnd, os.path.sep.join([self.tmp_path, 'setup-storage', 'conf.d', partition])) ret=self.runner._execute_module( conn, tmp_path, 'system_install', module_args, inject=inject, complex_args=complex_args) return ret
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): args = parse_kv(module_args) environment = args.get('environment') account_id = args.get('account_id') assume_role = args.get('assume_role') for name, val in (("environment", environment), ("account_id", account_id), ("assume_role", assume_role)): if val is None: result = dict(failed=True, msg="No {0} specified".format(name)) return ReturnData(conn=conn, comm_ok=True, result=result) source = template.template(self.runner.basedir, environment, inject) if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'vars', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) if os.path.exists(source): decrypted_data = {} data = json.load(open(source)) with assume(account_id, assume_role): kms = boto.kms.connect_to_region('ap-southeast-2') for key, val in data.items(): data_key = kms.decrypt(base64.b64decode(val['key']))["Plaintext"] content = base64.b64decode(val['content']) counter = Counter.new(128) decryptor = AES.new(data_key[:32], AES.MODE_CTR, counter=counter) decrypted_data[key] = decryptor.decrypt(content) result = dict(ansible_facts=decrypted_data) return ReturnData(conn=conn, comm_ok=True, result=result) else: result = dict(failed=True, msg="Couldn't find secrets!", file=source) return ReturnData(conn=conn, comm_ok=True, result=result)
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' if self.runner.noop_on_check(inject): # in check mode, always skip this module return ReturnData( conn=conn, comm_ok=True, result=dict(skipped=True, msg='check mode not supported for this module')) # Decode the result of shlex.split() to UTF8 to get around a bug in that's been fixed in Python 2.7 but not Python 2.6. # See: http://bugs.python.org/issue6988 tokens = shlex.split(module_args.encode('utf8')) tokens = [s.decode('utf8') for s in tokens] source = tokens[0] # FIXME: error handling args = " ".join(tokens[1:]) source = template.template(self.runner.basedir, source, inject) if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) # transfer the file to a remote tmp location source = source.replace('\x00', '') # why does this happen here? args = args.replace('\x00', '') # why does this happen here? tmp_src = os.path.join(tmp, os.path.basename(source)) tmp_src = tmp_src.replace('\x00', '') conn.put_file(source, tmp_src) # fix file permissions when the copy is done as a different user if self.runner.sudo and self.runner.sudo_user != 'root': prepcmd = 'chmod a+rx %s' % tmp_src else: prepcmd = 'chmod +x %s' % tmp_src # add preparation steps to one ssh roundtrip executing the script env_string = self.runner._compute_environment_string(inject) module_args = prepcmd + '; ' + env_string + tmp_src + ' ' + args handler = utils.plugins.action_loader.get('raw', self.runner) result = handler.run(conn, tmp, 'raw', module_args, inject) # clean up after if tmp.find("tmp") != -1 and not C.DEFAULT_KEEP_REMOTE_FILES: self.runner._low_level_exec_command( conn, 'rm -rf %s >/dev/null 2>&1' % tmp, tmp) result.result['changed'] = True return result
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for template operations ''' # note: since this module just calls the copy module, the --check mode support # can be implemented entirely over there if not self.runner.is_playbook: raise errors.AnsibleError( "in current versions of ansible, templates are only usable in playbooks" ) # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) source = options.get('src', None) dest = options.get('dest', None) if (source is None and 'first_available_file' not in inject) or dest is None: result = dict(failed=True, msg="src and dest are required") return ReturnData(conn=conn, comm_ok=False, result=result) # if we have first_available_file in our vars # look up the files and use the first one we find as src if 'first_available_file' in inject: found = False for fn in self.runner.module_vars.get('first_available_file'): fn_orig = fn fnt = template.template(self.runner.basedir, fn, inject) fnd = utils.path_dwim(self.runner.basedir, fnt) if not os.path.exists(fnd) and '_original_file' in inject: fnd = utils.path_dwim_relative(inject['_original_file'], 'templates', fnt, self.runner.basedir, check=False) if os.path.exists(fnd): source = fnd found = True break if not found: result = dict( failed=True, msg="could not find src in first_available_file list") return ReturnData(conn=conn, comm_ok=False, result=result) else: source = template.template(self.runner.basedir, source, inject) if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'templates', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) if dest.endswith("/"): # CCTODO: Fix path for Windows hosts. base = os.path.basename(source) dest = os.path.join(dest, base) # template the source data locally & get ready to transfer try: resultant = template.template_from_file( self.runner.basedir, source, inject, vault_password=self.runner.vault_pass) except Exception, e: result = dict(failed=True, msg=str(e)) return ReturnData(conn=conn, comm_ok=False, result=result)
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): """Run the method""" if not self.runner.is_playbook: raise errors.AnsibleError( 'FAILED: `config_templates` are only available in playbooks') options = self.grab_options(complex_args, module_args) try: source = options['src'] dest = options['dest'] config_overrides = options.get('config_overrides', dict()) config_type = options['config_type'] assert config_type.lower() in ['ini', 'json', 'yaml'] except KeyError as exp: result = dict(failed=True, msg=exp) return ReturnData(conn=conn, comm_ok=False, result=result) source_template = template.template(self.runner.basedir, source, inject) if '_original_file' in inject: source_file = utils.path_dwim_relative(inject['_original_file'], 'templates', source_template, self.runner.basedir) else: source_file = utils.path_dwim(self.runner.basedir, source_template) # Open the template file and return the data as a string. This is # being done here so that the file can be a vault encrypted file. resultant = template.template_from_file( self.runner.basedir, source_file, inject, vault_password=self.runner.vault_pass) if config_overrides: type_merger = getattr(self, CONFIG_TYPES.get(config_type)) resultant = type_merger(config_overrides=config_overrides, resultant=resultant) # Retemplate the resultant object as it may have new data within it # as provided by an override variable. template.template_from_string(basedir=self.runner.basedir, data=resultant, vars=inject, fail_on_undefined=True) # Access to protected method is unavoidable in Ansible 1.x. new_module_args = dict( src=self.runner._transfer_str(conn, tmp, 'source', resultant), dest=dest, original_basename=os.path.basename(source), follow=True, ) module_args_tmp = utils.merge_module_args(module_args, new_module_args) # Remove data types that are not available to the copy module complex_args.pop('config_overrides') complex_args.pop('config_type') # Return the copy module status. Access to protected method is # unavoidable in Ansible 1.x. return self.runner._execute_module(conn, tmp, 'copy', module_args_tmp, inject=inject, complex_args=complex_args)
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) source = options.get('src', None) dest = options.get('dest', None) copy = utils.boolean(options.get('copy', 'yes')) creates = options.get('creates', None) if source is None or dest is None: result = dict(failed=True, msg="src (or content) and dest are required") return ReturnData(conn=conn, result=result) if creates: # do not run the command if the line contains creates=filename # and the filename already exists. This allows idempotence # of command executions. module_args_tmp = "" complex_args_tmp = dict(path=creates, get_md5=False, get_checksum=False) module_return = self.runner._execute_module( conn, tmp, 'stat', module_args_tmp, inject=inject, complex_args=complex_args_tmp, persist_files=True) stat = module_return.result.get('stat', None) if stat and stat.get('exists', False): return ReturnData(conn=conn, comm_ok=True, result=dict(skipped=True, changed=False, msg=("skipped, since %s exists" % creates))) dest = self.runner._remote_expand_user( conn, dest, tmp) # CCTODO: Fix path for Windows hosts. source = template.template(self.runner.basedir, os.path.expanduser(source), inject) if copy: if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) remote_checksum = self.runner._remote_checksum(conn, tmp, dest, inject) if remote_checksum == '4': result = dict( failed=True, msg= "python isn't present on the system. Unable to compute checksum" ) return ReturnData(conn=conn, result=result) if remote_checksum != '3': result = dict(failed=True, msg="dest '%s' must be an existing dir" % dest) return ReturnData(conn=conn, result=result) if copy: # transfer the file to a remote tmp location tmp_src = tmp + 'source' conn.put_file(source, tmp_src) # handle diff mode client side # handle check mode client side # fix file permissions when the copy is done as a different user if copy: if self.runner.sudo and self.runner.sudo_user != 'root' or self.runner.su and self.runner.su_user != 'root': if not self.runner.noop_on_check(inject): self.runner._remote_chmod(conn, 'a+r', tmp_src, tmp) # Build temporary module_args. new_module_args = dict( src=tmp_src, original_basename=os.path.basename(source), ) # make sure checkmod is passed on correctly if self.runner.noop_on_check(inject): new_module_args['CHECKMODE'] = True module_args = utils.merge_module_args(module_args, new_module_args) else: module_args = "%s original_basename=%s" % ( module_args, pipes.quote(os.path.basename(source))) # make sure checkmod is passed on correctly if self.runner.noop_on_check(inject): module_args += " CHECKMODE=True" return self.runner._execute_module(conn, tmp, 'unarchive', module_args, inject=inject, complex_args=complex_args)
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) source = options.get('src', None) dest = options.get('dest', None) copy = utils.boolean(options.get('copy', 'yes')) creates = options.get('creates', None) if source is None or dest is None: result = dict(failed=True, msg="src (or content) and dest are required") return ReturnData(conn=conn, result=result) if creates: # do not run the command if the line contains creates=filename # and the filename already exists. This allows idempotence # of command executions. module_args_tmp = "" complex_args_tmp = dict(path=creates, get_md5=False, get_checksum=False) module_return = self.runner._execute_module(conn, tmp, 'stat', module_args_tmp, inject=inject, complex_args=complex_args_tmp, persist_files=True) stat = module_return.result.get('stat', None) if stat and stat.get('exists', False): return ReturnData( conn=conn, comm_ok=True, result=dict( skipped=True, changed=False, msg=("skipped, since %s exists" % creates) ) ) dest = self.runner._remote_expand_user(conn, dest, tmp) # CCTODO: Fix path for Windows hosts. source = template.template(self.runner.basedir, os.path.expanduser(source), inject) if copy: if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) remote_checksum = self.runner._remote_checksum(conn, tmp, dest, inject) if remote_checksum == '4': result = dict(failed=True, msg="python isn't present on the system. Unable to compute checksum") return ReturnData(conn=conn, result=result) if remote_checksum != '3': result = dict(failed=True, msg="dest '%s' must be an existing dir" % dest) return ReturnData(conn=conn, result=result) if copy: # transfer the file to a remote tmp location tmp_src = tmp + 'source' conn.put_file(source, tmp_src) # handle diff mode client side # handle check mode client side # fix file permissions when the copy is done as a different user if copy: if self.runner.sudo and self.runner.sudo_user != 'root' or self.runner.su and self.runner.su_user != 'root': if not self.runner.noop_on_check(inject): self.runner._remote_chmod(conn, 'a+r', tmp_src, tmp) # Build temporary module_args. new_module_args = dict( src=tmp_src, original_basename=os.path.basename(source), ) # make sure checkmod is passed on correctly if self.runner.noop_on_check(inject): new_module_args['CHECKMODE'] = True module_args = utils.merge_module_args(module_args, new_module_args) else: module_args = "%s original_basename=%s" % (module_args, pipes.quote(os.path.basename(source))) # make sure checkmod is passed on correctly if self.runner.noop_on_check(inject): module_args += " CHECKMODE=True" return self.runner._execute_module(conn, tmp, 'unarchive', module_args, inject=inject, complex_args=complex_args)
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) source = options.get('src', None) dest = options.get('dest', None) copy = utils.boolean(options.get('copy', 'yes')) if source is None or dest is None: result = dict(failed=True, msg="src (or content) and dest are required") return ReturnData(conn=conn, result=result) dest = os.path.expanduser(dest) # CCTODO: Fix path for Windows hosts. source = template.template(self.runner.basedir, os.path.expanduser(source), inject) if copy: if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) remote_md5 = self.runner._remote_md5(conn, tmp, dest) if remote_md5 != '3': result = dict(failed=True, msg="dest '%s' must be an existing dir" % dest) return ReturnData(conn=conn, result=result) if copy: # transfer the file to a remote tmp location tmp_src = tmp + 'source' conn.put_file(source, tmp_src) # handle diff mode client side # handle check mode client side # fix file permissions when the copy is done as a different user if copy: if self.runner.sudo and self.runner.sudo_user != 'root': self.runner._remote_chmod(conn, 'a+r', tmp_src, tmp) # Build temporary module_args. new_module_args = dict( src=tmp_src, original_basename=os.path.basename(source), ) module_args = utils.merge_module_args(module_args, new_module_args) else: module_args = "%s original_basename=%s" % ( module_args, pipes.quote(os.path.basename(source))) return self.runner._execute_module(conn, tmp, 'unarchive', module_args, inject=inject, complex_args=complex_args)
class ActionModule(object): def __init__(self, runner): self.runner = runner def run(self, conn, tmp_path, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) source = options.get('src', None) content = options.get('content', None) dest = options.get('dest', None) raw = utils.boolean(options.get('raw', 'no')) force = utils.boolean(options.get('force', 'yes')) # content with newlines is going to be escaped to safely load in yaml # now we need to unescape it so that the newlines are evaluated properly # when writing the file to disk if content: if isinstance(content, unicode): try: content = content.decode('unicode-escape') except UnicodeDecodeError: pass if (source is None and content is None and not 'first_available_file' in inject) or dest is None: result = dict(failed=True, msg="src (or content) and dest are required") return ReturnData(conn=conn, result=result) elif (source is not None or 'first_available_file' in inject) and content is not None: result = dict(failed=True, msg="src and content are mutually exclusive") return ReturnData(conn=conn, result=result) # Check if the source ends with a "/" source_trailing_slash = False if source: source_trailing_slash = source.endswith("/") # Define content_tempfile in case we set it after finding content populated. content_tempfile = None # If content is defined make a temp file and write the content into it. if content is not None: try: # If content comes to us as a dict it should be decoded json. # We need to encode it back into a string to write it out. if type(content) is dict: content_tempfile = self._create_content_tempfile( json.dumps(content)) else: content_tempfile = self._create_content_tempfile(content) source = content_tempfile except Exception, err: result = dict(failed=True, msg="could not write content temp file: %s" % err) return ReturnData(conn=conn, result=result) # if we have first_available_file in our vars # look up the files and use the first one we find as src elif 'first_available_file' in inject: found = False for fn in inject.get('first_available_file'): fn_orig = fn fnt = template.template(self.runner.basedir, fn, inject) fnd = utils.path_dwim(self.runner.basedir, fnt) if not os.path.exists(fnd) and '_original_file' in inject: fnd = utils.path_dwim_relative(inject['_original_file'], 'files', fnt, self.runner.basedir, check=False) if os.path.exists(fnd): source = fnd found = True break if not found: results = dict( failed=True, msg="could not find src in first_available_file list") return ReturnData(conn=conn, result=results)
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) src = options.get('src', None) dest = options.get('dest', None) delimiter = options.get('delimiter', None) remote_src = utils.boolean(options.get('remote_src', 'yes')) regexp = options.get('regexp', None) if src is None or dest is None: result = dict(failed=True, msg="src and dest are required") return ReturnData(conn=conn, comm_ok=False, result=result) if remote_src: return self.runner._execute_module(conn, tmp, 'assemble', module_args, inject=inject, complex_args=complex_args) elif '_original_file' in inject: src = utils.path_dwim_relative(inject['_original_file'], 'files', src, self.runner.basedir) else: # the source is local, so expand it here src = os.path.expanduser(src) _re = None if regexp is not None: _re = re.compile(regexp) # Does all work assembling the file path = self._assemble_from_fragments(src, delimiter, _re) path_checksum = utils.checksum_s(path) dest = self.runner._remote_expand_user(conn, dest, tmp) remote_checksum = self.runner._remote_checksum(conn, tmp, dest, inject) if path_checksum != remote_checksum: resultant = file(path).read() if self.runner.diff: dest_result = self.runner._execute_module(conn, tmp, 'slurp', "path=%s" % dest, inject=inject, persist_files=True) if 'content' in dest_result.result: dest_contents = dest_result.result['content'] if dest_result.result['encoding'] == 'base64': dest_contents = base64.b64decode(dest_contents) else: raise Exception("unknown encoding, failed: %s" % dest_result.result) xfered = self.runner._transfer_str(conn, tmp, 'src', resultant) # fix file permissions when the copy is done as a different user if self.runner.become and self.runner.become_user != 'root': self.runner._remote_chmod(conn, 'a+r', xfered, tmp) # run the copy module new_module_args = dict( src=xfered, dest=dest, original_basename=os.path.basename(src), ) module_args_tmp = utils.merge_module_args(module_args, new_module_args) if self.runner.noop_on_check(inject): return ReturnData(conn=conn, comm_ok=True, result=dict(changed=True), diff=dict(before_header=dest, after_header=src, after=resultant)) else: res = self.runner._execute_module(conn, tmp, 'copy', module_args_tmp, inject=inject) res.diff = dict(after=resultant) return res else: new_module_args = dict( src=xfered, dest=dest, original_basename=os.path.basename(src), ) # make sure checkmod is passed on correctly if self.runner.noop_on_check(inject): new_module_args['CHECKMODE'] = True module_args_tmp = utils.merge_module_args(module_args, new_module_args) return self.runner._execute_module(conn, tmp, 'file', module_args_tmp, inject=inject)
fnd = utils.path_dwim(self.runner.basedir, fnt) if not os.path.exists(fnd) and "_original_file" in inject: fnd = utils.path_dwim_relative( inject["_original_file"], "files", fnt, self.runner.basedir, check=False ) if os.path.exists(fnd): source = fnd found = True break if not found: results = dict(failed=True, msg="could not find src in first_available_file list") return ReturnData(conn=conn, result=results) else: source = template.template(self.runner.basedir, source, inject) if "_original_file" in inject: source = utils.path_dwim_relative(inject["_original_file"], "files", source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) # A list of source file tuples (full_path, relative_path) which will try to copy to the destination source_files = [] # If source is a directory populate our list else source is a file and translate it to a tuple. if os.path.isdir(source): # Get the amount of spaces to remove to get the relative path. if source_trailing_slash: sz = len(source) + 1 else: sz = len(source.rsplit("/", 1)[0]) + 1 # Walk the directory and append the file tuples to source_files.
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) src = options.get('src', None) dest = options.get('dest', None) delimiter = options.get('delimiter', None) remote_src = utils.boolean(options.get('remote_src', 'yes')) if src is None or dest is None: result = dict(failed=True, msg="src and dest are required") return ReturnData(conn=conn, comm_ok=False, result=result) if remote_src: return self.runner._execute_module(conn, tmp, 'assemble', module_args, inject=inject, complex_args=complex_args) elif '_original_file' in inject: src = utils.path_dwim_relative(inject['_original_file'], 'files', src, self.runner.basedir) else: # the source is local, so expand it here src = os.path.expanduser(src) # Does all work assembling the file path = self._assemble_from_fragments(src, delimiter) pathmd5 = utils.md5s(path) remote_md5 = self.runner._remote_md5(conn, tmp, dest) if pathmd5 != remote_md5: resultant = file(path).read() if self.runner.diff: dest_result = self.runner._execute_module(conn, tmp, 'slurp', "path=%s" % dest, inject=inject, persist_files=True) if 'content' in dest_result.result: dest_contents = dest_result.result['content'] if dest_result.result['encoding'] == 'base64': dest_contents = base64.b64decode(dest_contents) else: raise Exception("unknown encoding, failed: %s" % dest_result.result) xfered = self.runner._transfer_str(conn, tmp, 'src', resultant) # fix file permissions when the copy is done as a different user if self.runner.sudo and self.runner.sudo_user != 'root': self.runner._low_level_exec_command(conn, "chmod a+r %s" % xfered, tmp) # run the copy module module_args = "%s src=%s dest=%s original_basename=%s" % ( module_args, pipes.quote(xfered), pipes.quote(dest), pipes.quote(os.path.basename(src))) if self.runner.noop_on_check(inject): return ReturnData(conn=conn, comm_ok=True, result=dict(changed=True), diff=dict(before_header=dest, after_header=src, after=resultant)) else: res = self.runner._execute_module(conn, tmp, 'copy', module_args, inject=inject) res.diff = dict(after=resultant) return res else: module_args = "%s src=%s dest=%s original_basename=%s" % ( module_args, pipes.quote(xfered), pipes.quote(dest), pipes.quote(os.path.basename(src))) return self.runner._execute_module(conn, tmp, 'file', module_args, inject=inject)
fn_orig = fn fnt = template.template(self.runner.basedir, fn, inject) fnd = utils.path_dwim(self.runner.basedir, fnt) if not os.path.exists(fnd) and '_original_file' in inject: fnd = utils.path_dwim_relative(inject['_original_file'], 'files', fnt, self.runner.basedir, check=False) if os.path.exists(fnd): source = fnd found = True break if not found: results = dict(failed=True, msg="could not find src in first_available_file list") return ReturnData(conn=conn, result=results) else: source = template.template(self.runner.basedir, source, inject) if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) # A list of source file tuples (full_path, relative_path) which will try to copy to the destination source_files = [] # If source is a directory populate our list else source is a file and translate it to a tuple. if os.path.isdir(source): # Get the amount of spaces to remove to get the relative path. if source_trailing_slash: sz = len(source) + 1 else: sz = len(source.rsplit('/', 1)[0]) + 1 # Walk the directory and append the file tuples to source_files.
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' if self.runner.noop_on_check(inject): # in check mode, always skip this module return ReturnData(conn=conn, comm_ok=True, result=dict(skipped=True, msg='check mode not supported for this module')) # extract ansible reserved parameters # From library/command keep in sync creates = None removes = None r = re.compile(r'(^|\s)(creates|removes)=(?P<quote>[\'"])?(.*?)(?(quote)(?<!\\)(?P=quote))((?<!\\)(?=\s)|$)') for m in r.finditer(module_args): v = m.group(4).replace("\\", "") if m.group(2) == "creates": creates = v elif m.group(2) == "removes": removes = v module_args = r.sub("", module_args) if creates: # do not run the command if the line contains creates=filename # and the filename already exists. This allows idempotence # of command executions. module_args_tmp = "path=%s" % creates module_return = self.runner._execute_module(conn, tmp, 'stat', module_args_tmp, inject=inject, complex_args=complex_args, persist_files=True) stat = module_return.result.get('stat', None) if stat and stat.get('exists', False): return ReturnData( conn=conn, comm_ok=True, result=dict( skipped=True, msg=("skipped, since %s exists" % creates) ) ) if removes: # do not run the command if the line contains removes=filename # and the filename does not exist. This allows idempotence # of command executions. module_args_tmp = "path=%s" % removes module_return = self.runner._execute_module(conn, tmp, 'stat', module_args_tmp, inject=inject, complex_args=complex_args, persist_files=True) stat = module_return.result.get('stat', None) if stat and not stat.get('exists', False): return ReturnData( conn=conn, comm_ok=True, result=dict( skipped=True, msg=("skipped, since %s does not exist" % removes) ) ) # Decode the result of shlex.split() to UTF8 to get around a bug in that's been fixed in Python 2.7 but not Python 2.6. # See: http://bugs.python.org/issue6988 tokens = shlex.split(module_args.encode('utf8')) tokens = [s.decode('utf8') for s in tokens] # extract source script source = tokens[0] # FIXME: error handling args = " ".join(tokens[1:]) source = template.template(self.runner.basedir, source, inject) if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) # transfer the file to a remote tmp location source = source.replace('\x00', '') # why does this happen here? args = args.replace('\x00', '') # why does this happen here? tmp_src = os.path.join(tmp, os.path.basename(source)) tmp_src = tmp_src.replace('\x00', '') conn.put_file(source, tmp_src) sudoable = True # set file permissions, more permisive when the copy is done as a different user if self.runner.sudo and self.runner.sudo_user != 'root': cmd_args_chmod = "chmod a+rx %s" % tmp_src sudoable = False else: cmd_args_chmod = "chmod +rx %s" % tmp_src self.runner._low_level_exec_command(conn, cmd_args_chmod, tmp, sudoable=sudoable) # add preparation steps to one ssh roundtrip executing the script env_string = self.runner._compute_environment_string(inject) module_args = env_string + tmp_src + ' ' + args handler = utils.plugins.action_loader.get('raw', self.runner) result = handler.run(conn, tmp, 'raw', module_args, inject) # clean up after if tmp.find("tmp") != -1 and not C.DEFAULT_KEEP_REMOTE_FILES: self.runner._low_level_exec_command(conn, 'rm -rf %s >/dev/null 2>&1' % tmp, tmp) result.result['changed'] = True return result
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): ''' handler for file transfer operations ''' # load up options options = {} if complex_args: options.update(complex_args) options.update(utils.parse_kv(module_args)) source = options.get('src', None) content = options.get('content', None) dest = options.get('dest', None) force = utils.boolean(options.get('force', 'yes')) if (source is None and content is None and not 'first_available_file' in inject) or dest is None: result = dict(failed=True, msg="src (or content) and dest are required") return ReturnData(conn=conn, result=result) elif (source is not None or 'first_available_file' in inject) and content is not None: result = dict(failed=True, msg="src and content are mutually exclusive") return ReturnData(conn=conn, result=result) # if we have first_available_file in our vars # look up the files and use the first one we find as src if 'first_available_file' in inject: found = False for fn in inject.get('first_available_file'): fn_orig = fn fn = template.template(self.runner.basedir, fn, inject) fn = utils.path_dwim(self.runner.basedir, fn) if not os.path.exists(fn) and '_original_file' in inject: fn = utils.path_dwim_relative(inject['_original_file'], 'files', fn_orig, self.runner.basedir, check=False) if os.path.exists(fn): source = fn found = True break if not found: results = dict( failed=True, msg="could not find src in first_available_file list") return ReturnData(conn=conn, result=results) elif content is not None: fd, tmp_content = tempfile.mkstemp() f = os.fdopen(fd, 'w') try: f.write(content) except Exception, err: os.remove(tmp_content) result = dict(failed=True, msg="could not write content temp file: %s" % err) return ReturnData(conn=conn, result=result) f.close() source = tmp_content
f = os.fdopen(fd, 'w') try: f.write(content) except Exception, err: os.remove(tmp_content) result = dict(failed=True, msg="could not write content temp file: %s" % err) return ReturnData(conn=conn, result=result) f.close() source = tmp_content else: source = template.template(self.runner.basedir, source, inject) if '_original_file' in inject: source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir) else: source = utils.path_dwim(self.runner.basedir, source) local_md5 = utils.md5(source) if local_md5 is None: result = dict(failed=True, msg="could not find src=%s" % source) return ReturnData(conn=conn, result=result) if dest.endswith("/"): base = os.path.basename(source) dest = os.path.join(dest, base) remote_md5 = self.runner._remote_md5(conn, tmp, dest) if remote_md5 == '3':