def install_missing(name, version=None, source=None): """ Instructs Chocolatey to install a package if it doesn't already exist. .. versionchanged:: 2014.7.0 If the minion has Chocolatey >= 0.9.8.24 installed, this function calls :mod:`chocolatey.install <salt.modules.chocolatey.install>` instead, as ``installmissing`` is deprecated as of that version and will be removed in Chocolatey 1.0. name The name of the package to be installed. Only accepts a single argument. version Install a specific version of the package. Defaults to latest version available. source Chocolatey repository (directory, share or remote URL feed) the package comes from. Defaults to the official Chocolatey feed. CLI Example: .. code-block:: bash salt '*' chocolatey.install_missing <package name> salt '*' chocolatey.install_missing <package name> version=<package version> """ if _LooseVersion(chocolatey_version()) >= _LooseVersion("0.9.8.24"): log.warning("installmissing is deprecated, using install") return install(name, version=version) # chocolatey helpfully only supports a single package argument cmd = [_find_chocolatey(), "installmissing", name] if version: cmd.extend(["--version", version]) if source: cmd.extend(["--source", source]) # Shouldn't need this as this code should never run on v0.9.9 and newer cmd.extend(_yes()) result = __salt__["cmd.run_all"](cmd, python_shell=False) if result["retcode"] != 0: err = "Running chocolatey failed: {}".format(result["stdout"]) raise CommandExecutionError(err) return result["stdout"]
def _check_valid_version(): ''' Check the version of Bower to ensure this module will work. Currently bower must be at least version 1.3. ''' # pylint: disable=no-member bower_version = _LooseVersion( __salt__['cmd.run']('bower --version')) valid_version = _LooseVersion('1.3') # pylint: enable=no-member if bower_version < valid_version: raise CommandExecutionError( '\'bower\' is not recent enough({0} < {1}). ' 'Please Upgrade.'.format( bower_version, valid_version ) )
def version_cmp(pkg1, pkg2, ignore_epoch=False): ''' Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem making the comparison. ignore_epoch : False Set to ``True`` to ignore the epoch when comparing versions .. versionadded:: 2016.3.4 CLI Example: .. code-block:: bash salt '*' pkg.version_cmp '0.2.4-0' '0.2.4.1-0' ''' normalize = lambda x: str(x).split(':', 1)[-1] if ignore_epoch else str(x) pkg1 = normalize(pkg1) pkg2 = normalize(pkg2) output = __salt__['cmd.run_stdout'](['opkg', '--version'], output_loglevel='trace', python_shell=False) opkg_version = output.split(' ')[2].strip() if _LooseVersion(opkg_version) >= _LooseVersion('0.3.4'): cmd_compare = ['opkg', 'compare-versions'] elif salt.utils.which('opkg-compare-versions'): cmd_compare = ['opkg-compare-versions'] else: log.warning('Unable to find a compare-versions utility installed. Either upgrade opkg to ' 'version > 0.3.4 (preferred) or install the older opkg-compare-versions script.') return None for oper, ret in (("<<", -1), ("=", 0), (">>", 1)): cmd = cmd_compare[:] cmd.append(_cmd_quote(pkg1)) cmd.append(oper) cmd.append(_cmd_quote(pkg2)) retcode = __salt__['cmd.retcode'](cmd, output_loglevel='trace', ignore_retcode=True, python_shell=False) if retcode == 0: return ret return None
def __virtual__(): ''' Only work on Mac OS ''' if salt.utils.is_darwin() and _LooseVersion(__grains__['osrelease']) >= '10.9': return True return False, 'The assistive module cannot be loaded: must be run on ' \ 'macOS 10.9 or newer.'
def __virtual__(): ''' Only load if boto libraries exist and if boto libraries are greater than a given version. ''' # TODO: Determine minimal version we want to support. VPC requires > 2.8.0. required_boto_version = '2.0.0' if not HAS_BOTO: return False elif _LooseVersion( boto.__version__) < _LooseVersion(required_boto_version): return False else: global __salt__ if not __salt__: __salt__ = minion_mods(__opts__) return True
def update(name, source=None, pre_versions=False): ''' Instructs Chocolatey to update packages on the system. name The name of the package to update, or "all" to update everything installed on the system. source Chocolatey repository (directory, share or remote URL feed) the package comes from. Defaults to the official Chocolatey feed. pre_versions Include pre-release packages in comparison. Defaults to False. CLI Example: .. code-block:: bash salt "*" chocolatey.update all salt "*" chocolatey.update <package name> pre_versions=True ''' # chocolatey helpfully only supports a single package argument choc_path = _find_chocolatey(__context__, __salt__) if _LooseVersion(chocolatey_version()) >= _LooseVersion('0.9.8.24'): log.warning('update is deprecated, using upgrade') return upgrade(name, source=source, pre_versions=pre_versions) cmd = [choc_path, 'update', name] if source: cmd.extend(['--source', source]) if salt.utils.data.is_true(pre_versions): cmd.append('--prerelease') # Salt doesn't need to see the progress cmd.extend(_no_progress(__context__)) cmd.extend(_yes(__context__)) result = __salt__['cmd.run_all'](cmd, python_shell=False) if result['retcode'] not in [0, 1641, 3010]: raise CommandExecutionError( 'Running chocolatey failed: {0}'.format(result['stdout']) ) return result['stdout']
def __virtual__(): ''' Only load if boto3 libraries exist and if boto3 libraries are greater than a given version. ''' required_boto_version = '1.0.0' if not HAS_BOTO3: return (False, "The boto3.efs module cannot be loaded: " + "boto3 library not found") elif _LooseVersion(boto3.__version__) < \ _LooseVersion(required_boto_version): return (False, "The boto3.efs module cannot be loaded:" + "boto3 library version incorrect") else: return True
def __virtual__(): ''' Only load if boto libraries exist and if boto libraries are greater than a given version. ''' required_boto3_version = '1.2.1' # the boto_lambda execution module relies on the connect_to_region() method # which was added in boto 2.8.0 # https://github.com/boto/boto/commit/33ac26b416fbb48a60602542b4ce15dcc7029f12 if not HAS_BOTO: return (False, 'The boto_s3_bucket module could not be loaded: ' 'boto libraries not found') elif _LooseVersion(boto3.__version__) < _LooseVersion(required_boto3_version): return (False, 'The boto_cognitoidentity module could not be loaded: ' 'boto version {0} or later must be installed.'.format(required_boto3_version)) else: return True
def __virtual__(): """ Only load this module if right version of sleekxmpp is installed on this minion. """ min_version = "1.3.1" if HAS_LIBS: import sleekxmpp # pylint: disable=3rd-party-module-not-gated # Certain XMPP functionaility we're using doesn't work with versions under 1.3.1 sleekxmpp_version = _LooseVersion(sleekxmpp.__version__) valid_version = _LooseVersion(min_version) if sleekxmpp_version >= valid_version: return __virtualname__ return ( False, "Could not import xmpp returner; sleekxmpp python client is not " "installed or is older than version '{0}'.".format(min_version), )
def _check_valid_version(): """ Check the version of npm to ensure this module will work. Currently npm must be at least version 1.2. """ # Locate the full path to npm npm_path = salt.utils.path.which("npm") # pylint: disable=no-member res = salt.modules.cmdmod.run("{npm} --version".format(npm=npm_path), output_loglevel="quiet") npm_version, valid_version = _LooseVersion(res), _LooseVersion("1.2") # pylint: enable=no-member if npm_version < valid_version: raise CommandExecutionError( "'npm' is not recent enough({0} < {1}). Please Upgrade.".format( npm_version, valid_version))
def __virtual__(): ''' Only load if boto libraries exist and if boto libraries are greater than a given version. ''' required_boto_version = '2.4.0' # Boto < 2.4.0 GroupOrCIDR objects have different attributes than # Boto >= 2.4.0 GroupOrCIDR objects # Differences include no group_id attribute in Boto < 2.4.0 and returning # a groupId attribute when a GroupOrCIDR object authorizes an IP range # Support for Boto < 2.4.0 can be added if needed if not HAS_BOTO: return (False, 'The boto_secgroup module could not be loaded: boto libraries not found') elif _LooseVersion(boto.__version__) < _LooseVersion(required_boto_version): return (False, 'The boto_secgroup module could not be loaded: boto library v2.4.0 not found') else: __utils__['boto.assign_funcs'](__name__, 'ec2', pack=__salt__) return True
def __virtual__(): """ Only work on Mac OS """ if not salt.utils.platform.is_darwin(): return False, "Must be run on macOS" if _LooseVersion(__grains__["osrelease"]) < salt.utils.stringutils.to_str("10.9"): return False, "Must be run on macOS 10.9 or newer" return __virtualname__
def __virtual__(): ''' Only work on Mac OS ''' if not salt.utils.platform.is_darwin(): return False, 'Must be run on macOS' if not _LooseVersion(__grains__['osrelease']) >= salt.utils.stringutils.to_str('10.9'): return False, 'Must be run on macOS 10.9 or newer' return __virtualname__
def __virtual__(): if HAS_OPENSSL is False: return ( False, "The travisci module was unable to be loaded: Install pyOpenssl >= {}".format( OPENSSL_MIN_VER ), ) cur_version = _LooseVersion(OpenSSL.__version__) min_version = _LooseVersion(OPENSSL_MIN_VER) if cur_version < min_version: return ( False, "The travisci module was unable to be loaded: Install pyOpenssl >= {}".format( OPENSSL_MIN_VER ), ) return __virtualname__
def update(name, source=None, pre_versions=False): """ Instructs Chocolatey to update packages on the system. name The name of the package to update, or "all" to update everything installed on the system. source Chocolatey repository (directory, share or remote URL feed) the package comes from. Defaults to the official Chocolatey feed. pre_versions Include pre-release packages in comparison. Defaults to False. CLI Example: .. code-block:: bash salt "*" chocolatey.update all salt "*" chocolatey.update <package name> pre_versions=True """ # chocolatey helpfully only supports a single package argument if _LooseVersion(chocolatey_version()) >= _LooseVersion("0.9.8.24"): log.warning("update is deprecated, using upgrade") return upgrade(name, source=source, pre_versions=pre_versions) cmd = [_find_chocolatey(), "update", name] if source: cmd.extend(["--source", source]) if salt.utils.data.is_true(pre_versions): cmd.append("--prerelease") # Salt doesn't need to see the progress cmd.extend(_no_progress()) cmd.extend(_yes()) result = __salt__["cmd.run_all"](cmd, python_shell=False) if result["retcode"] not in [0, 1641, 3010]: err = "Running chocolatey failed: {}".format(result["stdout"]) raise CommandExecutionError(err) return result["stdout"]
def user_list(user=None, password=None, host=None, port=None, database='admin', authdb=None): ''' List users of a Mongodb database CLI Example: .. code-block:: bash salt '*' mongodb.user_list <user> <password> <host> <port> <database> ''' conn = _connect(user, password, host, port, authdb=authdb) if not conn: return 'Failed to connect to mongo database' try: log.info('Listing users') mdb = pymongo.database.Database(conn, database) output = [] mongodb_version = _version(mdb) if _LooseVersion(mongodb_version) >= _LooseVersion('2.6'): for user in mdb.command('usersInfo')['users']: output.append( {'user': user['user'], 'roles': user['roles']} ) else: for user in mdb.system.users.find(): output.append( {'user': user['user'], 'readOnly': user.get('readOnly', 'None')} ) return output except pymongo.errors.PyMongoError as err: log.error( 'Listing users failed with error: {0}'.format( str(err) ) ) return str(err)
def __virtual__(): ''' Only for macOS with launchctl ''' if not salt.utils.platform.is_darwin(): return (False, 'Failed to load the mac_service module:\n' 'Only available on macOS systems.') if not salt.utils.path.which('launchctl'): return (False, 'Failed to load the mac_service module:\n' 'Required binary not found: "launchctl"') if not salt.utils.path.which('plutil'): return (False, 'Failed to load the mac_service module:\n' 'Required binary not found: "plutil"') if _LooseVersion(__grains__['osrelease']) < _LooseVersion('10.11'): return (False, 'Failed to load the mac_service module:\n' 'Requires macOS 10.11 or newer') return __virtualname__
def __virtual__(): ''' Only work on MacOS ''' if not salt.utils.platform.is_darwin(): return (False, 'Failed to load the mac_service module:\n' 'Only available on macOS systems.') if not os.path.exists('/bin/launchctl'): return (False, 'Failed to load the mac_service module:\n' 'Required binary not found: "/bin/launchctl"') if _LooseVersion(__grains__['osrelease']) >= _LooseVersion('10.11'): return (False, 'Failed to load the mac_service module:\n' 'Not available on El Capitan, uses mac_service.py') if _LooseVersion(__grains__['osrelease']) >= _LooseVersion('10.10'): global BEFORE_YOSEMITE BEFORE_YOSEMITE = False return __virtualname__
def save_load(jid, load, minions=None): """ Save the load for a given job id """ conn, mdb = _get_conn(ret=None) to_save = _safe_copy(load) if PYMONGO_VERSION > _LooseVersion("2.3"): # using .copy() to ensure original data for load is unchanged mdb.jobs.insert_one(to_save) else: mdb.jobs.insert(to_save)
def __virtual__(): ''' Only for macOS with launchctl ''' if not salt.utils.platform.is_darwin(): return (False, 'Failed to load the mac_service module:\n' 'Only available on macOS systems.') if not salt.utils.path.which('launchctl'): return (False, 'Failed to load the mac_service module:\n' 'Required binary not found: "launchctl"') if not salt.utils.path.which('plutil'): return (False, 'Failed to load the mac_service module:\n' 'Required binary not found: "plutil"') if _LooseVersion(__grains__['osrelease']) < _LooseVersion('10.11'): return (False, 'Failed to load the mac_service module:\n' 'Requires macOS 10.11 or newer') return __virtualname__
def __virtual__(): ''' Only load if boto libraries exist and if boto libraries are greater than a given version. ''' required_boto_version = '2.8.0' required_boto3_version = '1.2.5' required_botocore_version = '1.5.2' # the boto_lambda execution module relies on the connect_to_region() method # which was added in boto 2.8.0 # https://github.com/boto/boto/commit/33ac26b416fbb48a60602542b4ce15dcc7029f12 # botocore version >= 1.5.2 is required due to lambda environment variables if not HAS_BOTO: return (False, 'The boto_lambda module could not be loaded: ' 'boto libraries not found') elif _LooseVersion(boto.__version__) < _LooseVersion(required_boto_version): return (False, 'The boto_lambda module could not be loaded: ' 'boto version {0} or later must be installed.'.format(required_boto_version)) elif _LooseVersion(boto3.__version__) < _LooseVersion(required_boto3_version): return (False, 'The boto_lambda module could not be loaded: ' 'boto version {0} or later must be installed.'.format(required_boto3_version)) elif _LooseVersion(found_botocore_version) < _LooseVersion(required_botocore_version): return (False, 'The boto_apigateway module could not be loaded: ' 'botocore version {0} or later must be installed.'.format(required_botocore_version)) else: return True
def user_list(user=None, password=None, host=None, port=None, database="admin", authdb=None): """ List users of a MongoDB database CLI Example: .. code-block:: bash salt '*' mongodb.user_list <user> <password> <host> <port> <database> """ conn = _connect(user, password, host, port, authdb=authdb) if not conn: return "Failed to connect to mongo database" try: log.info("Listing users") mdb = pymongo.database.Database(conn, database) output = [] mongodb_version = _version(mdb) if _LooseVersion(mongodb_version) >= _LooseVersion("2.6"): for user in mdb.command("usersInfo")["users"]: output.append({"user": user["user"], "roles": user["roles"]}) else: for user in mdb.system.users.find(): output.append({ "user": user["user"], "readOnly": user.get("readOnly", "None") }) return output except pymongo.errors.PyMongoError as err: log.error("Listing users failed with error: %s", err) return str(err)
def _get_conn(ret): ''' Return a mongodb connection object ''' _options = _get_options(ret) host = _options.get('host') port = _options.get('port') db_ = _options.get('db') user = _options.get('user') password = _options.get('password') indexes = _options.get('indexes', False) # at some point we should remove support for # pymongo versions < 2.3 until then there are # a bunch of these sections that need to be supported if PYMONGO_VERSION > _LooseVersion('2.3'): conn = pymongo.MongoClient(host, port) else: conn = pymongo.Connection(host, port) mdb = conn[db_] if user and password: mdb.authenticate(user, password) if indexes: if PYMONGO_VERSION > _LooseVersion('2.3'): mdb.saltReturns.create_index('minion') mdb.saltReturns.create_index('jid') mdb.jobs.create_index('jid') else: mdb.saltReturns.ensure_index('minion') mdb.saltReturns.ensure_index('jid') mdb.jobs.ensure_index('jid') return conn, mdb
def _get_conn(ret): """ Return a mongodb connection object """ _options = _get_options(ret) host = _options.get("host") port = _options.get("port") db_ = _options.get("db") user = _options.get("user") password = _options.get("password") indexes = _options.get("indexes", False) # at some point we should remove support for # pymongo versions < 2.3 until then there are # a bunch of these sections that need to be supported if PYMONGO_VERSION > _LooseVersion("2.3"): conn = pymongo.MongoClient(host, port) else: conn = pymongo.Connection(host, port) mdb = conn[db_] if user and password: mdb.authenticate(user, password) if indexes: if PYMONGO_VERSION > _LooseVersion("2.3"): mdb.saltReturns.create_index("minion") mdb.saltReturns.create_index("jid") mdb.jobs.create_index("jid") else: mdb.saltReturns.ensure_index("minion") mdb.saltReturns.ensure_index("jid") mdb.jobs.ensure_index("jid") return conn, mdb
def latest_installed(): ''' Return the version of the latest installed kernel. CLI Example: .. code-block:: bash salt '*' kernelpkg.latest_installed .. note:: This function may not return the same value as :py:func:`~salt.modules.kernelpkg.active` if a new kernel has been installed and the system has not yet been rebooted. The :py:func:`~salt.modules.kernelpkg.needs_reboot` function exists to detect this condition. ''' result = _LooseVersion(active()) for pkg in list_installed(): pkgver = _LooseVersion(pkg) if pkgver > result: result = pkgver return str(result)
def __virtual__(): ''' Makes sure that python-gnupg and gpg are available. ''' if not _gpg(): return (False, 'The gpg execution module cannot be loaded: ' 'gpg binary is not in the path.') if HAS_LIBS: gnupg_version = _LooseVersion(gnupg.__version__) if gnupg_version >= '1.3.1': global GPG_1_3_1 GPG_1_3_1 = True return __virtualname__ return (False, 'The gpg execution module cannot be loaded; the' ' gnupg python module is not installed.')
def event_return(events): """ Return events to Mongodb server """ conn, mdb = _get_conn(ret=None) if isinstance(events, list): events = events[0] if isinstance(events, dict): log.debug(events) if PYMONGO_VERSION > _LooseVersion("2.3"): mdb.events.insert_one(events.copy()) else: mdb.events.insert(events.copy())
def install(app_id, enable=True): ''' Install a bundle ID or command as being allowed to use assistive access. app_id The bundle ID or command to install for assistive access. enabled Sets enabled or disabled status. Default is ``True``. CLI Example: .. code-block:: bash salt '*' assistive.install /usr/bin/osascript salt '*' assistive.install com.smileonmymac.textexpander ''' ge_el_capitan = True if _LooseVersion( __grains__['osrelease']) >= salt.utils.stringutils.to_str( '10.11') else False client_type = _client_type(app_id) enable_str = '1' if enable else '0' cmd = 'sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" ' \ '"INSERT or REPLACE INTO access VALUES(\'kTCCServiceAccessibility\',\'{0}\',{1},{2},1,NULL{3})"'.\ format(app_id, client_type, enable_str, ',NULL' if ge_el_capitan else '') call = __salt__['cmd.run_all'](cmd, output_loglevel='debug', python_shell=False) if call['retcode'] != 0: comment = '' if 'stderr' in call: comment += call['stderr'] if 'stdout' in call: comment += call['stdout'] raise CommandExecutionError( 'Error installing app: {0}'.format(comment)) return True
def returner(ret): ''' Return data to a mongodb server ''' conn, mdb = _get_conn(ret) col = mdb[ret['id']] if isinstance(ret['return'], dict): back = _remove_dots(ret['return']) else: back = ret['return'] if isinstance(ret, dict): full_ret = _remove_dots(ret) else: full_ret = ret log.debug(back) sdata = { 'minion': ret['id'], 'jid': ret['jid'], 'return': back, 'fun': ret['fun'], 'full_ret': full_ret } if 'out' in ret: sdata['out'] = ret['out'] # save returns in the saltReturns collection in the json format: # { 'minion': <minion_name>, 'jid': <job_id>, 'return': <return info with dots removed>, # 'fun': <function>, 'full_ret': <unformatted return with dots removed>} # again we run into the issue with deprecated code from previous versions if PYMONGO_VERSION > _LooseVersion('2.3'): #using .copy() to ensure original data for load is unchanged mdb.saltReturns.insert_one(sdata.copy()) else: mdb.saltReturns.insert(sdata.copy())
def test_roster_config_validate(self): try: jsonschema.validate( { "target-1": { "host": "localhost", "user": "******", "passwd": "foo" } }, ssh_schemas.RosterItem.serialize(), format_checker=jsonschema.FormatChecker(), ) except jsonschema.exceptions.ValidationError as exc: self.fail("ValidationError raised: {}".format(exc)) with self.assertRaises( jsonschema.exceptions.ValidationError) as excinfo: jsonschema.validate( { salt.utils.stringutils.to_str("target-1:1"): { "host": "localhost", "user": "******", "passwd": "foo", } }, ssh_schemas.RosterItem.serialize(), format_checker=jsonschema.FormatChecker(), ) if JSONSCHEMA_VERSION < _LooseVersion("2.6.0"): self.assertIn( "Additional properties are not allowed ('target-1:1' was unexpected)", excinfo.exception.message, ) else: self.assertIn( "'target-1:1' does not match any of the regexes", excinfo.exception.message, )
def returner(ret): """ Return data to a mongodb server """ conn, mdb = _get_conn(ret) col = mdb[ret["id"]] if isinstance(ret["return"], dict): back = _remove_dots(ret["return"]) else: back = ret["return"] if isinstance(ret, dict): full_ret = _remove_dots(ret) else: full_ret = ret log.debug(back) sdata = { "minion": ret["id"], "jid": ret["jid"], "return": back, "fun": ret["fun"], "full_ret": full_ret, } if "out" in ret: sdata["out"] = ret["out"] # save returns in the saltReturns collection in the json format: # { 'minion': <minion_name>, 'jid': <job_id>, 'return': <return info with dots removed>, # 'fun': <function>, 'full_ret': <unformatted return with dots removed>} # again we run into the issue with deprecated code from previous versions if PYMONGO_VERSION > _LooseVersion("2.3"): # using .copy() to ensure original data for load is unchanged mdb.saltReturns.insert_one(sdata.copy()) else: mdb.saltReturns.insert(sdata.copy())