PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/states/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/states/pkgrepo.py |
""" Management of APT/DNF/YUM/Zypper package repos ============================================== States for managing software package repositories on Linux distros. Supported package managers are APT, DNF, YUM and Zypper. Here is some example SLS: .. code-block:: yaml base: pkgrepo.managed: - humanname: CentOS-$releasever - Base - mirrorlist: http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os - comments: - 'http://mirror.centos.org/centos/$releasever/os/$basearch/' - gpgcheck: 1 - gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6 .. code-block:: yaml base: pkgrepo.managed: - humanname: Logstash PPA - name: deb http://ppa.launchpad.net/wolfnet/logstash/ubuntu precise main - dist: precise - file: /etc/apt/sources.list.d/logstash.list - keyid: 28B04E4A - keyserver: keyserver.ubuntu.com - require_in: - pkg: logstash pkg.latest: - name: logstash - refresh: True .. code-block:: yaml base: pkgrepo.managed: - humanname: deb-multimedia - name: deb http://www.deb-multimedia.org stable main - file: /etc/apt/sources.list.d/deb-multimedia.list - key_url: salt://deb-multimedia/files/marillat.pub .. code-block:: yaml base: pkgrepo.managed: - humanname: Google Chrome - name: deb http://dl.google.com/linux/chrome/deb/ stable main - dist: stable - file: /etc/apt/sources.list.d/chrome-browser.list - require_in: - pkg: google-chrome-stable - gpgcheck: 1 - key_url: https://dl-ssl.google.com/linux/linux_signing_key.pub .. code-block:: yaml base: pkgrepo.managed: - ppa: wolfnet/logstash pkg.latest: - name: logstash - refresh: True .. note:: On Ubuntu systems, the ``python-software-properties`` package should be installed for better support of PPA repositories. To check if this package is installed, run ``dpkg -l python-software-properties``. On Ubuntu & Debian systems, the ``python-apt`` package is required to be installed. To check if this package is installed, run ``dpkg -l python-apt``. ``python-apt`` will need to be manually installed if it is not present. .. code-block:: yaml hello-copr: pkgrepo.managed: - copr: mymindstorm/hello pkg.installed: - name: hello apt-key deprecated ------------------ ``apt-key`` is deprecated and will be last available in Debian 11 and Ubuntu 22.04. The recommended way to manage repo keys going forward is to download the keys into /etc/apt/keyrings and use ``signed-by`` in your repo file pointing to the key. This module was updated in version 3005 to implement the recommended approach. You need to add ``- aptkey: False`` to your state and set ``signed-by`` in your repo name, to use this recommended approach. If the cli command ``apt-key`` is not available it will automatically set ``aptkey`` to False. Using ``aptkey: False`` with ``key_url`` example: .. code-block:: yaml deb [signed-by=/etc/apt/keyrings/salt-archive-keyring.gpg arch=amd64] https://repo.saltproject.io/py3/ubuntu/18.04/amd64/latest bionic main: pkgrepo.managed: - file: /etc/apt/sources.list.d/salt.list - key_url: https://repo.saltproject.io/py3/ubuntu/18.04/amd64/latest/salt-archive-keyring.gpg - aptkey: False Using ``aptkey: False`` with ``keyserver`` and ``keyid``: .. code-block:: yaml deb [signed-by=/etc/apt/keyrings/salt-archive-keyring.gpg arch=amd64] https://repo.saltproject.io/py3/ubuntu/18.04/amd64/latest bionic main: pkgrepo.managed: - file: /etc/apt/sources.list.d/salt.list - keyserver: keyserver.ubuntu.com - keyid: 0E08A149DE57BFBE - aptkey: False """ import sys import salt.utils.data import salt.utils.files import salt.utils.pkg.deb import salt.utils.pkg.rpm import salt.utils.versions from salt.exceptions import CommandExecutionError, SaltInvocationError from salt.state import STATE_INTERNAL_KEYWORDS as _STATE_INTERNAL_KEYWORDS def __virtual__(): """ Only load if modifying repos is available for this package type """ return "pkg.mod_repo" in __salt__ def managed(name, ppa=None, copr=None, aptkey=True, **kwargs): """ This state manages software package repositories. Currently, :mod:`yum <salt.modules.yumpkg>`, :mod:`apt <salt.modules.aptpkg>`, and :mod:`zypper <salt.modules.zypperpkg>` repositories are supported. **YUM/DNF/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``). enabled : True Whether the repo is enabled or not. Can be specified as ``True``/``False`` or ``1``/``0``. disabled : False Included to reduce confusion due to APT's use of the ``disabled`` argument. If this is passed for a YUM/DNF/Zypper-based distro, then the reverse will be passed as ``enabled``. For example passing ``disabled=True`` will assume ``enabled=False``. copr Fedora and RedHat based distributions only. Use community packages outside of the main package repository. .. versionadded:: 3002 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. gpgautoimport Only valid for Zypper package manager. If set to ``True``, automatically trust and import the new repository signing key. The key should be specified with ``gpgkey`` parameter. See details below. Additional configuration values seen in YUM/DNF/Zypper 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 (e.g. ``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 : False Toggles whether or not the repo is used for resolving dependencies and/or installing packages. enabled : True Included to reduce confusion due to YUM/DNF/Zypper's use of the ``enabled`` argument. If this is passed for an APT-based distro, then the reverse will be passed as ``disabled``. For example, passing ``enabled=False`` will assume ``disabled=False``. architectures On apt-based systems, ``architectures`` can restrict the available architectures that the repository provides (e.g. only ``amd64``). ``architectures`` should be a comma-separated list. 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 or a list of KeyIDs 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 ``https://`` as well as ``salt://``. If ``allow_insecure_key`` is True, this also allows ``http://``. .. note:: Use either ``keyid``/``keyserver`` or ``key_url``, but not both. key_text The string representation of the GPG key to install. .. versionadded:: 2018.3.0 .. note:: Use either ``keyid``/``keyserver``, ``key_url``, or ``key_text`` but not more than one method. consolidate : False 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 consolidation 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 : False If set to ``True``, empty the file before configuring the defined repository .. note:: Use with care. This can be dangerous if multiple sources are configured in the same file. .. versionadded:: 2015.8.0 refresh : True If set to ``False`` this will skip refreshing the apt package database on Debian based systems. refresh_db : True .. deprecated:: 2018.3.0 Use ``refresh`` instead. require_in Set this to a list of :mod:`pkg.installed <salt.states.pkg.installed>` or :mod:`pkg.latest <salt.states.pkg.latest>` to trigger the running of ``apt-get update`` prior to attempting to install these packages. Setting a require in the pkg state will not work for this. aptkey: Use the binary apt-key. If the command ``apt-key`` is not found in the path, aptkey will be False, regardless of what is passed into this argument. allow_insecure_key : True Whether to allow an insecure (e.g. http vs. https) key_url. .. versionadded:: 3006.0 """ if not salt.utils.path.which("apt-key"): aptkey = False 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 "key_text" in kwargs and ("keyid" in kwargs or "keyserver" in kwargs): ret["result"] = False ret["comment"] = ( 'You may not use both "keyid"/"keyserver" and "key_text" argument.' ) if "key_text" in kwargs and ("key_url" in kwargs): ret["result"] = False ret["comment"] = 'You may not use both "key_url" and "key_text" 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 enabled = kwargs.pop("enabled", None) disabled = kwargs.pop("disabled", None) if enabled is not None and disabled is not None: ret["result"] = False ret["comment"] = "Only one of enabled/disabled is allowed" return ret elif enabled is None and disabled is None: # If neither argument was passed we assume the repo will be enabled enabled = True # To be changed in version 3008: default to False and still log a warning allow_insecure_key = kwargs.pop("allow_insecure_key", True) key_is_insecure = kwargs.get("key_url", "").strip().startswith("http:") if key_is_insecure: if allow_insecure_key: salt.utils.versions.warn_until( 3008, "allow_insecure_key will default to False starting in salt 3008.", ) else: ret["result"] = False ret["comment"] = ( "Cannot have 'key_url' using http with 'allow_insecure_key' set to True" ) 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))) kwargs["disabled"] = ( not salt.utils.data.is_true(enabled) if enabled is not None else salt.utils.data.is_true(disabled) ) elif __grains__["os_family"] in ("RedHat", "Suse"): if __grains__["os_family"] in "RedHat": if copr is not None: repo = ":".join(("copr", copr)) kwargs["name"] = name if "humanname" in kwargs: kwargs["name"] = kwargs.pop("humanname") if "name" not in kwargs: # Fall back to the repo name if humanname not provided kwargs["name"] = repo kwargs["enabled"] = ( not salt.utils.data.is_true(disabled) if disabled is not None else salt.utils.data.is_true(enabled) ) elif __grains__["os_family"] in ("NILinuxRT", "Poky"): # opkg is the pkg virtual kwargs["enabled"] = ( not salt.utils.data.is_true(disabled) if disabled is not None else salt.utils.data.is_true(enabled) ) for kwarg in _STATE_INTERNAL_KEYWORDS: kwargs.pop(kwarg, None) try: pre = __salt__["pkg.get_repo"](repo=repo, **kwargs) except CommandExecutionError as exc: ret["result"] = False ret["comment"] = f"Failed to examine repo '{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 __grains__.get("os_family") == "Debian": from salt.modules.aptpkg import _expand_repo_def os_name = __grains__["os"] os_codename = __grains__["oscodename"] sanitizedkwargs = _expand_repo_def( os_name=os_name, os_codename=os_codename, repo=repo, **kwargs ) else: sanitizedkwargs = kwargs if pre: # 22412: Remove file attribute in case same repo is set up multiple times but with different files pre.pop("file", None) sanitizedkwargs.pop("file", None) 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.data.is_true(sanitizedkwargs[kwarg]): break else: break else: break elif kwarg in ("comps", "key_url"): if sorted(sanitizedkwargs[kwarg]) != sorted(pre[kwarg]): break elif kwarg == "line" and __grains__["os_family"] == "Debian": if not sanitizedkwargs["disabled"]: # split the line and sort everything after the URL sanitizedsplit = sanitizedkwargs[kwarg].split() sanitizedsplit[3:] = sorted(sanitizedsplit[3:]) reposplit, _, pre_comments = ( x.strip() for x in pre[kwarg].partition("#") ) reposplit = reposplit.split() reposplit[3:] = sorted(reposplit[3:]) if sanitizedsplit != reposplit: break if "comments" in kwargs: post_comments = salt.utils.pkg.deb.combine_comments( kwargs["comments"] ) if pre_comments != post_comments: break elif kwarg == "comments" and __grains__["os_family"] == "RedHat": precomments = salt.utils.pkg.rpm.combine_comments(pre[kwarg]) kwargcomments = salt.utils.pkg.rpm.combine_comments( sanitizedkwargs[kwarg] ) if precomments != kwargcomments: break elif kwarg == "architectures" and sanitizedkwargs[kwarg]: if set(sanitizedkwargs[kwarg]) != set(pre[kwarg]): break else: if __grains__["os_family"] in ("RedHat", "Suse") and any( isinstance(x, bool) for x in (sanitizedkwargs[kwarg], pre[kwarg]) ): # This check disambiguates 1/0 from True/False if salt.utils.data.is_true( sanitizedkwargs[kwarg] ) != salt.utils.data.is_true(pre[kwarg]): break else: if str(sanitizedkwargs[kwarg]) != str(pre[kwarg]): break else: ret["result"] = True ret["comment"] = f"Package repo '{name}' already configured" return ret if __opts__["test"]: ret["comment"] = ( "Package repo '{}' would 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) ) if pre: for kwarg in sanitizedkwargs: if sanitizedkwargs.get(kwarg) != pre.get(kwarg): ret["changes"][kwarg] = { "new": sanitizedkwargs.get(kwarg), "old": pre.get(kwarg), } else: ret["changes"]["repo"] = name return ret # empty file before configure if kwargs.get("clean_file", False): with salt.utils.files.fopen(kwargs["file"], "w"): pass try: if __grains__["os_family"] == "Debian": __salt__["pkg.mod_repo"](repo, saltenv=__env__, aptkey=aptkey, **kwargs) else: __salt__["pkg.mod_repo"](repo, **kwargs) except Exception as exc: # pylint: disable=broad-except # This is another way to pass information back from the mod_repo # function. ret["result"] = False ret["comment"] = f"Failed to configure repo '{name}': {exc}" return ret try: post = __salt__["pkg.get_repo"](repo=repo, **kwargs) if pre: for kwarg in sanitizedkwargs: if post.get(kwarg) != pre.get(kwarg): ret["changes"][kwarg] = { "new": post.get(kwarg), "old": pre.get(kwarg), } else: ret["changes"] = {"repo": repo} ret["result"] = True ret["comment"] = f"Configured package repo '{name}'" except Exception as exc: # pylint: disable=broad-except ret["result"] = False ret["comment"] = f"Failed to confirm config of repo '{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 absent(name, **kwargs): """ This function deletes the specified repo on the system, if it exists. It is essentially a wrapper around :mod:`pkg.del_repo <salt.modules.pkg.del_repo>`. name The name of the package repo, as it would be referred to when running the regular package manager commands. .. note:: On apt-based systems this must be the complete source entry. For example, if you include ``[arch=amd64]``, and a repo matching the specified URI, dist, etc. exists _without_ an architecture, then no changes will be made and the state will report a ``True`` result. **FEDORA/REDHAT-SPECIFIC OPTIONS** copr Use community packages outside of the main package repository. .. versionadded:: 3002 .. code-block:: yaml hello-copr: pkgrepo.absent: - copr: mymindstorm/hello **UBUNTU-SPECIFIC OPTIONS** ppa On Ubuntu, you can take advantage of Personal Package Archives on Launchpad simply by specifying the user and archive name. .. code-block:: yaml logstash-ppa: pkgrepo.absent: - 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 specified. This is required for matching if the name format uses the ``ppa:`` specifier and is private (requires username/password to access, which is encoded in the URI). .. code-block:: yaml logstash-ppa: pkgrepo.absent: - ppa: wolfnet/logstash - ppa_auth: username:password keyid If passed, then the GPG key corresponding to the passed KeyID will also be removed. keyid_ppa : False If set to ``True``, the GPG key's ID will be looked up from ppa.launchpad.net and removed, and the ``keyid`` argument will be ignored. .. note:: This option will be disregarded unless the ``ppa`` argument is present. """ ret = {"name": name, "changes": {}, "result": None, "comment": ""} if "ppa" in kwargs and __grains__["os"] in ("Ubuntu", "Mint"): name = kwargs.pop("ppa") if not name.startswith("ppa:"): name = "ppa:" + name if "copr" in kwargs and __grains__["os_family"] in "RedHat": name = kwargs.pop("copr") if not name.startswith("copr:"): name = "copr:" + name remove_key = any(kwargs.get(x) is not None for x in ("keyid", "keyid_ppa")) if remove_key and "pkg.del_repo_key" not in __salt__: ret["result"] = False ret["comment"] = "Repo key management is not implemented for this platform" return ret if __grains__["os_family"] == "Debian": stripname = salt.utils.pkg.deb.strip_uri(name) else: stripname = name try: repo = __salt__["pkg.get_repo"](stripname, **kwargs) except CommandExecutionError as exc: ret["result"] = False ret["comment"] = f"Failed to configure repo '{name}': {exc}" return ret if repo and ( __grains__["os_family"].lower() == "debian" or __opts__.get("providers", {}).get("pkg") == "aptpkg" ): # On Debian/Ubuntu, pkg.get_repo will return a match for the repo # even if the architectures do not match. However, changing get_repo # breaks idempotency for pkgrepo.managed states. So, compare the # architectures of the matched repo to the architectures specified in # the repo string passed to this state. If the architectures do not # match, then invalidate the match by setting repo to an empty dict. from salt.modules.aptpkg import _split_repo_str if set(_split_repo_str(stripname)["architectures"]) != set( repo["architectures"] ): repo = {} if not repo: ret["comment"] = f"Package repo {name} is absent" ret["result"] = True return ret if __opts__["test"]: ret["comment"] = ( "Package repo '{}' will be removed. 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.del_repo"](repo=stripname, **kwargs) except (CommandExecutionError, SaltInvocationError) as exc: ret["result"] = False ret["comment"] = exc.strerror return ret repos = __salt__["pkg.list_repos"]() if stripname not in repos: ret["changes"]["repo"] = name ret["comment"] = f"Removed repo {name}" if not remove_key: ret["result"] = True else: try: removed_keyid = __salt__["pkg.del_repo_key"](stripname, **kwargs) except (CommandExecutionError, SaltInvocationError) as exc: ret["result"] = False ret["comment"] += f", but failed to remove key: {exc}" else: ret["result"] = True ret["changes"]["keyid"] = removed_keyid ret["comment"] += f", and keyid {removed_keyid}" else: ret["result"] = False ret["comment"] = f"Failed to remove repo {name}" return ret