mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 08:58:59 +00:00
Merge pull request #26501 from terminalmage/git_pillar_docs
Update git_pillar docs, add git.list_worktrees function
This commit is contained in:
commit
2fee5708bb
@ -37,13 +37,182 @@ A new docker :mod:`state <salt.states.dockerng>` and :mod:`execution module
|
||||
of the existing state and execution module, but for now will exist alongside
|
||||
them.
|
||||
|
||||
Git State and Execution Modules Rewritten
|
||||
=========================================
|
||||
|
||||
The git state and execution modules have gone through an extensive overhaul.
|
||||
|
||||
Changes in the :py:func:`git.latest <salt.states.git.latest>` State
|
||||
-------------------------------------------------------------------
|
||||
|
||||
- The ``branch`` parameter has been added, allowing for a custom branch name to
|
||||
be used in the local checkout maintained by the :py:func:`git.latest
|
||||
<salt.states.git.latest>` state. This can be helpful in avoiding ambiguous
|
||||
refs in the local checkout when a tag is used as the ``rev`` parameter. If no
|
||||
``branch`` is specified, then the state uses the value of ``rev`` as the
|
||||
branch name.
|
||||
- The ``remote_name`` parameter has been deprecated and renamed to ``remote``.
|
||||
- The ``force`` parameter has been deprecated and renamed to ``force_clone`` to
|
||||
reduce ambiguity with the other "force" parameters.
|
||||
- Using SHA1 hashes (full or shortened) in the ``rev`` parameter is now
|
||||
properly supported.
|
||||
- Non-fast-forward merges are now detected before the repository is updated,
|
||||
and the state will not update the repository if the change is not a
|
||||
fast-forward. Non-fast-forward updates must be overridden with the
|
||||
``force_reset`` parameter. If ``force_reset`` is set to ``True``, the state
|
||||
will only reset the repository if it cannot be fast-forwarded. This is in
|
||||
contrast to the earlier behavior, in which a hard-reset would be performed
|
||||
every time the state was run if ``force_reset`` was set to ``True``.
|
||||
- A ``git pull`` is no longer performed by this state, dropped in favor of a
|
||||
fetch-and-merge (or fetch-and-reset) workflow.
|
||||
|
||||
:py:func:`git.config_unset <salt.states.git.config_unset>` state added
|
||||
----------------------------------------------------------------------
|
||||
|
||||
This state allows for configuration values (or entire keys) to be unset. See
|
||||
:py:func:`here <salt.states.git.config_unset>` for more information and example
|
||||
SLS.
|
||||
|
||||
git.config State Renamed to :py:func:`git.config_set <salt.states.git.config_set>`
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
To reduce confusion after the addition of :py:func:`git.config_unset
|
||||
<salt.states.git.config_unset>`, the git.config state has been renamed to
|
||||
:py:func:`git.config_set <salt.states.git.config_set>`. The old config.get name
|
||||
will still work for a couple releases, allowing time for SLS files to be
|
||||
updated.
|
||||
|
||||
In addition, this state now supports managing multivar git configuration
|
||||
values. See :py:func:`here <salt.states.git.config_set>` for more information
|
||||
and example SLS.
|
||||
|
||||
Initial Support for Git Worktrees in Execution Module
|
||||
-----------------------------------------------------
|
||||
|
||||
Several functions have been added to the execution module to manage worktrees_
|
||||
(a feature new to Git 2.5.0). State support does not exist yet, but will follow
|
||||
soon.
|
||||
|
||||
.. _worktrees: http://git-scm.com/docs/git-worktree
|
||||
|
||||
New Functions in Git Execution Module
|
||||
-------------------------------------
|
||||
|
||||
- :py:func:`git.config_get_regexp <salt.modules.git.config_regexp>`
|
||||
- :py:func:`git.config_unset <salt.modules.git.config_unset>`
|
||||
- :py:func:`git.is_worktree <salt.modules.git.is_worktree>`
|
||||
- :py:func:`git.list_branches <salt.modules.git.list_branches>`
|
||||
- :py:func:`git.list_tags <salt.modules.git.list_tags>`
|
||||
- :py:func:`git.list_worktrees <salt.modules.git.list_worktrees>`
|
||||
- :py:func:`git.merge_base <salt.modules.git.merge_base>`
|
||||
- :py:func:`git.merge_tree <salt.modules.git.merge_tree>`
|
||||
- :py:func:`git.rev_parse <salt.modules.git.rev_parse>`
|
||||
- :py:func:`git.version <salt.modules.git.version>`
|
||||
- :py:func:`git.worktree_rm <salt.modules.git.worktree_rm>`
|
||||
- :py:func:`git.worktree_add <salt.modules.git.worktree_add>`
|
||||
- :py:func:`git.worktree_prune <salt.modules.git.worktree_prune>`
|
||||
|
||||
Changes to Functions in Git Execution Module
|
||||
--------------------------------------------
|
||||
|
||||
:py:func:`git.add <salt.states.git.add>`
|
||||
****************************************
|
||||
|
||||
- ``--verbose`` is now implied when running the ``git add`` command, to provide
|
||||
a list of the files added in the return data.
|
||||
|
||||
:py:func:`git.archive <salt.modules.git.archive>`
|
||||
*************************************************
|
||||
|
||||
- Now returns ``True`` when the ``git archive`` command was successful, and
|
||||
otherwise raises an error.
|
||||
- ``overwrite`` argument added to prevent an exixting archive from being
|
||||
overwritten by this function.
|
||||
- ``fmt`` argument deprecated and renamed to ``format``
|
||||
- Trailing slash no longer implied in ``prefix`` argument, must be included if
|
||||
this argument is passed.
|
||||
|
||||
:py:func:`git.checkout <salt.modules.git.checkout>`
|
||||
***************************************************
|
||||
|
||||
- The ``rev`` argument is now optional when using ``-b`` or ``-B`` in ``opts``,
|
||||
allowing for a branch to be created (or reset) using ``HEAD`` as the starting
|
||||
point.
|
||||
|
||||
:py:func:`git.clone <salt.modules.git.clone>`
|
||||
*********************************************
|
||||
|
||||
- The ``name`` argument has been added to specify the name of the directory in
|
||||
which to clone the repository. If this option is specified, then the clone
|
||||
will be made within the directory specified by the ``cwd``, instead of at
|
||||
that location.
|
||||
- ``repository`` argument deprecated and renamed to ``url``
|
||||
|
||||
:py:func:`git.config_get <salt.modules.git.config_get>`
|
||||
*******************************************************
|
||||
|
||||
- ``setting_name`` argument deprecated and renamed to ``key``
|
||||
- The ``global`` argument has been added, to query the global git configuration
|
||||
- The ``all`` argument has been added to return a list of all values for the
|
||||
specified key, allowing for all values in a multivar to be returned.
|
||||
- ``cwd`` argument is now optional if ``global`` is set to ``True``
|
||||
|
||||
:py:func:`git.config_set <salt.modules.git.config_set>`
|
||||
*******************************************************
|
||||
|
||||
- The value(s) of the key being set are now returned
|
||||
- ``setting_name`` argument deprecated and renamed to ``key``
|
||||
- ``setting_value`` argument deprecated and renamed to ``value``
|
||||
- ``is_global`` argument deprecated and renamed to ``global``
|
||||
- The ``multivar`` argument has been added to specify a list of values to set
|
||||
for the specified key. The ``value`` argument is not compatible with
|
||||
``multivar``.
|
||||
- The ``add`` argument has been added to add a value to a key (this essentially
|
||||
just adds an ``--add`` to the ``git config`` command that is run to set the
|
||||
value).
|
||||
|
||||
:py:func:`git.ls_remote <salt.modules.git.ls_remote>`
|
||||
*****************************************************
|
||||
|
||||
- ``repository`` argument deprecated and renamed to ``remote``
|
||||
- ``branch`` argument deprecated and renamed to ``ref``
|
||||
- The ``opts`` argument has been added to allow for additional CLI options to
|
||||
be passed to the ``git ls-remote`` command.
|
||||
|
||||
:py:func:`git.merge <salt.modules.git.merge>`
|
||||
*********************************************
|
||||
|
||||
- The ``branch`` argument deprecated and renamed to ``rev``
|
||||
|
||||
:py:func:`git.status <salt.modules.git.status>`
|
||||
***********************************************
|
||||
|
||||
- Return data has been changed from a list of lists to a dictionary containing
|
||||
lists of files in the modified, added, deleted, and untracked states.
|
||||
|
||||
:py:func:`git.submodule <salt.modules.git.submodule>`
|
||||
*****************************************************
|
||||
|
||||
- Added the ``command`` argument to allow for operations other than ``update``
|
||||
to be run on submodules, and deprecated the ``init`` argument. To do a
|
||||
submodule update with ``init=True`` moving forward, use ``command=update
|
||||
opts='--init'``
|
||||
|
||||
|
||||
Git Pillar Rewritten
|
||||
====================
|
||||
|
||||
The Git external pillar has been rewritten to bring it up to feature parity
|
||||
with :mod:`gitfs <salt.fileserver.gitfs>`. See :mod:`here
|
||||
<salt.pillar.git_pillar>` for more information on the new git_pillar
|
||||
functionality.
|
||||
The git external pillar has been rewritten to bring it up to feature parity
|
||||
with :mod:`gitfs <salt.fileserver.gitfs>`. Support for pygit2_ has been added,
|
||||
bring with it the ability to access authenticated repositories.
|
||||
|
||||
Using the new features will require updates to the git ext_pillar
|
||||
configuration, further details can be found :ref:`here
|
||||
<git-pillar-2015-8-0-and-later>`.
|
||||
|
||||
.. note::
|
||||
As with :mod:`gitfs <salt.fileserver.gitfs>`, pygit2_ 0.20.3 is required to
|
||||
use pygit2_ with the git external pillar.
|
||||
|
||||
Windows Software Repo Changes
|
||||
=============================
|
||||
|
@ -739,45 +739,22 @@ anything, so long as the usage is consistent.
|
||||
|
||||
.. _`post-receive hook`: http://www.git-scm.com/book/en/Customizing-Git-Git-Hooks#Server-Side-Hooks
|
||||
|
||||
.. _git-as-ext_pillar
|
||||
|
||||
Using Git as an External Pillar Source
|
||||
======================================
|
||||
|
||||
Git repositories can also be used to provide :doc:`Pillar
|
||||
</topics/pillar/index>` data, using the :doc:`External Pillar
|
||||
</topics/development/external_pillars>` system. Note that this is different
|
||||
from gitfs, and is not yet at feature parity with it.
|
||||
The git external pillar (a.k.a. git_pillar) has been rewritten for the 2015.8.0
|
||||
release. This rewrite brings with it pygit2_ support (allowing for access to
|
||||
authenticated repositories), as well as more granular support for per-remote
|
||||
configuration.
|
||||
|
||||
To define a git external pillar, add a section like the following to the salt
|
||||
master config file:
|
||||
To make use of the new features, changes to the git ext_pillar configuration
|
||||
must be made. The new configuration schema is detailed :ref:`here
|
||||
<git-pillar-2015-8-0-and-later>`.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
ext_pillar:
|
||||
- git: <branch> <repo> [root=<gitroot>]
|
||||
|
||||
.. versionchanged:: 2014.7.0
|
||||
The optional ``root`` parameter was added
|
||||
|
||||
The ``<branch>`` param is the branch containing the pillar SLS tree. The
|
||||
``<repo>`` param is the URI for the repository. To add the
|
||||
``master`` branch of the specified repo as an external pillar source:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
ext_pillar:
|
||||
- git: master https://domain.com/pillar.git
|
||||
|
||||
Use the ``root`` parameter to use pillars from a subdirectory of a git
|
||||
repository:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
ext_pillar:
|
||||
- git: master https://domain.com/pillar.git root=subdirectory
|
||||
|
||||
More information on the git external pillar can be found in the
|
||||
:mod:`salt.pillar.git_pillar docs <salt.pillar.git_pillar>`.
|
||||
For Salt releases before 2015.8.0, click :ref:`here <git-pillar-pre-2015-8-0>`
|
||||
for documentation.
|
||||
|
||||
|
||||
.. _faq-gitfs-bug:
|
||||
|
@ -342,10 +342,10 @@ list of the winrepo config options, see :ref:`here <winrepo-config-opts>`.
|
||||
Starting in version 2015.8.0, the :py:func:`winrepo.update_git_repos
|
||||
<salt.runners.winrepo.update_git_repos>` runner now makes use of the same
|
||||
underlying code used by the :ref:`Git Fileserver Backend <tutorial-gitfs>` and
|
||||
:ref:`Git External Pillar <tutorial-git_pillar>` to maintain and update its
|
||||
local clones of git repositories. If a compatible version of either pygit2_
|
||||
(0.20.3 and later) or GitPython_ (0.3.0 or later) is installed, then Salt will
|
||||
use it instead of the old method (which invokes the :py:func:`git.latest
|
||||
:ref:`Git External Pillar <git-as-ext_pillar>` to maintain and update its local
|
||||
clones of git repositories. If a compatible version of either pygit2_ (0.20.3
|
||||
and later) or GitPython_ (0.3.0 or later) is installed, then Salt will use it
|
||||
instead of the old method (which invokes the :py:func:`git.latest
|
||||
<salt.states.git.latest>` state).
|
||||
|
||||
.. note::
|
||||
@ -388,7 +388,7 @@ example of this would be the following:
|
||||
- passphrase: myaw3s0m3pa$$phr4$3
|
||||
- https://github.com/myuser/privaterepo.git:
|
||||
- user: mygithubuser
|
||||
- password: correcthorsebatterystaple
|
||||
- password: CorrectHorseBatteryStaple
|
||||
|
||||
.. note::
|
||||
Per-remote configuration settings work in the same fashion as they do in
|
||||
|
@ -78,7 +78,7 @@ def init_git_pillar(opts):
|
||||
)
|
||||
else:
|
||||
ret.append(
|
||||
git_pillar.LegacyGitPillar(
|
||||
git_pillar._LegacyGitPillar(
|
||||
br,
|
||||
loc,
|
||||
opts
|
||||
|
@ -6,6 +6,7 @@ from __future__ import absolute_import
|
||||
|
||||
# Import python libs
|
||||
import copy
|
||||
import errno
|
||||
import logging
|
||||
import os
|
||||
import shlex
|
||||
@ -231,7 +232,10 @@ def _git_run(command, cwd=None, runas=None, identity=None,
|
||||
return result
|
||||
else:
|
||||
if failhard:
|
||||
msg = 'Command \'{0}\' failed'.format(command)
|
||||
gitcommand = ' '.join(command) \
|
||||
if isinstance(command, list) \
|
||||
else command
|
||||
msg = 'Command \'{0}\' failed'.format(gitcommand)
|
||||
if result['stderr']:
|
||||
msg += ': {0}'.format(result['stderr'])
|
||||
raise CommandExecutionError(msg)
|
||||
@ -782,6 +786,8 @@ def config_get(key,
|
||||
If ``True``, query the global git configuraton. Otherwise, only the
|
||||
local git configuration will be queried.
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
all : False
|
||||
If ``True``, return a list of all values set for ``key``. If the key
|
||||
does not exist, ``None`` will be returned.
|
||||
@ -864,9 +870,6 @@ def config_get_regexp(key,
|
||||
cwd
|
||||
The path to the git checkout
|
||||
|
||||
.. versionchanged:: 2015.8.0
|
||||
Now optional if ``global`` is set to ``True``
|
||||
|
||||
global : False
|
||||
If ``True``, query the global git configuraton. Otherwise, only the
|
||||
local git configuration will be queried.
|
||||
@ -931,11 +934,6 @@ def config_set(key,
|
||||
The path to the git checkout. Must be an absolute path, or the word
|
||||
``global`` to indicate that a global key should be set.
|
||||
|
||||
.. versionchanged:: 2015.8.0
|
||||
Can now be set to ``global`` instead of an absolute path, to set a
|
||||
global git configuration parameter, deprecating the ``is_global``
|
||||
parameter.
|
||||
|
||||
.. versionchanged:: 2014.7.0
|
||||
Made ``cwd`` argument optional if ``is_global=True``
|
||||
|
||||
@ -953,7 +951,7 @@ def config_set(key,
|
||||
Argument renamed from ``setting_value`` to ``value``
|
||||
|
||||
add : False
|
||||
Add a value to a multivar
|
||||
Add a value to a key, creating/updating a multivar
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
@ -1551,6 +1549,103 @@ def list_tags(cwd, user=None, ignore_retcode=False):
|
||||
ignore_retcode=ignore_retcode)['stdout'].splitlines()
|
||||
|
||||
|
||||
def list_worktrees(cwd, stale=False, user=None, **kwargs):
|
||||
'''
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Return a dictionary mapping worktrees to their locations.
|
||||
|
||||
.. note::
|
||||
This information is compiled by analyzing the administrative data in
|
||||
$GIT_DIR/worktrees. By default, only worktrees for which the gitdir is
|
||||
still present are returned, but this can be changed using the ``all``
|
||||
and ``stale`` arguments (described below).
|
||||
|
||||
cwd
|
||||
The path to the git checkout
|
||||
|
||||
user
|
||||
User under which to run the git command. By default, the command is run
|
||||
by the user under which the minion is running.
|
||||
|
||||
all : False
|
||||
If ``True``, then return all worktrees, including ones whose gitdir is
|
||||
no longer present.
|
||||
|
||||
stale : False
|
||||
If ``True``, return only worktrees whose gitdir is no longer present.
|
||||
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion git.list_worktrees /path/to/repo
|
||||
salt myminion git.list_worktrees /path/to/repo all=True
|
||||
salt myminion git.list_worktrees /path/to/repo stale=True
|
||||
'''
|
||||
cwd = _expand_path(cwd, user)
|
||||
kwargs = salt.utils.clean_kwargs(**kwargs)
|
||||
all_ = kwargs.pop('all', False)
|
||||
if kwargs:
|
||||
salt.utils.invalid_kwargs(kwargs)
|
||||
|
||||
if all_ and stale:
|
||||
raise CommandExecutionError(
|
||||
'\'all\' and \'stale\' cannot both be set to True'
|
||||
)
|
||||
|
||||
try:
|
||||
worktree_root = rev_parse(cwd, opts=['--git-path', 'worktrees'])
|
||||
except CommandExecutionError as exc:
|
||||
msg = 'Failed to find worktree location for ' + cwd
|
||||
log.error(msg, exc_info_on_loglevel=logging.DEBUG)
|
||||
raise CommandExecutionError(msg)
|
||||
if worktree_root.startswith('.git'):
|
||||
worktree_root = os.path.join(cwd, worktree_root)
|
||||
if not os.path.isdir(worktree_root):
|
||||
return {}
|
||||
|
||||
worktree_info = {}
|
||||
for worktree_name in os.listdir(worktree_root):
|
||||
gitdir_file = os.path.join(worktree_root, worktree_name, 'gitdir')
|
||||
try:
|
||||
with salt.utils.fopen(gitdir_file, 'r') as fp_:
|
||||
for line in fp_:
|
||||
worktree_loc = line.rstrip('\n')
|
||||
if worktree_loc.endswith('/.git'):
|
||||
worktree_loc = worktree_loc[:-5]
|
||||
worktree_info[worktree_name] = worktree_loc
|
||||
break
|
||||
except (IOError, OSError) as exc:
|
||||
if exc.errno == errno.EEXIST:
|
||||
log.warning(
|
||||
gitdir_file + ' does not exist, data for worktree ' +
|
||||
worktree_name + ' may be corrupted. Try pruning worktrees.'
|
||||
)
|
||||
elif exc.errno == errno.EACCES:
|
||||
raise CommandExecutionError(
|
||||
'Permission denied reading from ' + gitdir_file
|
||||
)
|
||||
else:
|
||||
raise CommandExecutionError(
|
||||
'Error {0} encountered reading from {1}: {2}'.format(
|
||||
exc.errno, gitdir_file, exc.strerror
|
||||
)
|
||||
)
|
||||
|
||||
if all_ or not worktree_info:
|
||||
return worktree_info
|
||||
|
||||
ret = {}
|
||||
for worktree_name, worktree_loc in six.iteritems(worktree_info):
|
||||
worktree_is_stale = not os.path.isdir(worktree_loc)
|
||||
if (stale and worktree_is_stale) \
|
||||
or (not stale and not worktree_is_stale):
|
||||
ret[worktree_name] = worktree_loc
|
||||
return ret
|
||||
|
||||
|
||||
def ls_remote(cwd=None,
|
||||
remote='origin',
|
||||
ref='master',
|
||||
@ -1678,11 +1773,6 @@ def merge(cwd,
|
||||
The remote branch or revision to merge into the current branch
|
||||
Revision to merge into the current branch
|
||||
|
||||
.. versionchanged:: 2015.8.0
|
||||
Default value changed from ``'@{upstream}'`` to ``None`` (unset),
|
||||
allowing this function to merge the remote tracking branch without
|
||||
having to specify it
|
||||
|
||||
.. deprecated:: 2015.8.0
|
||||
Use ``rev`` instead.
|
||||
|
||||
@ -2038,8 +2128,6 @@ def push(cwd,
|
||||
ignore_retcode=False,
|
||||
branch=None):
|
||||
'''
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
Interface to `git-push(1)`_
|
||||
|
||||
cwd
|
||||
@ -2416,7 +2504,7 @@ def reset(cwd, opts='', user=None, ignore_retcode=False):
|
||||
ignore_retcode=ignore_retcode)['stdout']
|
||||
|
||||
|
||||
def rev_parse(cwd, rev, opts='', user=None, ignore_retcode=False):
|
||||
def rev_parse(cwd, rev=None, opts='', user=None, ignore_retcode=False):
|
||||
'''
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
@ -2429,6 +2517,9 @@ def rev_parse(cwd, rev, opts='', user=None, ignore_retcode=False):
|
||||
Revision to parse. See the `SPECIFYING REVISIONS`_ section of the
|
||||
`git-rev-parse(1)`_ manpage for details on how to format this argument.
|
||||
|
||||
This argument is optional when using the options in the `Options for
|
||||
Files` section of the `git-rev-parse(1)`_ manpage.
|
||||
|
||||
opts
|
||||
Any additional options to add to the command line, in a single string
|
||||
|
||||
@ -2440,10 +2531,9 @@ def rev_parse(cwd, rev, opts='', user=None, ignore_retcode=False):
|
||||
If ``True``, do not log an error to the minion log if the git command
|
||||
returns a nonzero exit status.
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
.. _`git-rev-parse(1)`: http://git-scm.com/docs/git-rev-parse
|
||||
.. _`SPECIFYING REVISIONS`: http://git-scm.com/docs/git-rev-parse#_specifying_revisions
|
||||
.. _`Options for Files`: http://git-scm.com/docs/git-rev-parse#_options_for_files
|
||||
|
||||
|
||||
CLI Examples:
|
||||
@ -2458,11 +2548,16 @@ def rev_parse(cwd, rev, opts='', user=None, ignore_retcode=False):
|
||||
salt myminion git.rev_parse /path/to/repo 'develop@{upstream}' opts='--abbrev-ref'
|
||||
# Get the SHA1 for the commit corresponding to tag v1.2.3
|
||||
salt myminion git.rev_parse /path/to/repo 'v1.2.3^{commit}'
|
||||
# Find out whether or not the repo at /path/to/repo is a bare repository
|
||||
salt myminion git.rev_parse /path/to/repo opts='--is-bare-repository'
|
||||
'''
|
||||
cwd = _expand_path(cwd, user)
|
||||
command = ['git', 'rev-parse']
|
||||
command.extend(_format_opts(opts))
|
||||
command.append(rev)
|
||||
if rev is not None:
|
||||
if not isinstance(rev, six.string_types):
|
||||
rev = str(rev)
|
||||
command.append(rev)
|
||||
return _git_run(command,
|
||||
cwd=cwd,
|
||||
runas=user,
|
||||
@ -2616,7 +2711,7 @@ def stash(cwd, action='save', opts='', user=None, ignore_retcode=False):
|
||||
def status(cwd, user=None, ignore_retcode=False):
|
||||
'''
|
||||
.. versionchanged:: 2015.8.0
|
||||
Return data has changed from a list of tuples to a dictionary
|
||||
Return data has changed from a list of lists to a dictionary
|
||||
|
||||
Returns the changes to the repository
|
||||
|
||||
@ -2836,6 +2931,8 @@ def symbolic_ref(cwd,
|
||||
|
||||
def version(versioninfo=False, user=None):
|
||||
'''
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Returns the version of Git installed on the minion
|
||||
|
||||
versioninfo : False
|
||||
|
@ -26,6 +26,8 @@ The branch/tag which maps to that environment must then be specified along with
|
||||
the repo's URL. Configuration details can be found below.
|
||||
|
||||
|
||||
.. _git-pillar-pre-2015-8-0:
|
||||
|
||||
Configuring git_pillar for Salt releases before 2015.8.0
|
||||
========================================================
|
||||
|
||||
@ -96,13 +98,22 @@ The corresponding Pillar top file would look like this:
|
||||
'*':
|
||||
- bar
|
||||
|
||||
.. _git-pillar-2015-8-0-and-later:
|
||||
|
||||
Configuring git_pillar for Salt releases 2015.8.0 and later
|
||||
===========================================================
|
||||
|
||||
Beginning with Salt version 2015.8.0, pygit2_ is now supported for git_pillar,
|
||||
in addition to GitPython_ (Dulwich_ will not be supported for the forseeable
|
||||
future). The requirements for GitPython_ and pygit2_ are the same as for gitfs,
|
||||
as described :ref:`here <gitfs-dependencies>`.
|
||||
.. note::
|
||||
In version 2015.8.0, the method of configuring git external pillars has
|
||||
changed, and now more closely resembles that of the :ref:`Git Fileserver
|
||||
Backend <tutorial-gitfs>`. If Salt detects the old configuration schema, it
|
||||
will use the pre-2015.8.0 code to compile the external pillar. A warning
|
||||
will also be logged.
|
||||
|
||||
Beginning with Salt version 2015.8.0, pygit2_ is now supported in addition to
|
||||
GitPython_ (Dulwich_ will not be supported for the forseeable future). The
|
||||
requirements for GitPython_ and pygit2_ are the same as for gitfs, as described
|
||||
:ref:`here <gitfs-dependencies>`.
|
||||
|
||||
Here is an example git_pillar configuration.
|
||||
|
||||
@ -110,13 +121,27 @@ Here is an example git_pillar configuration.
|
||||
|
||||
ext_pillar:
|
||||
- git:
|
||||
# Use 'prod' instead of the branch name 'production' as the environment
|
||||
- production https://gitserver/git-pillar.git:
|
||||
- env: prod
|
||||
# Use 'dev' instead of the branch name 'develop' as the environment
|
||||
- develop https://gitserver/git-pillar.git:
|
||||
- env: dev
|
||||
# No per-remote config parameters (and no trailing colon), 'qa' will
|
||||
# be used as the environment
|
||||
- qa https://gitserver/git-pillar.git
|
||||
- master https://other-git-server/pillardata.git
|
||||
# SSH key authentication
|
||||
- master git@other-git-server:pillardata-ssh.git:
|
||||
# Pillar SLS files will be read from the 'pillar' subdirectory in
|
||||
# this repository
|
||||
- root: pillar
|
||||
- privkey: /path/to/key
|
||||
- pubkey: /path/to/key.pub
|
||||
- passphrase: CorrectHorseBatteryStaple
|
||||
# HTTPS authentication
|
||||
- master https://other-git-server/pillardata-https.git:
|
||||
- user: git
|
||||
- password: CorrectHorseBatteryStaple
|
||||
|
||||
The main difference between this and the old way of configuring git_pillar is
|
||||
that multiple remotes can be configured under one ``git`` section under
|
||||
@ -129,10 +154,10 @@ configuration parameters can also be set.
|
||||
|
||||
With the addition of pygit2_ support, git_pillar can now interact with
|
||||
authenticated remotes. Authentication works just like in gitfs (as outlined in
|
||||
the :ref:`GitFS Walkthrough <gitfs-authentication>`), only with the global
|
||||
authenication parameter names prefixed with ``git_pillar`` instead of ``gitfs``
|
||||
(e.g. :conf_master:`git_pillar_pubkey`, :conf_master:`git_pillar_privkey`,
|
||||
:conf_master:`git_pillar_passphrase`, etc.).
|
||||
the :ref:`Git Fileserver Backend Walkthrough <gitfs-authentication>`), only
|
||||
with the global authenication parameter names prefixed with ``git_pillar``
|
||||
instead of ``gitfs`` (e.g. :conf_master:`git_pillar_pubkey`,
|
||||
:conf_master:`git_pillar_privkey`, :conf_master:`git_pillar_passphrase`, etc.).
|
||||
|
||||
A full list of the git_pillar configuration options can be found :ref:`here
|
||||
<git_pillar-config-opts>`.
|
||||
@ -209,7 +234,7 @@ def __virtual__():
|
||||
|
||||
def ext_pillar(minion_id, repo, pillar_dirs):
|
||||
'''
|
||||
Execute a command and read the output as YAML
|
||||
Checkout the ext_pillar sources and compile the resulting pillar SLS
|
||||
'''
|
||||
if isinstance(repo, six.string_types):
|
||||
return _legacy_git_pillar(minion_id, repo, pillar_dirs)
|
||||
@ -228,7 +253,7 @@ def ext_pillar(minion_id, repo, pillar_dirs):
|
||||
|
||||
|
||||
# Legacy git_pillar code
|
||||
class LegacyGitPillar(object):
|
||||
class _LegacyGitPillar(object):
|
||||
'''
|
||||
Deal with the remote git repository for Pillar
|
||||
'''
|
||||
@ -363,7 +388,7 @@ def _legacy_git_pillar(minion_id, repo_string, pillar_dirs):
|
||||
# environment is "different" from the branch
|
||||
branch, _, environment = branch_env.partition(':')
|
||||
|
||||
gitpil = LegacyGitPillar(branch, repo_location, __opts__)
|
||||
gitpil = _LegacyGitPillar(branch, repo_location, __opts__)
|
||||
branch = gitpil.branch
|
||||
|
||||
if environment == '':
|
||||
@ -402,7 +427,7 @@ def _update(branch, repo_location):
|
||||
|
||||
return boolean whether it worked
|
||||
'''
|
||||
gitpil = LegacyGitPillar(branch, repo_location, __opts__)
|
||||
gitpil = _LegacyGitPillar(branch, repo_location, __opts__)
|
||||
|
||||
return gitpil.update()
|
||||
|
||||
@ -411,7 +436,7 @@ def _envs(branch, repo_location):
|
||||
'''
|
||||
Return a list of refs that can be used as environments
|
||||
'''
|
||||
gitpil = LegacyGitPillar(branch, repo_location, __opts__)
|
||||
gitpil = _LegacyGitPillar(branch, repo_location, __opts__)
|
||||
|
||||
return gitpil.envs()
|
||||
|
||||
|
@ -1,18 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Interaction with Git repositories
|
||||
=================================
|
||||
States to manage git repositories and git configuration
|
||||
|
||||
Important: Before using git over ssh, make sure your remote host fingerprint
|
||||
exists in your ``~/.ssh/known_hosts`` file. To avoid requiring password
|
||||
authentication, it is also possible to pass private keys to use explicitly.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
https://github.com/saltstack/salt.git:
|
||||
git.latest:
|
||||
- rev: develop
|
||||
- target: /tmp/salt
|
||||
.. important::
|
||||
Before using git over ssh, make sure your remote host fingerprint exists in
|
||||
your ``~/.ssh/known_hosts`` file.
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
|
||||
@ -109,7 +101,7 @@ def _strip_exc(exc):
|
||||
Strip the actual command that was run from exc.strerror to leave just the
|
||||
error message
|
||||
'''
|
||||
return re.sub('^Command [\'"].+[\'"] failed: ', '', exc.strerror)
|
||||
return re.sub(r'^Command [\'"].+[\'"] failed: ', '', exc.strerror)
|
||||
|
||||
|
||||
def _neutral_test(ret, comment):
|
||||
|
@ -865,21 +865,24 @@ class GitModuleTest(integration.ModuleCase):
|
||||
|
||||
@skipIf(not _worktrees_supported(),
|
||||
'Git 2.5 or newer required for worktree support')
|
||||
def test_worktree(self):
|
||||
def test_worktrees(self):
|
||||
'''
|
||||
This tests git.worktree_add, git.is_worktree, git.worktree_rm, and
|
||||
git.worktree_prune
|
||||
This tests git.worktree_add, git.is_worktree, git.list_worktrees,
|
||||
git.worktree_rm, and git.worktree_prune
|
||||
'''
|
||||
worktree_name = 'hotfix'
|
||||
worktree_path = tempfile.mkdtemp(dir=integration.TMP)
|
||||
worktree_basename = os.path.basename(worktree_path)
|
||||
# Add a new worktree
|
||||
worktree_path2 = tempfile.mkdtemp(dir=integration.TMP)
|
||||
worktree_basename2 = os.path.basename(worktree_path2)
|
||||
# Add the worktrees
|
||||
ret = self.run_function(
|
||||
'git.worktree_add',
|
||||
[self.repo, worktree_path],
|
||||
branch=worktree_name
|
||||
'git.worktree_add', [self.repo, worktree_path],
|
||||
)
|
||||
self.assertTrue('Enter ' + worktree_path in ret)
|
||||
ret = self.run_function(
|
||||
'git.worktree_add', [self.repo, worktree_path2]
|
||||
)
|
||||
self.assertTrue('Enter ' + worktree_path2 in ret)
|
||||
# Check if this new path is a worktree
|
||||
self.assertTrue(self.run_function('git.is_worktree', [worktree_path]))
|
||||
# Check if the main repo is a worktree
|
||||
@ -888,13 +891,56 @@ class GitModuleTest(integration.ModuleCase):
|
||||
empty_dir = tempfile.mkdtemp(dir=integration.TMP)
|
||||
self.assertFalse(self.run_function('git.is_worktree', [empty_dir]))
|
||||
shutil.rmtree(empty_dir)
|
||||
# Remove the worktree
|
||||
# Both worktrees should show up here
|
||||
self.assertEqual(
|
||||
self.run_function('git.list_worktrees', [self.repo]),
|
||||
{os.path.basename(worktree_path): worktree_path,
|
||||
os.path.basename(worktree_path2): worktree_path2}
|
||||
)
|
||||
# There should be no stale worktrees right now
|
||||
self.assertEqual(
|
||||
self.run_function('git.list_worktrees', [self.repo], stale=True),
|
||||
{}
|
||||
)
|
||||
# Both worktrees should show in the all=True output
|
||||
self.assertEqual(
|
||||
self.run_function(
|
||||
'git.list_worktrees',
|
||||
[self.repo],
|
||||
**{'all': True}
|
||||
),
|
||||
{os.path.basename(worktree_path): worktree_path,
|
||||
os.path.basename(worktree_path2): worktree_path2}
|
||||
)
|
||||
# Remove the first worktree
|
||||
self.assertTrue(self.run_function('git.worktree_rm', [worktree_path]))
|
||||
# The first worktree should no longer show up here
|
||||
self.assertEqual(
|
||||
self.run_function('git.list_worktrees', [self.repo]),
|
||||
{os.path.basename(worktree_path2): worktree_path2}
|
||||
)
|
||||
# The first worktree should be identified as stale now
|
||||
self.assertEqual(
|
||||
self.run_function('git.list_worktrees', [self.repo], stale=True),
|
||||
{os.path.basename(worktree_path): worktree_path}
|
||||
)
|
||||
# Both worktrees should show in the all=True output
|
||||
self.assertEqual(
|
||||
self.run_function(
|
||||
'git.list_worktrees',
|
||||
[self.repo],
|
||||
**{'all': True}
|
||||
),
|
||||
{os.path.basename(worktree_path): worktree_path,
|
||||
os.path.basename(worktree_path2): worktree_path2}
|
||||
)
|
||||
# Prune the worktrees
|
||||
prune_message = (
|
||||
'Removing worktrees/{0}: gitdir file points to non-existent '
|
||||
'location'.format(worktree_basename)
|
||||
)
|
||||
# Test dry run output. It should match the same output we get when we
|
||||
# actually prune the worktrees.
|
||||
self.assertEqual(
|
||||
self.run_function(
|
||||
'git.worktree_prune',
|
||||
@ -907,6 +953,27 @@ class GitModuleTest(integration.ModuleCase):
|
||||
self.run_function('git.worktree_prune', [self.repo]),
|
||||
prune_message
|
||||
)
|
||||
# The first worktree should still no longer show up here
|
||||
self.assertEqual(
|
||||
self.run_function('git.list_worktrees', [self.repo]),
|
||||
{os.path.basename(worktree_path2): worktree_path2}
|
||||
)
|
||||
# The first worktree should no loner be identified as stale, since it
|
||||
# was just pruned.
|
||||
self.assertEqual(
|
||||
self.run_function('git.list_worktrees', [self.repo], stale=True),
|
||||
{}
|
||||
)
|
||||
# Only the second worktree should still show in the all=True output,
|
||||
# since the first was pruned.
|
||||
self.assertEqual(
|
||||
self.run_function(
|
||||
'git.list_worktrees',
|
||||
[self.repo],
|
||||
**{'all': True}
|
||||
),
|
||||
{os.path.basename(worktree_path2): worktree_path2}
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -107,9 +107,9 @@ class PillarModuleTest(integration.ModuleCase):
|
||||
'cachedir': self.master_opts['cachedir'],
|
||||
}
|
||||
|
||||
git_pillar.LegacyGitPillar('master', original_url, opts)
|
||||
git_pillar._LegacyGitPillar('master', original_url, opts)
|
||||
opts['ext_pillar'] = [{'git': 'master {0}'.format(changed_url)}]
|
||||
grepo = git_pillar.LegacyGitPillar('master', changed_url, opts)
|
||||
grepo = git_pillar._LegacyGitPillar('master', changed_url, opts)
|
||||
repo = git.Repo(rp_location)
|
||||
|
||||
self.assertEqual(grepo.rp_location, repo.remotes.origin.url)
|
||||
@ -123,7 +123,7 @@ class PillarModuleTest(integration.ModuleCase):
|
||||
pillar = self.run_function('pillar.data')
|
||||
|
||||
for branch, env in [('dev', 'testing')]:
|
||||
repo = git_pillar.LegacyGitPillar(branch, repo_url, self.master_opts)
|
||||
repo = git_pillar._LegacyGitPillar(branch, repo_url, self.master_opts)
|
||||
|
||||
self.assertIn(repo.working_dir,
|
||||
pillar['test_ext_pillar_opts']['pillar_roots'][env])
|
||||
|
Loading…
Reference in New Issue
Block a user