def managed(name, ppa=None, **kwargs): ''' This state manages software package repositories. Currently, :mod:`yum <salt.modules.yumpkg>`, :mod:`apt <salt.modules.aptpkg>`, and :mod:`zypper <salt.modules.zypper>` repositories are supported. **YUM OR ZYPPER-BASED SYSTEMS** .. note:: One of ``baseurl`` or ``mirrorlist`` below is required. Additionally, note that this state is not presently capable of managing more than one repo in a single repo file, so each instance of this state will manage a single repo file containing the configuration for a single repo. name This value will be used in two ways: Firstly, it will be the repo ID, as seen in the entry in square brackets (e.g. ``[foo]``) for a given repo. Secondly, it will be the name of the file as stored in /etc/yum.repos.d (e.g. ``/etc/yum.repos.d/foo.conf``). humanname This is used as the "name" value in the repo file in ``/etc/yum.repos.d/`` (or ``/etc/zypp/repos.d`` for Suse distros). baseurl The URL to a yum repository mirrorlist A URL which points to a file containing a collection of baseurls comments Sometimes you want to supply additional information, but not as enabled configuration. Anything supplied for this list will be saved in the repo configuration with a comment marker (#) in front. Additional configuration values seen in yum repo files, such as ``gpgkey`` or ``gpgcheck``, will be used directly as key-value pairs. For example: .. code-block:: yaml foo: pkgrepo.managed: - humanname: Personal repo for foo - baseurl: https://mydomain.tld/repo/foo/$releasever/$basearch - gpgkey: file:///etc/pki/rpm-gpg/foo-signing-key - gpgcheck: 1 **APT-BASED SYSTEMS** ppa On Ubuntu, you can take advantage of Personal Package Archives on Launchpad simply by specifying the user and archive name. The keyid will be queried from launchpad and everything else is set automatically. You can override any of the below settings by simply setting them as you would normally. For example: .. code-block:: yaml logstash-ppa: pkgrepo.managed: - ppa: wolfnet/logstash ppa_auth For Ubuntu PPAs there can be private PPAs that require authentication to access. For these PPAs the username/password can be passed as an HTTP Basic style username/password combination. .. code-block:: yaml logstash-ppa: pkgrepo.managed: - ppa: wolfnet/logstash - ppa_auth: username:password name On apt-based systems this must be the complete entry as it would be seen in the sources.list file. This can have a limited subset of components (i.e. 'main') which can be added/modified with the ``comps`` option. .. code-block:: yaml precise-repo: pkgrepo.managed: - name: deb http://us.archive.ubuntu.com/ubuntu precise main .. note:: The above example is intended as a more readable way of configuring the SLS, it is equivalent to the following: .. code-block:: yaml 'deb http://us.archive.ubuntu.com/ubuntu precise main': pkgrepo.managed disabled Toggles whether or not the repo is used for resolving dependencies and/or installing packages. comps On apt-based systems, comps dictate the types of packages to be installed from the repository (e.g. main, nonfree, ...). For purposes of this, comps should be a comma-separated list. file The filename for the .list that the repository is configured in. It is important to include the full-path AND make sure it is in a directory that APT will look in when handling packages dist This dictates the release of the distro the packages should be built for. (e.g. unstable). This option is rarely needed. keyid The KeyID of the GPG key to install. This option also requires the ``keyserver`` option to be set. keyserver This is the name of the keyserver to retrieve gpg keys from. The ``keyid`` option must also be set for this option to work. key_url URL to retrieve a GPG key from. Allows the usage of ``http://``, ``https://`` as well as ``salt://``. .. note:: Use either ``keyid``/``keyserver`` or ``key_url``, but not both. consolidate If set to true, this will consolidate all sources definitions to the sources.list file, cleanup the now unused files, consolidate components (e.g. main) for the same URI, type, and architecture to a single line, and finally remove comments from the sources.list file. The consolidate will run every time the state is processed. The option only needs to be set on one repo managed by salt to take effect. clean_file If set to true, empty file before config repo, dangerous if use multiple sources in one file. .. versionadded:: 2015.8.0 refresh_db If set to false this will skip refreshing the apt package database on debian based systems. require_in Set this to a list of pkg.installed or pkg.latest to trigger the running of apt-get update prior to attempting to install these packages. Setting a require in the pkg will not work for this. ''' ret = {'name': name, 'changes': {}, 'result': None, 'comment': ''} if 'pkg.get_repo' not in __salt__: ret['result'] = False ret['comment'] = 'Repo management not implemented on this platform' return ret if 'key_url' in kwargs and ('keyid' in kwargs or 'keyserver' in kwargs): ret['result'] = False ret['comment'] = 'You may not use both "keyid"/"keyserver" and ' \ '"key_url" argument.' return ret repo = name if __grains__['os'] in ('Ubuntu', 'Mint'): if ppa is not None: # overload the name/repo value for PPAs cleanly # this allows us to have one code-path for PPAs try: repo = ':'.join(('ppa', ppa)) except TypeError: repo = ':'.join(('ppa', str(ppa))) elif __grains__['os_family'].lower() in ('redhat', 'suse'): if 'humanname' in kwargs: kwargs['name'] = kwargs.pop('humanname') _val = lambda x: '1' if salt.utils.is_true(x) else '0' if 'disabled' in kwargs: if 'enabled' in kwargs: ret['result'] = False ret['comment'] = 'Only one of enabled/disabled is permitted' return ret _reverse = lambda x: '1' if x == '0' else '0' kwargs['enabled'] = _reverse(_val(kwargs.pop('disabled'))) elif 'enabled' in kwargs: kwargs['enabled'] = _val(kwargs['enabled']) if 'name' not in kwargs: # Fall back to the repo name if humanname not provided kwargs['name'] = repo if kwargs.pop('enabled', None): kwargs['disabled'] = False salt.utils.warn_until( 'Carbon', 'The `enabled` argument has been deprecated in favor of ' '`disabled`.' ) for kwarg in _STATE_INTERNAL_KEYWORDS: kwargs.pop(kwarg, None) try: pre = __salt__['pkg.get_repo']( repo, ppa_auth=kwargs.get('ppa_auth', None) ) except CommandExecutionError as exc: ret['result'] = False ret['comment'] = \ 'Failed to examine repo \'{0}\': {1}'.format(name, exc) return ret # This is because of how apt-sources works. This pushes distro logic # out of the state itself and into a module that it makes more sense # to use. Most package providers will simply return the data provided # it doesn't require any "specialized" data massaging. if 'pkg.expand_repo_def' in __salt__: sanitizedkwargs = __salt__['pkg.expand_repo_def'](repo=repo, **kwargs) else: sanitizedkwargs = kwargs if __grains__['os_family'] == 'Debian': repo = _strip_uri(repo) if pre: needs_update = False for kwarg in sanitizedkwargs: if kwarg not in pre: if kwarg == 'enabled': # On a RedHat-based OS, 'enabled' is assumed to be true if # not explicitly set, so we don't need to update the repo # if it's desired to be enabled and the 'enabled' key is # missing from the repo definition if __grains__['os_family'] == 'RedHat': if not salt.utils.is_true(sanitizedkwargs[kwarg]): needs_update = True else: needs_update = True else: needs_update = True elif kwarg == 'comps': if sorted(sanitizedkwargs[kwarg]) != sorted(pre[kwarg]): needs_update = True elif kwarg == 'line' and __grains__['os_family'] == 'Debian': # split the line and sort everything after the URL sanitizedsplit = sanitizedkwargs[kwarg].split() sanitizedsplit[3:] = sorted(sanitizedsplit[3:]) reposplit = pre[kwarg].split() reposplit[3:] = sorted(reposplit[3:]) if sanitizedsplit != reposplit: needs_update = True else: if str(sanitizedkwargs[kwarg]) != str(pre[kwarg]): needs_update = True if not needs_update: ret['result'] = True ret['comment'] = ('Package repo \'{0}\' already configured' .format(name)) return ret if __opts__['test']: ret['comment'] = ( 'Package repo \'{0}\' will be configured. This may cause pkg ' 'states to behave differently than stated if this action is ' 'repeated without test=True, due to the differences in the ' 'configured repositories.'.format(name) ) return ret # empty file before configure if kwargs.get('clean_file', False): salt.utils.fopen(kwargs['file'], 'w').close() try: if __grains__['os_family'] == 'Debian': __salt__['pkg.mod_repo'](repo, saltenv=__env__, **kwargs) else: __salt__['pkg.mod_repo'](repo, **kwargs) except Exception as exc: # This is another way to pass information back from the mod_repo # function. ret['result'] = False ret['comment'] = \ 'Failed to configure repo \'{0}\': {1}'.format(name, exc) return ret try: post = __salt__['pkg.get_repo']( repo, ppa_auth=kwargs.get('ppa_auth', None) ) if pre: for kwarg in sanitizedkwargs: if post.get(kwarg) != pre.get(kwarg): change = {'new': post[kwarg], 'old': pre.get(kwarg)} ret['changes'][kwarg] = change else: ret['changes'] = {'repo': repo} ret['result'] = True ret['comment'] = 'Configured package repo \'{0}\''.format(name) except Exception as exc: ret['result'] = False ret['comment'] = \ 'Failed to confirm config of repo {0!r}: {1}'.format(name, exc) # Clear cache of available packages, if present, since changes to the # repositories may change the packages that are available. if ret['changes']: sys.modules[ __salt__['test.ping'].__module__ ].__context__.pop('pkg._avail', None) return ret
def managed(name, **kwargs): ''' This function manages the configuration on a system that points to the repositories for the system's package manager. name The name of the package repo, as it would be referred to when running the regular package manager commands. For yum-based systems, take note of the following configuration values: humanname On yum-based systems, this is stored as the "name" value in the .repo file in /etc/yum.repos.d/. On yum-based systems, this is required. baseurl On yum-based systems, baseurl refers to a direct URL to be used for this yum repo. One of baseurl or mirrorlist is required. mirrorlist a URL which contains a collection of baseurls to choose from. On yum-based systems. One of baseurl or mirrorlist is required. comments Sometimes you want to supply additional information, but not as enabled configuration. Anything supplied for this list will be saved in the repo configuration with a comment marker (#) in front. Additional configuration values, such as gpgkey or gpgcheck, are used verbatim to update the options for the yum repo in question. For apt-based systems, take note of the following configuration values: ppa On Ubuntu, you can take advantage of Personal Package Archives on Launchpad simply by specifying the user and archive name. The keyid will be queried from launchpad and everything else is set automatically. You can override any of the below settings by simply setting them as you would normally. For example: .. code-block:: yaml logstash-ppa: pkgrepo.managed: - ppa: wolfnet/logstash ppa_auth For Ubuntu PPAs there can be private PPAs that require authentication to access. For these PPAs the username/password can be passed as an HTTP Basic style username/password combination. .. code-block:: yaml logstash-ppa: pkgrepo.managed: - ppa: wolfnet/logstash - ppa_auth: username:password name On apt-based systems this must be the complete entry as it would be seen in the sources.list file. This can have a limited subset of components (i.e. 'main') which can be added/modified with the "comps" option. .. code-block:: yaml precise-repo: pkgrepo.managed: - name: deb http://us.archive.ubuntu.com/ubuntu precise main disabled On apt-based systems, disabled toggles whether or not the repo is used for resolving dependencies and/or installing packages comps On apt-based systems, comps dictate the types of packages to be installed from the repository (e.g. main, nonfree, ...). For purposes of this, comps should be a comma-separated list. file The filename for the .list that the repository is configured in. It is important to include the full-path AND make sure it is in a directory that APT will look in when handling packages dist This dictates the release of the distro the packages should be built for. (e.g. unstable) keyid The KeyID of the GPG key to install. This option also requires the 'keyserver' option to be set. keyserver This is the name of the keyserver to retrieve gpg keys from. The keyid option must also be set for this option to work. key_url A web URL to retrieve the GPG key from. consolidate If set to true, this will consolidate all sources definitions to the sources.list file, cleanup the now unused files, consolidate components (e.g. main) for the same URI, type, and architecture to a single line, and finally remove comments from the sources.list file. The consolidate will run every time the state is processed. The option only needs to be set on one repo managed by salt to take effect. require_in Set this to a list of pkg.installed or pkg.latest to trigger the running of apt-get update prior to attempting to install these packages. Setting a require in the pkg will not work for this. ''' ret = {'name': name, 'changes': {}, 'result': None, 'comment': '', 'state_stdout': ''} repo = {} # pkg.mod_repo has conflicting kwargs, so move 'em around if 'name' in kwargs: if 'ppa' in kwargs: ret['result'] = False ret['comment'] = 'You may not use both the "name" argument ' \ 'and the "ppa" argument.' return ret kwargs['repo'] = kwargs['name'] if 'ppa' in kwargs and __grains__['os'] == 'Ubuntu': # overload the name/repo value for PPAs cleanly # this allows us to have one code-path for PPAs repo_name = 'ppa:{0}'.format(kwargs['ppa']) kwargs['repo'] = repo_name if 'repo' not in kwargs: kwargs['repo'] = name if 'humanname' in kwargs: kwargs['name'] = kwargs['humanname'] for kwarg in _STATE_INTERNAL_KEYWORDS: kwargs.pop(kwarg, None) try: repo = __salt__['pkg.get_repo']( kwargs['repo'], ppa_auth=kwargs.get('ppa_auth', None) ) except Exception: pass # this is because of how apt-sources works. This pushes distro logic # out of the state itself and into a module that it makes more sense # to use. Most package providers will simply return the data provided # it doesn't require any "specialized" data massaging. sanitizedkwargs = __salt__['pkg.expand_repo_def'](kwargs) if __grains__['os_family'] == 'Debian': kwargs['repo'] = _strip_uri(kwargs['repo']) if repo: notset = False for kwarg in sanitizedkwargs: if kwarg == 'repo': pass elif kwarg not in repo.keys(): notset = True elif kwarg == 'comps': if sorted(sanitizedkwargs[kwarg]) != sorted(repo[kwarg]): notset = True elif kwarg == 'line' and __grains__['os_family'] == 'Debian': # split the line and sort everything after the URL sanitizedsplit = sanitizedkwargs[kwarg].split() sanitizedsplit[3:] = sorted(sanitizedsplit[3:]) reposplit = repo[kwarg].split() reposplit[3:] = sorted(reposplit[3:]) if sanitizedsplit != reposplit: notset = True else: if str(sanitizedkwargs[kwarg]) != str(repo[kwarg]): notset = True if notset is False: ret['result'] = True ret['comment'] = ('Package repo {0!r} already configured' .format(name)) return ret if __opts__['test']: ret['comment'] = ('Package repo {0!r} will be configured. This may ' 'cause pkg states to behave differently than stated ' 'if this action is repeated without test=True, due ' 'to the differences in the configured repositories.' .format(name)) return ret try: __salt__['pkg.mod_repo'](state_ret=ret, **kwargs) except Exception as e: # This is another way to pass information back from the mod_repo # function. ret['result'] = False ret['comment'] = ('Failed to configure repo {0!r}: {1}' .format(name, str(e))) return ret try: repodict = __salt__['pkg.get_repo'](kwargs['repo'], ppa_auth=kwargs.get('ppa_auth', None)) if repo: for kwarg in sanitizedkwargs: if repodict.get(kwarg) != repo.get(kwarg): change = {'new': repodict[kwarg], 'old': repo.get(kwarg)} ret['changes'][kwarg] = change else: ret['changes'] = {'repo': kwargs['repo']} ret['result'] = True ret['comment'] = 'Configured package repo {0!r}'.format(name) except Exception as e: ret['result'] = False ret['comment'] = 'Failed to confirm config of repo {0!r}: {1}'.format( name, str(e)) return ret
def managed(name, **kwargs): ''' This function manages the configuration on a system that points to the repositories for the system's package manager. name The name of the package repo, as it would be referred to when running the regular package manager commands. For yum-based systems, take note of the following configuration values: humanname On yum-based systems, this is stored as the "name" value in the .repo file in /etc/yum.repos.d/. On yum-based systems, this is required. baseurl On yum-based systems, baseurl refers to a direct URL to be used for this yum repo. One of baseurl or mirrorlist is required. mirrorlist a URL which contains a collection of baseurls to choose from. On yum-based systems. One of baseurl or mirrorlist is required. comments Sometimes you want to supply additional information, but not as enabled configuration. Anything supplied for this list will be saved in the repo configuration with a comment marker (#) in front. Additional configuration values, such as gpgkey or gpgcheck, are used verbatim to update the options for the yum repo in question. For apt-based systems, take note of the following configuration values: ppa On Ubuntu, you can take advantage of Personal Package Archives on Launchpad simply by specifying the user and archive name. The keyid will be queried from launchpad and everything else is set automatically. You can override any of the below settings by simply setting them as you would normally. For example: .. code-block:: yaml logstash-ppa: pkgrepo.managed: - ppa: wolfnet/logstash ppa_auth For Ubuntu PPAs there can be private PPAs that require authentication to access. For these PPAs the username/password can be passed as an HTTP Basic style username/password combination. .. code-block:: yaml logstash-ppa: pkgrepo.managed: - ppa: wolfnet/logstash - ppa_auth: username:password name On apt-based systems this must be the complete entry as it would be seen in the sources.list file. This can have a limited subset of components (i.e. 'main') which can be added/modified with the "comps" option. .. code-block:: yaml precise-repo: pkgrepo.managed: - name: deb http://us.archive.ubuntu.com/ubuntu precise main disabled Toggles whether or not the repo is used for resolving dependencies and/or installing packages. enabled Enables the repository, even if the repository has been disabled, in order for the respective package requiring the repository can be found and installed. comps On apt-based systems, comps dictate the types of packages to be installed from the repository (e.g. main, nonfree, ...). For purposes of this, comps should be a comma-separated list. file The filename for the .list that the repository is configured in. It is important to include the full-path AND make sure it is in a directory that APT will look in when handling packages dist This dictates the release of the distro the packages should be built for. (e.g. unstable) keyid The KeyID of the GPG key to install. This option also requires the 'keyserver' option to be set. keyserver This is the name of the keyserver to retrieve gpg keys from. The keyid option must also be set for this option to work. key_url URL to retrieve a GPG key from. consolidate If set to true, this will consolidate all sources definitions to the sources.list file, cleanup the now unused files, consolidate components (e.g. main) for the same URI, type, and architecture to a single line, and finally remove comments from the sources.list file. The consolidate will run every time the state is processed. The option only needs to be set on one repo managed by salt to take effect. clean_file If set to true, empty file before config repo, dangerous if use multiple sources in one file. refresh_db If set to false this will skip refreshing the apt package database on debian based systems. require_in Set this to a list of pkg.installed or pkg.latest to trigger the running of apt-get update prior to attempting to install these packages. Setting a require in the pkg will not work for this. ''' ret = {'name': name, 'changes': {}, 'result': None, 'comment': ''} repo = {} # pkg.mod_repo has conflicting kwargs, so move 'em around if 'name' in kwargs: if 'ppa' in kwargs: ret['result'] = False ret['comment'] = 'You may not use both the "name" argument ' \ 'and the "ppa" argument.' return ret kwargs['repo'] = kwargs['name'] if 'ppa' in kwargs and __grains__['os'] == 'Ubuntu': # overload the name/repo value for PPAs cleanly # this allows us to have one code-path for PPAs repo_name = 'ppa:{0}'.format(kwargs['ppa']) kwargs['repo'] = repo_name if 'repo' not in kwargs: kwargs['repo'] = name if 'humanname' in kwargs: kwargs['name'] = kwargs['humanname'] for kwarg in _STATE_INTERNAL_KEYWORDS: kwargs.pop(kwarg, None) try: repo = __salt__['pkg.get_repo'](kwargs['repo'], ppa_auth=kwargs.get('ppa_auth', None)) except CommandExecutionError as exc: ret['result'] = False ret['comment'] = \ 'Failed to configure repo {0!r}: {1}'.format(name, exc) return ret # aptpkg supports "disabled", yumpkg supports "enabled" # lets just provide both to everyone. if 'enabled' in kwargs and 'disabled' not in kwargs: kw_enabled = kwargs['enabled'] in (['true', 'True', 'TRUE', True, 1]) kwargs['disabled'] = not kw_enabled if 'disabled' in kwargs and 'enabled' not in kwargs: kw_disabled = kwargs['disabled'] in (['true', 'True', 'TRUE', True, 1]) kwargs['enabled'] = not kw_disabled # this is because of how apt-sources works. This pushes distro logic # out of the state itself and into a module that it makes more sense # to use. Most package providers will simply return the data provided # it doesn't require any "specialized" data massaging. if 'pkg.expand_repo_def' in __salt__: sanitizedkwargs = __salt__['pkg.expand_repo_def'](kwargs) else: sanitizedkwargs = kwargs if __grains__['os_family'] == 'Debian': kwargs['repo'] = _strip_uri(kwargs['repo']) if repo: notset = False for kwarg in sanitizedkwargs: if kwarg == 'repo': pass elif kwarg not in repo: notset = True elif kwarg == 'comps': if sorted(sanitizedkwargs[kwarg]) != sorted(repo[kwarg]): notset = True elif kwarg == 'line' and __grains__['os_family'] == 'Debian': # split the line and sort everything after the URL sanitizedsplit = sanitizedkwargs[kwarg].split() sanitizedsplit[3:] = sorted(sanitizedsplit[3:]) reposplit = repo[kwarg].split() reposplit[3:] = sorted(reposplit[3:]) if sanitizedsplit != reposplit: notset = True else: if str(sanitizedkwargs[kwarg]) != str(repo[kwarg]): notset = True if notset is False: ret['result'] = True ret['comment'] = ( 'Package repo {0!r} already configured'.format(name)) return ret if __opts__['test']: ret['comment'] = ( 'Package repo {0!r} will be configured. This may ' 'cause pkg states to behave differently than stated ' 'if this action is repeated without test=True, due ' 'to the differences in the configured repositories.'.format(name)) return ret # empty file before configure if kwargs.get('clean_file', False): open(kwargs['file'], 'w').close() try: if __grains__['os_family'] == 'Debian': __salt__['pkg.mod_repo'](saltenv=__env__, **kwargs) else: __salt__['pkg.mod_repo'](**kwargs) except Exception as exc: # This is another way to pass information back from the mod_repo # function. ret['result'] = False ret['comment'] = \ 'Failed to configure repo {0!r}: {1}'.format(name, exc) return ret try: repodict = __salt__['pkg.get_repo'](kwargs['repo'], ppa_auth=kwargs.get( 'ppa_auth', None)) if repo: for kwarg in sanitizedkwargs: if repodict.get(kwarg) != repo.get(kwarg): change = {'new': repodict[kwarg], 'old': repo.get(kwarg)} ret['changes'][kwarg] = change else: ret['changes'] = {'repo': kwargs['repo']} ret['result'] = True ret['comment'] = 'Configured package repo {0!r}'.format(name) except Exception as exc: ret['result'] = False ret['comment'] = \ 'Failed to confirm config of repo {0!r}: {1}'.format(name, exc) # Clear cache of available packages, if present, since changes to the # repositories may change the packages that are available. if ret['changes']: sys.modules[__salt__['test.ping'].__module__].__context__.pop( 'pkg._avail', None) return ret
def managed(name, ppa=None, **kwargs): ''' This state manages software package repositories. Currently, :mod:`yum <salt.modules.yumpkg>`, :mod:`apt <salt.modules.aptpkg>`, and :mod:`zypper <salt.modules.zypper>` repositories are supported. **YUM OR ZYPPER-BASED SYSTEMS** .. note:: One of ``baseurl`` or ``mirrorlist`` below is required. Additionally, note that this state is not presently capable of managing more than one repo in a single repo file, so each instance of this state will manage a single repo file containing the configuration for a single repo. name This value will be used in two ways: Firstly, it will be the repo ID, as seen in the entry in square brackets (e.g. ``[foo]``) for a given repo. Secondly, it will be the name of the file as stored in /etc/yum.repos.d (e.g. ``/etc/yum.repos.d/foo.conf``). humanname This is used as the "name" value in the repo file in ``/etc/yum.repos.d/`` (or ``/etc/zypp/repos.d`` for SUSE distros). baseurl The URL to a yum repository mirrorlist A URL which points to a file containing a collection of baseurls comments Sometimes you want to supply additional information, but not as enabled configuration. Anything supplied for this list will be saved in the repo configuration with a comment marker (#) in front. Additional configuration values seen in yum repo files, such as ``gpgkey`` or ``gpgcheck``, will be used directly as key-value pairs. For example: .. code-block:: yaml foo: pkgrepo.managed: - humanname: Personal repo for foo - baseurl: https://mydomain.tld/repo/foo/$releasever/$basearch - gpgkey: file:///etc/pki/rpm-gpg/foo-signing-key - gpgcheck: 1 **APT-BASED SYSTEMS** ppa On Ubuntu, you can take advantage of Personal Package Archives on Launchpad simply by specifying the user and archive name. The keyid will be queried from launchpad and everything else is set automatically. You can override any of the below settings by simply setting them as you would normally. For example: .. code-block:: yaml logstash-ppa: pkgrepo.managed: - ppa: wolfnet/logstash ppa_auth For Ubuntu PPAs there can be private PPAs that require authentication to access. For these PPAs the username/password can be passed as an HTTP Basic style username/password combination. .. code-block:: yaml logstash-ppa: pkgrepo.managed: - ppa: wolfnet/logstash - ppa_auth: username:password name On apt-based systems this must be the complete entry as it would be seen in the sources.list file. This can have a limited subset of components (i.e. 'main') which can be added/modified with the ``comps`` option. .. code-block:: yaml precise-repo: pkgrepo.managed: - name: deb http://us.archive.ubuntu.com/ubuntu precise main .. note:: The above example is intended as a more readable way of configuring the SLS, it is equivalent to the following: .. code-block:: yaml 'deb http://us.archive.ubuntu.com/ubuntu precise main': pkgrepo.managed disabled Toggles whether or not the repo is used for resolving dependencies and/or installing packages. comps On apt-based systems, comps dictate the types of packages to be installed from the repository (e.g. main, nonfree, ...). For purposes of this, comps should be a comma-separated list. file The filename for the .list that the repository is configured in. It is important to include the full-path AND make sure it is in a directory that APT will look in when handling packages dist This dictates the release of the distro the packages should be built for. (e.g. unstable). This option is rarely needed. keyid The KeyID of the GPG key to install. This option also requires the ``keyserver`` option to be set. keyserver This is the name of the keyserver to retrieve gpg keys from. The ``keyid`` option must also be set for this option to work. key_url URL to retrieve a GPG key from. Allows the usage of ``http://``, ``https://`` as well as ``salt://``. .. note:: Use either ``keyid``/``keyserver`` or ``key_url``, but not both. consolidate If set to true, this will consolidate all sources definitions to the sources.list file, cleanup the now unused files, consolidate components (e.g. main) for the same URI, type, and architecture to a single line, and finally remove comments from the sources.list file. The consolidate will run every time the state is processed. The option only needs to be set on one repo managed by salt to take effect. clean_file If set to true, empty file before config repo, dangerous if use multiple sources in one file. .. versionadded:: 2015.8.0 refresh_db If set to false this will skip refreshing the apt package database on debian based systems. require_in Set this to a list of pkg.installed or pkg.latest to trigger the running of apt-get update prior to attempting to install these packages. Setting a require in the pkg will not work for this. ''' ret = {'name': name, 'changes': {}, 'result': None, 'comment': ''} if 'pkg.get_repo' not in __salt__: ret['result'] = False ret['comment'] = 'Repo management not implemented on this platform' return ret if 'key_url' in kwargs and ('keyid' in kwargs or 'keyserver' in kwargs): ret['result'] = False ret['comment'] = 'You may not use both "keyid"/"keyserver" and ' \ '"key_url" argument.' if 'repo' in kwargs: ret['result'] = False ret['comment'] = ('\'repo\' is not a supported argument for this ' 'state. The \'name\' argument is probably what was ' 'intended.') return ret if 'enabled' in kwargs: salt.utils.warn_until( 'Nitrogen', 'The `enabled` argument has been deprecated in favor of ' '`disabled`.' ) repo = name if __grains__['os'] in ('Ubuntu', 'Mint'): if ppa is not None: # overload the name/repo value for PPAs cleanly # this allows us to have one code-path for PPAs try: repo = ':'.join(('ppa', ppa)) except TypeError: repo = ':'.join(('ppa', str(ppa))) elif __grains__['os_family'].lower() in ('redhat', 'suse'): if 'humanname' in kwargs: kwargs['name'] = kwargs.pop('humanname') _val = lambda x: '1' if salt.utils.is_true(x) else '0' if 'disabled' in kwargs: if 'enabled' in kwargs: ret['result'] = False ret['comment'] = 'Only one of enabled/disabled is permitted' return ret _reverse = lambda x: '1' if x == '0' else '0' kwargs['enabled'] = _reverse(_val(kwargs.pop('disabled'))) elif 'enabled' in kwargs: kwargs['enabled'] = _val(kwargs['enabled']) if 'name' not in kwargs: # Fall back to the repo name if humanname not provided kwargs['name'] = repo # Replace 'enabled' from kwargs with 'disabled' enabled = kwargs.pop('enabled', True) kwargs['disabled'] = not salt.utils.is_true(enabled) for kwarg in _STATE_INTERNAL_KEYWORDS: kwargs.pop(kwarg, None) try: pre = __salt__['pkg.get_repo']( repo, ppa_auth=kwargs.get('ppa_auth', None) ) except CommandExecutionError as exc: ret['result'] = False ret['comment'] = \ 'Failed to examine repo \'{0}\': {1}'.format(name, exc) return ret # This is because of how apt-sources works. This pushes distro logic # out of the state itself and into a module that it makes more sense # to use. Most package providers will simply return the data provided # it doesn't require any "specialized" data massaging. if 'pkg.expand_repo_def' in __salt__: sanitizedkwargs = __salt__['pkg.expand_repo_def'](repo=repo, **kwargs) else: sanitizedkwargs = kwargs if __grains__['os_family'] == 'Debian': repo = _strip_uri(repo) if pre: needs_update = False for kwarg in sanitizedkwargs: if kwarg not in pre: if kwarg == 'enabled': # On a RedHat-based OS, 'enabled' is assumed to be true if # not explicitly set, so we don't need to update the repo # if it's desired to be enabled and the 'enabled' key is # missing from the repo definition if __grains__['os_family'] == 'RedHat': if not salt.utils.is_true(sanitizedkwargs[kwarg]): needs_update = True else: needs_update = True else: needs_update = True elif kwarg == 'comps': if sorted(sanitizedkwargs[kwarg]) != sorted(pre[kwarg]): needs_update = True elif kwarg == 'line' and __grains__['os_family'] == 'Debian': # split the line and sort everything after the URL sanitizedsplit = sanitizedkwargs[kwarg].split() sanitizedsplit[3:] = sorted(sanitizedsplit[3:]) reposplit = pre[kwarg].split() reposplit[3:] = sorted(reposplit[3:]) if sanitizedsplit != reposplit: needs_update = True if 'comments' in kwargs: _line = pre[kwarg].split('#') if str(kwargs['comments']) not in _line: needs_update = True else: if str(sanitizedkwargs[kwarg]) != str(pre[kwarg]): needs_update = True if not needs_update: ret['result'] = True ret['comment'] = ('Package repo \'{0}\' already configured' .format(name)) return ret if __opts__['test']: ret['comment'] = ( 'Package repo \'{0}\' will be configured. This may cause pkg ' 'states to behave differently than stated if this action is ' 'repeated without test=True, due to the differences in the ' 'configured repositories.'.format(name) ) return ret # empty file before configure if kwargs.get('clean_file', False): with salt.utils.fopen(kwargs['file'], 'w'): pass try: if __grains__['os_family'] == 'Debian': __salt__['pkg.mod_repo'](repo, saltenv=__env__, **kwargs) else: __salt__['pkg.mod_repo'](repo, **kwargs) except Exception as exc: # This is another way to pass information back from the mod_repo # function. ret['result'] = False ret['comment'] = \ 'Failed to configure repo \'{0}\': {1}'.format(name, exc) return ret try: post = __salt__['pkg.get_repo']( repo, ppa_auth=kwargs.get('ppa_auth', None) ) if pre: for kwarg in sanitizedkwargs: if post.get(kwarg) != pre.get(kwarg): change = {'new': post[kwarg], 'old': pre.get(kwarg)} ret['changes'][kwarg] = change else: ret['changes'] = {'repo': repo} ret['result'] = True ret['comment'] = 'Configured package repo \'{0}\''.format(name) except Exception as exc: ret['result'] = False ret['comment'] = \ 'Failed to confirm config of repo \'{0}\': {1}'.format(name, exc) # Clear cache of available packages, if present, since changes to the # repositories may change the packages that are available. if ret['changes']: sys.modules[ __salt__['test.ping'].__module__ ].__context__.pop('pkg._avail', None) return ret