def main(): module = AssibleModule( argument_spec=dict( name=dict(required=True), selection=dict(choices=['install', 'hold', 'deinstall', 'purge'], required=True)), supports_check_mode=True, ) dpkg = module.get_bin_path('dpkg', True) name = module.params['name'] selection = module.params['selection'] # Get current settings. rc, out, err = module.run_command([dpkg, '--get-selections', name], check_rc=True) if not out: current = 'not present' else: current = out.split()[1] changed = current != selection if module.check_mode or not changed: module.exit_json(changed=changed, before=current, after=selection) module.run_command([dpkg, '--set-selections'], data="%s %s" % (name, selection), check_rc=True) module.exit_json(changed=changed, before=current, after=selection)
def main(): module = AssibleModule( argument_spec=dict( database=dict(type='str', required=True), key=dict(type='str'), service=dict(type='str'), split=dict(type='str'), fail_key=dict(type='bool', default=True), ), supports_check_mode=True, ) colon = ['passwd', 'shadow', 'group', 'gshadow'] database = module.params['database'] key = module.params.get('key') split = module.params.get('split') service = module.params.get('service') fail_key = module.params.get('fail_key') getent_bin = module.get_bin_path('getent', True) if key is not None: cmd = [getent_bin, database, key] else: cmd = [getent_bin, database] if service is not None: cmd.extend(['-s', service]) if split is None and database in colon: split = ':' try: rc, out, err = module.run_command(cmd) except Exception as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) msg = "Unexpected failure!" dbtree = 'getent_%s' % database results = {dbtree: {}} if rc == 0: for line in out.splitlines(): record = line.split(split) results[dbtree][record[0]] = record[1:] module.exit_json(assible_facts=results) elif rc == 1: msg = "Missing arguments, or database unknown." elif rc == 2: msg = "One or more supplied key could not be found in the database." if not fail_key: results[dbtree][key] = None module.exit_json(assible_facts=results, msg=msg) elif rc == 3: msg = "Enumeration not supported on this database." module.fail_json(msg=msg)
def main(): module = AssibleModule( argument_spec=dict( state=dict(default="present", choices=["present", "latest", "absent"], required=False), name=dict(aliases=["pkg"], required=True, type='list'), cached=dict(default=False, type='bool'), annotation=dict(default="", required=False), pkgsite=dict(default="", required=False), rootdir=dict(default="", required=False, type='path'), chroot=dict(default="", required=False, type='path'), jail=dict(default="", required=False, type='str'), autoremove=dict(default=False, type='bool')), supports_check_mode=True, mutually_exclusive=[["rootdir", "chroot", "jail"]]) pkgng_path = module.get_bin_path('pkg', True) p = module.params pkgs = p["name"] changed = False msgs = [] dir_arg = "" if p["rootdir"] != "": old_pkgng = pkgng_older_than(module, pkgng_path, [1, 5, 0]) if old_pkgng: module.fail_json(msg="To use option 'rootdir' pkg version must be 1.5 or greater") else: dir_arg = "--rootdir %s" % (p["rootdir"]) if p["chroot"] != "": dir_arg = '--chroot %s' % (p["chroot"]) if p["jail"] != "": dir_arg = '--jail %s' % (p["jail"]) if p["state"] in ("present", "latest"): _changed, _msg = install_packages(module, pkgng_path, pkgs, p["cached"], p["pkgsite"], dir_arg, p["state"]) changed = changed or _changed msgs.append(_msg) elif p["state"] == "absent": _changed, _msg = remove_packages(module, pkgng_path, pkgs, dir_arg) changed = changed or _changed msgs.append(_msg) if p["autoremove"]: _changed, _msg = autoremove_packages(module, pkgng_path, dir_arg) changed = changed or _changed msgs.append(_msg) if p["annotation"]: _changed, _msg = annotate_packages(module, pkgng_path, pkgs, p["annotation"], dir_arg) changed = changed or _changed msgs.append(_msg) module.exit_json(changed=changed, msg=", ".join(msgs))
def test_sanity_check(self): basic._load_params = lambda: {} # Module used internally to execute ssh-keygen system executable module = AssibleModule(argument_spec={}) host = '10.0.0.1' key = '%s ssh-rsa ASDF foo@bar' % (host, ) keygen = module.get_bin_path('ssh-keygen') sanity_check(module, host, key, keygen)
def main(): module = AssibleModule( supports_check_mode=True, argument_spec=dict( table=dict(type='str', default='filter', choices=['filter', 'nat', 'mangle', 'raw', 'security']), state=dict(type='str', default='present', choices=['absent', 'present']), action=dict(type='str', default='append', choices=['append', 'insert']), ip_version=dict(type='str', default='ipv4', choices=['ipv4', 'ipv6']), chain=dict(type='str'), rule_num=dict(type='str'), protocol=dict(type='str'), wait=dict(type='str'), source=dict(type='str'), to_source=dict(type='str'), destination=dict(type='str'), to_destination=dict(type='str'), match=dict(type='list', elements='str', default=[]), tcp_flags=dict(type='dict', options=dict(flags=dict(type='list', elements='str'), flags_set=dict(type='list', elements='str'))), jump=dict(type='str'), gateway=dict(type='str'), log_prefix=dict(type='str'), log_level=dict( type='str', choices=[ '0', '1', '2', '3', '4', '5', '6', '7', 'emerg', 'alert', 'crit', 'error', 'warning', 'notice', 'info', 'debug' ], default=None, ), goto=dict(type='str'), in_interface=dict(type='str'), out_interface=dict(type='str'), fragment=dict(type='str'), set_counters=dict(type='str'), source_port=dict(type='str'), destination_port=dict(type='str'), to_ports=dict(type='str'), set_dscp_mark=dict(type='str'), set_dscp_mark_class=dict(type='str'), comment=dict(type='str'), ctstate=dict(type='list', elements='str', default=[]), src_range=dict(type='str'), dst_range=dict(type='str'), limit=dict(type='str'), limit_burst=dict(type='str'), uid_owner=dict(type='str'), gid_owner=dict(type='str'), reject_with=dict(type='str'), icmp_type=dict(type='str'), syn=dict(type='str', default='ignore', choices=['ignore', 'match', 'negate']), flush=dict(type='bool', default=False), policy=dict(type='str', choices=['ACCEPT', 'DROP', 'QUEUE', 'RETURN']), ), mutually_exclusive=( ['set_dscp_mark', 'set_dscp_mark_class'], ['flush', 'policy'], ), required_if=[ ['jump', 'TEE', ['gateway']], ['jump', 'tee', ['gateway']], ]) args = dict( changed=False, failed=False, ip_version=module.params['ip_version'], table=module.params['table'], chain=module.params['chain'], flush=module.params['flush'], rule=' '.join(construct_rule(module.params)), state=module.params['state'], ) ip_version = module.params['ip_version'] iptables_path = module.get_bin_path(BINS[ip_version], True) # Check if chain option is required if args['flush'] is False and args['chain'] is None: module.fail_json( msg="Either chain or flush parameter must be specified.") if module.params.get('log_prefix', None) or module.params.get( 'log_level', None): if module.params['jump'] is None: module.params['jump'] = 'LOG' elif module.params['jump'] != 'LOG': module.fail_json( msg="Logging options can only be used with the LOG jump target." ) # Check if wait option is supported iptables_version = LooseVersion(get_iptables_version( iptables_path, module)) if iptables_version >= LooseVersion(IPTABLES_WAIT_SUPPORT_ADDED): if iptables_version < LooseVersion( IPTABLES_WAIT_WITH_SECONDS_SUPPORT_ADDED): module.params['wait'] = '' else: module.params['wait'] = None # Flush the table if args['flush'] is True: args['changed'] = True if not module.check_mode: flush_table(iptables_path, module, module.params) # Set the policy elif module.params['policy']: current_policy = get_chain_policy(iptables_path, module, module.params) if not current_policy: module.fail_json(msg='Can\'t detect current policy') changed = current_policy != module.params['policy'] args['changed'] = changed if changed and not module.check_mode: set_chain_policy(iptables_path, module, module.params) else: insert = (module.params['action'] == 'insert') rule_is_present = check_present(iptables_path, module, module.params) should_be_present = (args['state'] == 'present') # Check if target is up to date args['changed'] = (rule_is_present != should_be_present) if args['changed'] is False: # Target is already up to date module.exit_json(**args) # Check only; don't modify if not module.check_mode: if should_be_present: if insert: insert_rule(iptables_path, module, module.params) else: append_rule(iptables_path, module, module.params) else: remove_rule(iptables_path, module, module.params) module.exit_json(**args)
def main(): module = AssibleModule( argument_spec=dict( vg=dict(type='str', required=True), pvs=dict(type='list'), pesize=dict(type='str', default='4'), pv_options=dict(type='str', default=''), vg_options=dict(type='str', default=''), state=dict(type='str', default='present', choices=['absent', 'present']), force=dict(type='bool', default=False), ), supports_check_mode=True, ) vg = module.params['vg'] state = module.params['state'] force = module.boolean(module.params['force']) pesize = module.params['pesize'] pvoptions = module.params['pv_options'].split() vgoptions = module.params['vg_options'].split() dev_list = [] if module.params['pvs']: dev_list = list(module.params['pvs']) elif state == 'present': module.fail_json(msg="No physical volumes given.") # LVM always uses real paths not symlinks so replace symlinks with actual path for idx, dev in enumerate(dev_list): dev_list[idx] = os.path.realpath(dev) if state == 'present': # check given devices for test_dev in dev_list: if not os.path.exists(test_dev): module.fail_json(msg="Device %s not found." % test_dev) # get pv list pvs_cmd = module.get_bin_path('pvs', True) if dev_list: pvs_filter_pv_name = ' || '.join( 'pv_name = {0}'.format(x) for x in itertools.chain(dev_list, module.params['pvs'])) pvs_filter_vg_name = 'vg_name = {0}'.format(vg) pvs_filter = "--select '{0} || {1}' ".format( pvs_filter_pv_name, pvs_filter_vg_name) else: pvs_filter = '' rc, current_pvs, err = module.run_command( "%s --noheadings -o pv_name,vg_name --separator ';' %s" % (pvs_cmd, pvs_filter)) if rc != 0: module.fail_json(msg="Failed executing pvs command.", rc=rc, err=err) # check pv for devices pvs = parse_pvs(module, current_pvs) used_pvs = [ pv for pv in pvs if pv['name'] in dev_list and pv['vg_name'] and pv['vg_name'] != vg ] if used_pvs: module.fail_json(msg="Device %s is already in %s volume group." % (used_pvs[0]['name'], used_pvs[0]['vg_name'])) vgs_cmd = module.get_bin_path('vgs', True) rc, current_vgs, err = module.run_command( "%s --noheadings -o vg_name,pv_count,lv_count --separator ';'" % vgs_cmd) if rc != 0: module.fail_json(msg="Failed executing vgs command.", rc=rc, err=err) changed = False vgs = parse_vgs(current_vgs) for test_vg in vgs: if test_vg['name'] == vg: this_vg = test_vg break else: this_vg = None if this_vg is None: if state == 'present': # create VG if module.check_mode: changed = True else: # create PV pvcreate_cmd = module.get_bin_path('pvcreate', True) for current_dev in dev_list: rc, _, err = module.run_command( [pvcreate_cmd] + pvoptions + ['-f', str(current_dev)]) if rc == 0: changed = True else: module.fail_json( msg="Creating physical volume '%s' failed" % current_dev, rc=rc, err=err) vgcreate_cmd = module.get_bin_path('vgcreate') rc, _, err = module.run_command([vgcreate_cmd] + vgoptions + ['-s', pesize, vg] + dev_list) if rc == 0: changed = True else: module.fail_json(msg="Creating volume group '%s' failed" % vg, rc=rc, err=err) else: if state == 'absent': if module.check_mode: module.exit_json(changed=True) else: if this_vg['lv_count'] == 0 or force: # remove VG vgremove_cmd = module.get_bin_path('vgremove', True) rc, _, err = module.run_command("%s --force %s" % (vgremove_cmd, vg)) if rc == 0: module.exit_json(changed=True) else: module.fail_json( msg="Failed to remove volume group %s" % (vg), rc=rc, err=err) else: module.fail_json( msg= "Refuse to remove non-empty volume group %s without force=yes" % (vg)) # resize VG current_devs = [ os.path.realpath(pv['name']) for pv in pvs if pv['vg_name'] == vg ] devs_to_remove = list(set(current_devs) - set(dev_list)) devs_to_add = list(set(dev_list) - set(current_devs)) if devs_to_add or devs_to_remove: if module.check_mode: changed = True else: if devs_to_add: devs_to_add_string = ' '.join(devs_to_add) # create PV pvcreate_cmd = module.get_bin_path('pvcreate', True) for current_dev in devs_to_add: rc, _, err = module.run_command( [pvcreate_cmd] + pvoptions + ['-f', str(current_dev)]) if rc == 0: changed = True else: module.fail_json( msg="Creating physical volume '%s' failed" % current_dev, rc=rc, err=err) # add PV to our VG vgextend_cmd = module.get_bin_path('vgextend', True) rc, _, err = module.run_command( "%s %s %s" % (vgextend_cmd, vg, devs_to_add_string)) if rc == 0: changed = True else: module.fail_json(msg="Unable to extend %s by %s." % (vg, devs_to_add_string), rc=rc, err=err) # remove some PV from our VG if devs_to_remove: devs_to_remove_string = ' '.join(devs_to_remove) vgreduce_cmd = module.get_bin_path('vgreduce', True) rc, _, err = module.run_command( "%s --force %s %s" % (vgreduce_cmd, vg, devs_to_remove_string)) if rc == 0: changed = True else: module.fail_json(msg="Unable to reduce %s by %s." % (vg, devs_to_remove_string), rc=rc, err=err) module.exit_json(changed=changed)
def main(): module = AssibleModule( argument_spec=dict( name=dict(required=True, type='str', aliases=['service']), state=dict(choices=['started', 'stopped', 'restarted', 'reloaded'], type='str'), enabled=dict(type='bool'), sleep=dict(type='int', default=1), pattern=dict(type='str'), arguments=dict(type='str', aliases=['args']), runlevels=dict(type='list', elements='str'), daemonize=dict(type='bool', default=False), ), supports_check_mode=True, required_one_of=[['state', 'enabled']], ) name = module.params['name'] action = module.params['state'] enabled = module.params['enabled'] runlevels = module.params['runlevels'] pattern = module.params['pattern'] sleep_for = module.params['sleep'] rc = 0 out = err = '' result = { 'name': name, 'changed': False, 'status': {} } # ensure service exists, get script name fail_if_missing(module, sysv_exists(name), name) script = get_sysv_script(name) # locate binaries for service management paths = ['/sbin', '/usr/sbin', '/bin', '/usr/bin'] binaries = ['chkconfig', 'update-rc.d', 'insserv', 'service'] # Keeps track of the service status for various runlevels because we can # operate on multiple runlevels at once runlevel_status = {} location = {} for binary in binaries: location[binary] = module.get_bin_path(binary, opt_dirs=paths) # figure out enable status if runlevels: for rl in runlevels: runlevel_status.setdefault(rl, {}) runlevel_status[rl]["enabled"] = sysv_is_enabled(name, runlevel=rl) else: runlevel_status["enabled"] = sysv_is_enabled(name) # figure out started status, everyone does it different! is_started = False worked = False # user knows other methods fail and supplied pattern if pattern: worked = is_started = get_ps(module, pattern) else: if location.get('service'): # standard tool that has been 'destandarized' by reimplementation in other OS/distros cmd = '%s %s status' % (location['service'], name) elif script: # maybe script implements status (not LSB) cmd = '%s status' % script else: module.fail_json(msg="Unable to determine service status") (rc, out, err) = module.run_command(cmd) if not rc == -1: # special case if name == 'iptables' and "ACCEPT" in out: worked = True is_started = True # check output messages, messy but sadly more reliable than rc if not worked and out.count('\n') <= 1: cleanout = out.lower().replace(name.lower(), '') for stopped in ['stop', 'is dead ', 'dead but ', 'could not access pid file', 'inactive']: if stopped in cleanout: worked = True break if not worked: for started_status in ['run', 'start', 'active']: if started_status in cleanout and "not " not in cleanout: is_started = True worked = True break # hope rc is not lying to us, use often used 'bad' returns if not worked and rc in [1, 2, 3, 4, 69]: worked = True if not worked: # hail mary if rc == 0: is_started = True worked = True # ps for luck, can only assure positive match elif get_ps(module, name): is_started = True worked = True module.warn("Used ps output to match service name and determine it is up, this is very unreliable") if not worked: module.warn("Unable to determine if service is up, assuming it is down") ########################################################################### # BEGIN: Enable/Disable result['status'].setdefault('enabled', {}) result['status']['enabled']['changed'] = False result['status']['enabled']['rc'] = None result['status']['enabled']['stdout'] = None result['status']['enabled']['stderr'] = None if runlevels: result['status']['enabled']['runlevels'] = runlevels for rl in runlevels: if enabled != runlevel_status[rl]["enabled"]: result['changed'] = True result['status']['enabled']['changed'] = True if not module.check_mode and result['changed']: # Perform enable/disable here if enabled: if location.get('update-rc.d'): (rc, out, err) = module.run_command("%s %s enable %s" % (location['update-rc.d'], name, ' '.join(runlevels))) elif location.get('chkconfig'): (rc, out, err) = module.run_command("%s --level %s %s on" % (location['chkconfig'], ''.join(runlevels), name)) else: if location.get('update-rc.d'): (rc, out, err) = module.run_command("%s %s disable %s" % (location['update-rc.d'], name, ' '.join(runlevels))) elif location.get('chkconfig'): (rc, out, err) = module.run_command("%s --level %s %s off" % (location['chkconfig'], ''.join(runlevels), name)) else: if enabled is not None and enabled != runlevel_status["enabled"]: result['changed'] = True result['status']['enabled']['changed'] = True if not module.check_mode and result['changed']: # Perform enable/disable here if enabled: if location.get('update-rc.d'): (rc, out, err) = module.run_command("%s %s defaults" % (location['update-rc.d'], name)) elif location.get('chkconfig'): (rc, out, err) = module.run_command("%s %s on" % (location['chkconfig'], name)) else: if location.get('update-rc.d'): (rc, out, err) = module.run_command("%s %s disable" % (location['update-rc.d'], name)) elif location.get('chkconfig'): (rc, out, err) = module.run_command("%s %s off" % (location['chkconfig'], name)) # Assigned above, might be useful is something goes sideways if not module.check_mode and result['status']['enabled']['changed']: result['status']['enabled']['rc'] = rc result['status']['enabled']['stdout'] = out result['status']['enabled']['stderr'] = err rc, out, err = None, None, None if "illegal runlevel specified" in result['status']['enabled']['stderr']: module.fail_json(msg="Illegal runlevel specified for enable operation on service %s" % name, **result) # END: Enable/Disable ########################################################################### ########################################################################### # BEGIN: state result['status'].setdefault(module.params['state'], {}) result['status'][module.params['state']]['changed'] = False result['status'][module.params['state']]['rc'] = None result['status'][module.params['state']]['stdout'] = None result['status'][module.params['state']]['stderr'] = None if action: action = re.sub(r'p?ed$', '', action.lower()) def runme(doit): args = module.params['arguments'] cmd = "%s %s %s" % (script, doit, "" if args is None else args) # how to run if module.params['daemonize']: (rc, out, err) = daemonize(module, cmd) else: (rc, out, err) = module.run_command(cmd) # FIXME: ERRORS if rc != 0: module.fail_json(msg="Failed to %s service: %s" % (action, name), rc=rc, stdout=out, stderr=err) return (rc, out, err) if action == 'restart': result['changed'] = True result['status'][module.params['state']]['changed'] = True if not module.check_mode: # cannot rely on existing 'restart' in init script for dothis in ['stop', 'start']: (rc, out, err) = runme(dothis) if sleep_for: sleep(sleep_for) elif is_started != (action == 'start'): result['changed'] = True result['status'][module.params['state']]['changed'] = True if not module.check_mode: rc, out, err = runme(action) elif is_started == (action == 'stop'): result['changed'] = True result['status'][module.params['state']]['changed'] = True if not module.check_mode: rc, out, err = runme(action) if not module.check_mode and result['status'][module.params['state']]['changed']: result['status'][module.params['state']]['rc'] = rc result['status'][module.params['state']]['stdout'] = out result['status'][module.params['state']]['stderr'] = err rc, out, err = None, None, None # END: state ########################################################################### module.exit_json(**result)
def main(): # initialize module = AssibleModule( argument_spec=dict( name=dict(type='str', aliases=['service', 'unit']), state=dict(type='str', choices=['reloaded', 'restarted', 'started', 'stopped']), enabled=dict(type='bool'), force=dict(type='bool'), masked=dict(type='bool'), daemon_reload=dict(type='bool', default=False, aliases=['daemon-reload']), daemon_reexec=dict(type='bool', default=False, aliases=['daemon-reexec']), scope=dict(type='str', default='system', choices=['system', 'user', 'global']), no_block=dict(type='bool', default=False), ), supports_check_mode=True, required_one_of=[[ 'state', 'enabled', 'masked', 'daemon_reload', 'daemon_reexec' ]], required_by=dict( state=('name', ), enabled=('name', ), masked=('name', ), ), ) unit = module.params['name'] if unit is not None: for globpattern in (r"*", r"?", r"["): if globpattern in unit: module.fail_json( msg= "This module does not currently support using glob patterns, found '%s' in service name: %s" % (globpattern, unit)) systemctl = module.get_bin_path('systemctl', True) if os.getenv('XDG_RUNTIME_DIR') is None: os.environ['XDG_RUNTIME_DIR'] = '/run/user/%s' % os.geteuid() ''' Set CLI options depending on params ''' # if scope is 'system' or None, we can ignore as there is no extra switch. # The other choices match the corresponding switch if module.params['scope'] != 'system': systemctl += " --%s" % module.params['scope'] if module.params['no_block']: systemctl += " --no-block" if module.params['force']: systemctl += " --force" rc = 0 out = err = '' result = dict( name=unit, changed=False, status=dict(), ) # Run daemon-reload first, if requested if module.params['daemon_reload'] and not module.check_mode: (rc, out, err) = module.run_command("%s daemon-reload" % (systemctl)) if rc != 0: module.fail_json(msg='failure %d during daemon-reload: %s' % (rc, err)) # Run daemon-reexec if module.params['daemon_reexec'] and not module.check_mode: (rc, out, err) = module.run_command("%s daemon-reexec" % (systemctl)) if rc != 0: module.fail_json(msg='failure %d during daemon-reexec: %s' % (rc, err)) if unit: found = False is_initd = sysv_exists(unit) is_systemd = False # check service data, cannot error out on rc as it changes across versions, assume not found (rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit)) if rc == 0 and not (request_was_ignored(out) or request_was_ignored(err)): # load return of systemctl show into dictionary for easy access and return if out: result['status'] = parse_systemctl_show( to_native(out).split('\n')) is_systemd = 'LoadState' in result[ 'status'] and result['status']['LoadState'] != 'not-found' is_masked = 'LoadState' in result['status'] and result[ 'status']['LoadState'] == 'masked' # Check for loading error if is_systemd and not is_masked and 'LoadError' in result[ 'status']: module.fail_json(msg="Error loading unit file '%s': %s" % (unit, result['status']['LoadError'])) else: # list taken from man systemctl(1) for systemd 244 valid_enabled_states = [ "enabled", "enabled-runtime", "linked", "linked-runtime", "masked", "masked-runtime", "static", "indirect", "disabled", "generated", "transient" ] (rc, out, err) = module.run_command("%s is-enabled '%s'" % (systemctl, unit)) if out.strip() in valid_enabled_states: is_systemd = True else: # fallback list-unit-files as show does not work on some systems (chroot) # not used as primary as it skips some services (like those using init.d) and requires .service/etc notation (rc, out, err) = module.run_command("%s list-unit-files '%s'" % (systemctl, unit)) if rc == 0: is_systemd = True else: # Check for systemctl command module.run_command(systemctl, check_rc=True) # Does service exist? found = is_systemd or is_initd if is_initd and not is_systemd: module.warn( 'The service (%s) is actually an init script but the system is managed by systemd' % unit) # mask/unmask the service, if requested, can operate on services before they are installed if module.params['masked'] is not None: # state is not masked unless systemd affirms otherwise (rc, out, err) = module.run_command("%s is-enabled '%s'" % (systemctl, unit)) masked = out.strip() == "masked" if masked != module.params['masked']: result['changed'] = True if module.params['masked']: action = 'mask' else: action = 'unmask' if not module.check_mode: (rc, out, err) = module.run_command( "%s %s '%s'" % (systemctl, action, unit)) if rc != 0: # some versions of system CAN mask/unmask non existing services, we only fail on missing if they don't fail_if_missing(module, found, unit, msg='host') # Enable/disable service startup at boot if requested if module.params['enabled'] is not None: if module.params['enabled']: action = 'enable' else: action = 'disable' fail_if_missing(module, found, unit, msg='host') # do we need to enable the service? enabled = False (rc, out, err) = module.run_command("%s is-enabled '%s'" % (systemctl, unit)) # check systemctl result or if it is a init script if rc == 0: enabled = True elif rc == 1: # if not a user or global user service and both init script and unit file exist stdout should have enabled/disabled, otherwise use rc entries if module.params['scope'] == 'system' and \ is_initd and \ not out.strip().endswith('disabled') and \ sysv_is_enabled(unit): enabled = True # default to current state result['enabled'] = enabled # Change enable/disable if needed if enabled != module.params['enabled']: result['changed'] = True if not module.check_mode: (rc, out, err) = module.run_command( "%s %s '%s'" % (systemctl, action, unit)) if rc != 0: module.fail_json(msg="Unable to %s service %s: %s" % (action, unit, out + err)) result['enabled'] = not enabled # set service state if requested if module.params['state'] is not None: fail_if_missing(module, found, unit, msg="host") # default to desired state result['state'] = module.params['state'] # What is current service state? if 'ActiveState' in result['status']: action = None if module.params['state'] == 'started': if not is_running_service(result['status']): action = 'start' elif module.params['state'] == 'stopped': if is_running_service( result['status']) or is_deactivating_service( result['status']): action = 'stop' else: if not is_running_service(result['status']): action = 'start' else: action = module.params[ 'state'][: -2] # remove 'ed' from restarted/reloaded result['state'] = 'started' if action: result['changed'] = True if not module.check_mode: (rc, out, err) = module.run_command( "%s %s '%s'" % (systemctl, action, unit)) if rc != 0: module.fail_json( msg="Unable to %s service %s: %s" % (action, unit, err)) # check for chroot elif is_chroot(module) or os.environ.get('SYSTEMD_OFFLINE') == '1': module.warn( "Target is a chroot or systemd is offline. This can lead to false positives or prevent the init system tools from working." ) else: # this should not happen? module.fail_json(msg="Service is in unknown state", status=result['status']) module.exit_json(**result)
def main(): module = AssibleModule( argument_spec=dict( dest=dict(type='path'), repo=dict(type='str', required=True, aliases=['name', 'repository']), revision=dict(type='str', default='HEAD', aliases=['rev', 'version']), force=dict(type='bool', default=False), username=dict(type='str'), password=dict(type='str', no_log=True), executable=dict(type='path'), export=dict(type='bool', default=False), checkout=dict(type='bool', default=True), update=dict(type='bool', default=True), switch=dict(type='bool', default=True), in_place=dict(type='bool', default=False), validate_certs=dict(type='bool', default=False), ), supports_check_mode=True, ) dest = module.params['dest'] repo = module.params['repo'] revision = module.params['revision'] force = module.params['force'] username = module.params['username'] password = module.params['password'] svn_path = module.params['executable'] or module.get_bin_path('svn', True) export = module.params['export'] switch = module.params['switch'] checkout = module.params['checkout'] update = module.params['update'] in_place = module.params['in_place'] validate_certs = module.params['validate_certs'] # We screenscrape a huge amount of svn commands so use C locale anytime we # call run_command() module.run_command_environ_update = dict(LANG='C', LC_MESSAGES='C') if not dest and (checkout or update or export): module.fail_json(msg="the destination directory must be specified unless checkout=no, update=no, and export=no") svn = Subversion(module, dest, repo, revision, username, password, svn_path, validate_certs) if not export and not update and not checkout: module.exit_json(changed=False, after=svn.get_remote_revision()) if export or not os.path.exists(dest): before = None local_mods = False if module.check_mode: module.exit_json(changed=True) elif not export and not checkout: module.exit_json(changed=False) if not export and checkout: svn.checkout() files_changed = True else: svn.export(force=force) files_changed = True elif svn.is_svn_repo(): # Order matters. Need to get local mods before switch to avoid false # positives. Need to switch before revert to ensure we are reverting to # correct repo. if not update: module.exit_json(changed=False) if module.check_mode: if svn.has_local_mods() and not force: module.fail_json(msg="ERROR: modified files exist in the repository.") check, before, after = svn.needs_update() module.exit_json(changed=check, before=before, after=after) files_changed = False before = svn.get_revision() local_mods = svn.has_local_mods() if switch: files_changed = svn.switch() or files_changed if local_mods: if force: files_changed = svn.revert() or files_changed else: module.fail_json(msg="ERROR: modified files exist in the repository.") files_changed = svn.update() or files_changed elif in_place: before = None svn.checkout(force=True) files_changed = True local_mods = svn.has_local_mods() if local_mods and force: svn.revert() else: module.fail_json(msg="ERROR: %s folder already exists, but its not a subversion repository." % (dest,)) if export: module.exit_json(changed=True) else: after = svn.get_revision() changed = files_changed or local_mods module.exit_json(changed=changed, before=before, after=after)
def main(): module = AssibleModule( 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: 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." % PYTHON_APT) try: # 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" % PYTHON_APT) else: module.warn( "Updating cache and auto-installing missing dependency: %s" % PYTHON_APT) module.run_command(['apt-get', 'update'], check_rc=True) module.run_command([ 'apt-get', 'install', '--no-install-recommends', PYTHON_APT, '-y', '-q' ], check_rc=True) global apt, apt_pkg import apt import apt.debfile import apt_pkg except ImportError: module.fail_json( msg="Could not import python modules: apt, apt_pkg. " "Please install %s package." % PYTHON_APT) 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 = AssibleModule( argument_spec=dict( path=dict(type='path', required=True, aliases=['dest', 'name']), follow=dict(type='bool', default=False), get_md5=dict(type='bool', default=False), get_checksum=dict(type='bool', default=True), get_mime=dict(type='bool', default=True, aliases=['mime', 'mime_type', 'mime-type']), get_attributes=dict(type='bool', default=True, aliases=['attr', 'attributes']), checksum_algorithm=dict(type='str', default='sha1', choices=[ 'md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512' ], aliases=['checksum', 'checksum_algo']), ), supports_check_mode=True, ) path = module.params.get('path') b_path = to_bytes(path, errors='surrogate_or_strict') follow = module.params.get('follow') get_mime = module.params.get('get_mime') get_attr = module.params.get('get_attributes') get_checksum = module.params.get('get_checksum') checksum_algorithm = module.params.get('checksum_algorithm') # NOTE: undocumented option since 2.9 to be removed at a later date if possible (3.0+) # no real reason for keeping other than fear we may break older content. get_md5 = module.params.get('get_md5') # main stat data try: if follow: st = os.stat(b_path) else: st = os.lstat(b_path) except OSError as e: if e.errno == errno.ENOENT: output = {'exists': False} module.exit_json(changed=False, stat=output) module.fail_json(msg=e.strerror) # process base results output = format_output(module, path, st) # resolved permissions for perm in [('readable', os.R_OK), ('writeable', os.W_OK), ('executable', os.X_OK)]: output[perm[0]] = os.access(b_path, perm[1]) # symlink info if output.get('islnk'): output['lnk_source'] = os.path.realpath(b_path) output['lnk_target'] = os.readlink(b_path) try: # user data pw = pwd.getpwuid(st.st_uid) output['pw_name'] = pw.pw_name except (TypeError, KeyError): pass try: # group data grp_info = grp.getgrgid(st.st_gid) output['gr_name'] = grp_info.gr_name except (KeyError, ValueError, OverflowError): pass # checksums if output.get('isreg') and output.get('readable'): # NOTE: see above about get_md5 if get_md5: # Will fail on FIPS-140 compliant systems try: output['md5'] = module.md5(b_path) except ValueError: output['md5'] = None if get_checksum: output['checksum'] = module.digest_from_file( b_path, checksum_algorithm) # try to get mime data if requested if get_mime: output['mimetype'] = output['charset'] = 'unknown' mimecmd = module.get_bin_path('file') if mimecmd: mimecmd = [mimecmd, '--mime-type', '--mime-encoding', b_path] try: rc, out, err = module.run_command(mimecmd) if rc == 0: mimetype, charset = out.rsplit(':', 1)[1].split(';') output['mimetype'] = mimetype.strip() output['charset'] = charset.split('=')[1].strip() except Exception: pass # try to get attr data if get_attr: output['version'] = None output['attributes'] = [] output['attr_flags'] = '' out = module.get_file_attributes(b_path) for x in ('version', 'attributes', 'attr_flags'): if x in out: output[x] = out[x] module.exit_json(changed=False, stat=output)