def is_available(self): ''' we expect the python bindings installed, but this gives warning if they are missing and we have rpm cli''' we_have_lib = super(RPM, self).is_available() try: get_bin_path('rpm') if not we_have_lib and not has_respawned(): # try to locate an interpreter with the necessary lib interpreters = [ '/usr/libexec/platform-python', '/usr/bin/python3', '/usr/bin/python2' ] interpreter_path = probe_interpreters_for_module( interpreters, self.LIB) if interpreter_path: respawn_module(interpreter_path) # end of the line for this process; this module will exit when the respawned copy completes if not we_have_lib: module.warn('Found "rpm" but %s' % (missing_required_lib(self.LIB))) except ValueError: pass return we_have_lib
def main(): mod = AnsibleModule(argument_spec=dict(mode=dict( required=True, choices=['multi_respawn', 'no_respawn', 'respawn']))) # just return info about what interpreter we're currently running under if mod.params['mode'] == 'no_respawn': mod.exit_json(interpreter_path=sys.executable) elif mod.params['mode'] == 'respawn': if not has_respawned(): new_interpreter = os.path.join(mod.tmpdir, 'anotherpython') os.symlink(sys.executable, new_interpreter) respawn_module(interpreter_path=new_interpreter) # respawn should always exit internally- if we continue executing here, it's a bug raise Exception('FAIL, should never reach this line') else: # return the current interpreter, as well as a signal that we created a different one mod.exit_json(created_interpreter=sys.executable, interpreter_path=sys.executable) elif mod.params['mode'] == 'multi_respawn': # blindly respawn with the current interpreter, the second time should bomb respawn_module(sys.executable) # shouldn't be any way for us to fall through, but just in case, that's also a bug raise Exception('FAIL, should never reach this code')
def main(): module = AnsibleModule( argument_spec=dict( ignore_selinux_state=dict(type='bool', default=False), target=dict(type='str', required=True, aliases=['path']), ftype=dict(type='str', default='a', choices=option_to_file_type_str.keys()), setype=dict(type='str', required=True), seuser=dict(type='str'), selevel=dict(type='str', aliases=['serange']), state=dict(type='str', default='present', choices=['absent', 'present']), reload=dict(type='bool', default=True), ), supports_check_mode=True, ) if not HAVE_SELINUX or not HAVE_SEOBJECT and not has_respawned(): system_interpreters = [ '/usr/libexec/platform-python', '/usr/bin/python3', '/usr/bin/python2', ] # policycoreutils-python depends on libselinux-python interpreter = probe_interpreters_for_module(system_interpreters, 'seobject') if interpreter: respawn_module(interpreter) if not HAVE_SELINUX or not HAVE_SEOBJECT: module.fail_json(msg=missing_required_lib("policycoreutils-python(3)"), exception=SELINUX_IMP_ERR) ignore_selinux_state = module.params['ignore_selinux_state'] if not get_runtime_status(ignore_selinux_state): module.fail_json(msg="SELinux is disabled on this host.") target = module.params['target'] ftype = module.params['ftype'] setype = module.params['setype'] seuser = module.params['seuser'] serange = module.params['selevel'] state = module.params['state'] do_reload = module.params['reload'] result = dict(target=target, ftype=ftype, setype=setype, state=state) if state == 'present': semanage_fcontext_modify(module, result, target, ftype, setype, do_reload, serange, seuser) elif state == 'absent': semanage_fcontext_delete(module, result, target, ftype, do_reload) else: module.fail_json( msg='Invalid value of argument "state": {0}'.format(state))
def main(): module = AnsibleModule(argument_spec={ 'arch': { 'required': True }, 'tempdir': { 'type': 'path' }, }) if not HAS_RPMFLUFF: system_interpreters = [ '/usr/libexec/platform-python', '/usr/bin/python3', '/usr/bin/python' ] interpreter = probe_interpreters_for_module(system_interpreters, 'rpmfluff') if not interpreter or has_respawned(): module.fail_json('unable to find rpmfluff; tried {0}'.format( system_interpreters)) respawn_module(interpreter) arch = module.params['arch'] tempdir = module.params['tempdir'] # Save current temp dir so we can set it back later original_tempdir = tempfile.tempdir tempfile.tempdir = tempdir try: repo_dir = create_repo(arch) finally: tempfile.tempdir = original_tempdir module.exit_json(repo_dir=repo_dir, tmpfile=tempfile.gettempdir())
def is_available(self): ''' we expect the python bindings installed, but if there is apt/apt-get give warning about missing bindings''' we_have_lib = super(APT, self).is_available() if not we_have_lib: for exe in ('apt', 'apt-get', 'aptitude'): try: get_bin_path(exe) except ValueError: continue else: if not has_respawned(): # try to locate an interpreter with the necessary lib interpreters = ['/usr/bin/python3', '/usr/bin/python2'] interpreter_path = probe_interpreters_for_module(interpreters, self.LIB) if interpreter_path: respawn_module(interpreter_path) # end of the line for this process; this module will exit here when respawned copy completes module.warn('Found "%s" but %s' % (exe, missing_required_lib('apt'))) break return we_have_lib
def main(): module = AnsibleModule( argument_spec=dict( state=dict(type='str', default='present', choices=['absent', 'build-dep', 'fixed', 'latest', 'present']), update_cache=dict(type='bool', aliases=['update-cache']), update_cache_retries=dict(type='int', default=5), update_cache_retry_max_delay=dict(type='int', default=12), cache_valid_time=dict(type='int', default=0), purge=dict(type='bool', default=False), package=dict(type='list', elements='str', aliases=['pkg', 'name']), deb=dict(type='path'), default_release=dict(type='str', aliases=['default-release']), install_recommends=dict(type='bool', aliases=['install-recommends']), force=dict(type='bool', default=False), upgrade=dict(type='str', choices=['dist', 'full', 'no', 'safe', 'yes'], default='no'), dpkg_options=dict(type='str', default=DPKG_OPTIONS), autoremove=dict(type='bool', default=False), autoclean=dict(type='bool', default=False), fail_on_autoremove=dict(type='bool', default=False), policy_rc_d=dict(type='int', default=None), only_upgrade=dict(type='bool', default=False), force_apt_get=dict(type='bool', default=False), allow_unauthenticated=dict(type='bool', default=False, aliases=['allow-unauthenticated']), ), mutually_exclusive=[['deb', 'package', 'upgrade']], required_one_of=[['autoremove', 'deb', 'package', 'update_cache', 'upgrade']], supports_check_mode=True, ) module.run_command_environ_update = APT_ENV_VARS if not HAS_PYTHON_APT: # This interpreter can't see the apt Python library- we'll do the following to try and fix that: # 1) look in common locations for system-owned interpreters that can see it; if we find one, respawn under it # 2) finding none, try to install a matching python-apt package for the current interpreter version; # we limit to the current interpreter version to try and avoid installing a whole other Python just # for apt support # 3) if we installed a support package, try to respawn under what we think is the right interpreter (could be # the current interpreter again, but we'll let it respawn anyway for simplicity) # 4) if still not working, return an error and give up (some corner cases not covered, but this shouldn't be # made any more complex than it already is to try and cover more, eg, custom interpreters taking over # system locations) apt_pkg_name = 'python3-apt' if PY3 else 'python-apt' if has_respawned(): # this shouldn't be possible; short-circuit early if it happens... module.fail_json(msg="{0} must be installed and visible from {1}.".format(apt_pkg_name, sys.executable)) interpreters = ['/usr/bin/python3', '/usr/bin/python2', '/usr/bin/python'] interpreter = probe_interpreters_for_module(interpreters, 'apt') if interpreter: # found the Python bindings; respawn this module under the interpreter where we found them respawn_module(interpreter) # this is the end of the line for this process, it will exit here once the respawned module has completed # don't make changes if we're in check_mode if module.check_mode: module.fail_json(msg="%s must be installed to use check mode. " "If run normally this module can auto-install it." % apt_pkg_name) # We skip cache update in auto install the dependency if the # user explicitly declared it with update_cache=no. if module.params.get('update_cache') is False: module.warn("Auto-installing missing dependency without updating cache: %s" % apt_pkg_name) else: module.warn("Updating cache and auto-installing missing dependency: %s" % apt_pkg_name) module.run_command(['apt-get', 'update'], check_rc=True) # try to install the apt Python binding module.run_command(['apt-get', 'install', '--no-install-recommends', apt_pkg_name, '-y', '-q'], check_rc=True) # try again to find the bindings in common places interpreter = probe_interpreters_for_module(interpreters, 'apt') if interpreter: # found the Python bindings; respawn this module under the interpreter where we found them # NB: respawn is somewhat wasteful if it's this interpreter, but simplifies the code respawn_module(interpreter) # this is the end of the line for this process, it will exit here once the respawned module has completed else: # we've done all we can do; just tell the user it's busted and get out module.fail_json(msg="{0} must be installed and visible from {1}.".format(apt_pkg_name, sys.executable)) global APTITUDE_CMD APTITUDE_CMD = module.get_bin_path("aptitude", False) global APT_GET_CMD APT_GET_CMD = module.get_bin_path("apt-get") p = module.params if p['upgrade'] == 'no': p['upgrade'] = None use_apt_get = p['force_apt_get'] if not use_apt_get and not APTITUDE_CMD: use_apt_get = True updated_cache = False updated_cache_time = 0 install_recommends = p['install_recommends'] allow_unauthenticated = p['allow_unauthenticated'] dpkg_options = expand_dpkg_options(p['dpkg_options']) autoremove = p['autoremove'] fail_on_autoremove = p['fail_on_autoremove'] autoclean = p['autoclean'] # Get the cache object cache = get_cache(module) try: if p['default_release']: try: apt_pkg.config['APT::Default-Release'] = p['default_release'] except AttributeError: apt_pkg.Config['APT::Default-Release'] = p['default_release'] # reopen cache w/ modified config cache.open(progress=None) mtimestamp, updated_cache_time = get_updated_cache_time() # Cache valid time is default 0, which will update the cache if # needed and `update_cache` was set to true updated_cache = False if p['update_cache'] or p['cache_valid_time']: now = datetime.datetime.now() tdelta = datetime.timedelta(seconds=p['cache_valid_time']) if not mtimestamp + tdelta >= now: # Retry to update the cache with exponential backoff err = '' update_cache_retries = module.params.get('update_cache_retries') update_cache_retry_max_delay = module.params.get('update_cache_retry_max_delay') randomize = random.randint(0, 1000) / 1000.0 for retry in range(update_cache_retries): try: cache.update() break except apt.cache.FetchFailedException as e: err = to_native(e) # Use exponential backoff plus a little bit of randomness delay = 2 ** retry + randomize if delay > update_cache_retry_max_delay: delay = update_cache_retry_max_delay + randomize time.sleep(delay) else: module.fail_json(msg='Failed to update apt cache: %s' % (err if err else 'unknown reason')) cache.open(progress=None) mtimestamp, post_cache_update_time = get_updated_cache_time() if updated_cache_time != post_cache_update_time: updated_cache = True updated_cache_time = post_cache_update_time # If there is nothing else to do exit. This will set state as # changed based on if the cache was updated. if not p['package'] and not p['upgrade'] and not p['deb']: module.exit_json( changed=updated_cache, cache_updated=updated_cache, cache_update_time=updated_cache_time ) force_yes = p['force'] if p['upgrade']: upgrade(module, p['upgrade'], force_yes, p['default_release'], use_apt_get, dpkg_options, autoremove, fail_on_autoremove, allow_unauthenticated) if p['deb']: if p['state'] != 'present': module.fail_json(msg="deb only supports state=present") if '://' in p['deb']: p['deb'] = fetch_file(module, p['deb']) install_deb(module, p['deb'], cache, install_recommends=install_recommends, allow_unauthenticated=allow_unauthenticated, force=force_yes, fail_on_autoremove=fail_on_autoremove, dpkg_options=p['dpkg_options']) unfiltered_packages = p['package'] or () packages = [package.strip() for package in unfiltered_packages if package != '*'] all_installed = '*' in unfiltered_packages latest = p['state'] == 'latest' if latest and all_installed: if packages: module.fail_json(msg='unable to install additional packages when upgrading all installed packages') upgrade(module, 'yes', force_yes, p['default_release'], use_apt_get, dpkg_options, autoremove, fail_on_autoremove, allow_unauthenticated) if packages: for package in packages: if package.count('=') > 1: module.fail_json(msg="invalid package spec: %s" % package) if latest and '=' in package: module.fail_json(msg='version number inconsistent with state=latest: %s' % package) if not packages: if autoclean: cleanup(module, p['purge'], force=force_yes, operation='autoclean', dpkg_options=dpkg_options) if autoremove: cleanup(module, p['purge'], force=force_yes, operation='autoremove', dpkg_options=dpkg_options) if p['state'] in ('latest', 'present', 'build-dep', 'fixed'): state_upgrade = False state_builddep = False state_fixed = False if p['state'] == 'latest': state_upgrade = True if p['state'] == 'build-dep': state_builddep = True if p['state'] == 'fixed': state_fixed = True success, retvals = install( module, packages, cache, upgrade=state_upgrade, default_release=p['default_release'], install_recommends=install_recommends, force=force_yes, dpkg_options=dpkg_options, build_dep=state_builddep, fixed=state_fixed, autoremove=autoremove, fail_on_autoremove=fail_on_autoremove, only_upgrade=p['only_upgrade'], allow_unauthenticated=allow_unauthenticated ) # Store if the cache has been updated retvals['cache_updated'] = updated_cache # Store when the update time was last retvals['cache_update_time'] = updated_cache_time if success: module.exit_json(**retvals) else: module.fail_json(**retvals) elif p['state'] == 'absent': remove(module, packages, cache, p['purge'], force=force_yes, dpkg_options=dpkg_options, autoremove=autoremove) except apt.cache.LockFailedException as lockFailedException: module.fail_json(msg="Failed to lock apt for exclusive operation: %s" % lockFailedException) except apt.cache.FetchFailedException as fetchFailedException: module.fail_json(msg="Could not fetch updated apt files: %s" % fetchFailedException)
def main(): module = AnsibleModule( argument_spec=dict( repo=dict(type='str', required=True), state=dict(type='str', default='present', choices=['absent', 'present']), mode=dict(type='raw'), update_cache=dict(type='bool', default=True, aliases=['update-cache']), update_cache_retries=dict(type='int', default=5), update_cache_retry_max_delay=dict(type='int', default=12), filename=dict(type='str'), # This should not be needed, but exists as a failsafe install_python_apt=dict(type='bool', default=True), validate_certs=dict(type='bool', default=True), codename=dict(type='str'), ), supports_check_mode=True, ) params = module.params repo = module.params['repo'] state = module.params['state'] update_cache = module.params['update_cache'] # Note: mode is referenced in SourcesList class via the passed in module (self here) sourceslist = None if not HAVE_PYTHON_APT: # This interpreter can't see the apt Python library- we'll do the following to try and fix that: # 1) look in common locations for system-owned interpreters that can see it; if we find one, respawn under it # 2) finding none, try to install a matching python-apt package for the current interpreter version; # we limit to the current interpreter version to try and avoid installing a whole other Python just # for apt support # 3) if we installed a support package, try to respawn under what we think is the right interpreter (could be # the current interpreter again, but we'll let it respawn anyway for simplicity) # 4) if still not working, return an error and give up (some corner cases not covered, but this shouldn't be # made any more complex than it already is to try and cover more, eg, custom interpreters taking over # system locations) apt_pkg_name = 'python3-apt' if PY3 else 'python-apt' if has_respawned(): # this shouldn't be possible; short-circuit early if it happens... module.fail_json( msg="{0} must be installed and visible from {1}.".format( apt_pkg_name, sys.executable)) interpreters = [ '/usr/bin/python3', '/usr/bin/python2', '/usr/bin/python' ] interpreter = probe_interpreters_for_module(interpreters, 'apt') if interpreter: # found the Python bindings; respawn this module under the interpreter where we found them respawn_module(interpreter) # this is the end of the line for this process, it will exit here once the respawned module has completed # don't make changes if we're in check_mode if module.check_mode: module.fail_json( msg="%s must be installed to use check mode. " "If run normally this module can auto-install it." % apt_pkg_name) if params['install_python_apt']: install_python_apt(module, apt_pkg_name) else: module.fail_json( msg='%s is not installed, and install_python_apt is False' % apt_pkg_name) # try again to find the bindings in common places interpreter = probe_interpreters_for_module(interpreters, 'apt') if interpreter: # found the Python bindings; respawn this module under the interpreter where we found them # NB: respawn is somewhat wasteful if it's this interpreter, but simplifies the code respawn_module(interpreter) # this is the end of the line for this process, it will exit here once the respawned module has completed else: # we've done all we can do; just tell the user it's busted and get out module.fail_json( msg="{0} must be installed and visible from {1}.".format( apt_pkg_name, sys.executable)) if not repo: module.fail_json( msg='Please set argument \'repo\' to a non-empty value') if isinstance(distro, aptsources_distro.Distribution): sourceslist = UbuntuSourcesList( module, add_ppa_signing_keys_callback=get_add_ppa_signing_key_callback( module)) else: module.fail_json( msg='Module apt_repository is not supported on target.') sourceslist_before = copy.deepcopy(sourceslist) sources_before = sourceslist.dump() try: if state == 'present': sourceslist.add_source(repo) elif state == 'absent': sourceslist.remove_source(repo) except InvalidSource as err: module.fail_json(msg='Invalid repository string: %s' % to_native(err)) sources_after = sourceslist.dump() changed = sources_before != sources_after if changed and module._diff: diff = [] for filename in set(sources_before.keys()).union(sources_after.keys()): diff.append({ 'before': sources_before.get(filename, ''), 'after': sources_after.get(filename, ''), 'before_header': (filename, '/dev/null')[filename not in sources_before], 'after_header': (filename, '/dev/null')[filename not in sources_after] }) else: diff = {} if changed and not module.check_mode: try: sourceslist.save() if update_cache: err = '' update_cache_retries = module.params.get( 'update_cache_retries') update_cache_retry_max_delay = module.params.get( 'update_cache_retry_max_delay') randomize = random.randint(0, 1000) / 1000.0 for retry in range(update_cache_retries): try: cache = apt.Cache() cache.update() break except apt.cache.FetchFailedException as e: err = to_native(e) # Use exponential backoff with a max fail count, plus a little bit of randomness delay = 2**retry + randomize if delay > update_cache_retry_max_delay: delay = update_cache_retry_max_delay + randomize time.sleep(delay) else: revert_sources_list(sources_before, sources_after, sourceslist_before) module.fail_json(msg='Failed to update apt cache: %s' % (err if err else 'unknown reason')) except (OSError, IOError) as err: revert_sources_list(sources_before, sources_after, sourceslist_before) module.fail_json(msg=to_native(err)) module.exit_json(changed=changed, repo=repo, state=state, diff=diff)