コード例 #1
0
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
コード例 #2
0
ファイル: pkgrepo.py プロジェクト: MadeiraCloud/salt
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
コード例 #3
0
ファイル: pkgrepo.py プロジェクト: saltyus/salt
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
コード例 #4
0
ファイル: pkgrepo.py プロジェクト: bryson/salt
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