mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 08:58:59 +00:00
398cc78224
Conflicts: - .kitchen.yml - doc/topics/releases/2017.7.6.rst - salt/modules/timezone.py - tests/support/case.py - tests/unit/modules/test_timezone.py
1150 lines
39 KiB
ReStructuredText
1150 lines
39 KiB
ReStructuredText
.. _tutorial-gitfs:
|
|
|
|
==================================
|
|
Git Fileserver Backend Walkthrough
|
|
==================================
|
|
|
|
.. note::
|
|
|
|
This walkthrough assumes basic knowledge of Salt. To get up to speed, check
|
|
out the :ref:`Salt Walkthrough <tutorial-salt-walk-through>`.
|
|
|
|
The gitfs backend allows Salt to serve files from git repositories. It can be
|
|
enabled by adding ``git`` to the :conf_master:`fileserver_backend` list, and
|
|
configuring one or more repositories in :conf_master:`gitfs_remotes`.
|
|
|
|
Branches and tags become Salt fileserver environments.
|
|
|
|
.. note::
|
|
Branching and tagging can result in a lot of potentially-conflicting
|
|
:ref:`top files <states-top>`, for this reason it may be useful to set
|
|
:conf_minion:`top_file_merging_strategy` to ``same`` in the minions' config
|
|
files if the top files are being managed in a GitFS repo.
|
|
|
|
.. _gitfs-dependencies:
|
|
|
|
Installing Dependencies
|
|
=======================
|
|
|
|
Both pygit2_ and GitPython_ are supported Python interfaces to git. If
|
|
compatible versions of both are installed, pygit2_ will be preferred. In these
|
|
cases, GitPython_ can be forced using the :conf_master:`gitfs_provider`
|
|
parameter in the master config file.
|
|
|
|
.. note::
|
|
It is recommended to always run the most recent version of any the below
|
|
dependencies. Certain features of GitFS may not be available without
|
|
the most recent version of the chosen library.
|
|
|
|
.. _pygit2: https://github.com/libgit2/pygit2
|
|
.. _GitPython: https://github.com/gitpython-developers/GitPython
|
|
|
|
pygit2
|
|
------
|
|
|
|
The minimum supported version of pygit2_ is 0.20.3. Availability for this
|
|
version of pygit2_ is still limited, though the SaltStack team is working to
|
|
get compatible versions available for as many platforms as possible.
|
|
|
|
For the Fedora/EPEL versions which have a new enough version packaged, the
|
|
following command would be used to install pygit2_:
|
|
|
|
.. code-block:: bash
|
|
|
|
# yum install python-pygit2
|
|
|
|
Provided a valid version is packaged for Debian/Ubuntu (which is not currently
|
|
the case), the package name would be the same, and the following command would
|
|
be used to install it:
|
|
|
|
.. code-block:: bash
|
|
|
|
# apt-get install python-pygit2
|
|
|
|
|
|
If pygit2_ is not packaged for the platform on which the Master is running, the
|
|
pygit2_ website has installation instructions
|
|
`here <pygit2-install-instructions>`_. Keep in mind however that
|
|
following these instructions will install libgit2_ and pygit2_ without system
|
|
packages. Additionally, keep in mind that :ref:`SSH authentication in pygit2
|
|
<pygit2-authentication-ssh>` requires libssh2_ (*not* libssh) development
|
|
libraries to be present before libgit2_ is built. On some Debian-based distros
|
|
``pkg-config`` is also required to link libgit2_ with libssh2.
|
|
|
|
.. note::
|
|
If you are receiving the error "Unsupported URL Protocol" in the Salt Master
|
|
log when making a connection using SSH, review the libssh2 details listed
|
|
above.
|
|
|
|
Additionally, version 0.21.0 of pygit2 introduced a dependency on python-cffi_,
|
|
which in turn depends on newer releases of libffi_. Upgrading libffi_ is not
|
|
advisable as several other applications depend on it, so on older LTS linux
|
|
releases pygit2_ 0.20.3 and libgit2_ 0.20.0 is the recommended combination.
|
|
|
|
.. warning::
|
|
pygit2_ is actively developed and `frequently makes
|
|
non-backwards-compatible API changes <pygit2-version-policy>`_, even in
|
|
minor releases. It is not uncommon for pygit2_ upgrades to result in errors
|
|
in Salt. Please take care when upgrading pygit2_, and pay close attention
|
|
to the changelog_, keeping an eye out for API changes. Errors can be
|
|
reported on the `SaltStack issue tracker <saltstack-issue-tracker>`_.
|
|
|
|
.. _pygit2-version-policy: http://www.pygit2.org/install.html#version-numbers
|
|
.. _changelog: https://github.com/libgit2/pygit2#changelog
|
|
.. _saltstack-issue-tracker: https://github.com/saltstack/salt/issues
|
|
.. _pygit2-install-instructions: http://www.pygit2.org/install.html
|
|
.. _libgit2: https://libgit2.github.com/
|
|
.. _libssh2: http://www.libssh2.org/
|
|
.. _python-cffi: https://pypi.python.org/pypi/cffi
|
|
.. _libffi: http://sourceware.org/libffi/
|
|
|
|
|
|
RedHat Pygit2 Issues
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The release of RedHat/CentOS 7.3 upgraded both ``python-cffi`` and
|
|
``http-parser``, both of which are dependencies for pygit2_/libgit2_. Both
|
|
``pygit2`` and ``libgit2`` packages (which are from the EPEL repository) should
|
|
be upgraded to the most recent versions, at least to ``0.24.2``.
|
|
|
|
The below errors will show up in the master log if an incompatible
|
|
``python-pygit2`` package is installed:
|
|
|
|
.. code-block:: text
|
|
|
|
2017-02-10 09:07:34,892 [salt.utils.gitfs ][ERROR ][11211] Import pygit2 failed: CompileError: command 'gcc' failed with exit status 1
|
|
2017-02-10 09:07:34,907 [salt.utils.gitfs ][ERROR ][11211] gitfs is configured but could not be loaded, are pygit2 and libgit2 installed?
|
|
2017-02-10 09:07:34,907 [salt.utils.gitfs ][CRITICAL][11211] No suitable gitfs provider module is installed.
|
|
2017-02-10 09:07:34,912 [salt.master ][CRITICAL][11211] Master failed pre flight checks, exiting
|
|
|
|
The below errors will show up in the master log if an incompatible ``libgit2``
|
|
package is installed:
|
|
|
|
.. code-block:: text
|
|
|
|
2017-02-15 18:04:45,211 [salt.utils.gitfs ][ERROR ][6211] Error occurred fetching gitfs remote 'https://foo.com/bar.git': No Content-Type header in response
|
|
|
|
A restart of the ``salt-master`` daemon and gitfs cache directory clean up may
|
|
be required to allow http(s) repositories to continue to be fetched.
|
|
|
|
|
|
GitPython
|
|
---------
|
|
|
|
GitPython_ 0.3.0 or newer is required to use GitPython for gitfs. For
|
|
RHEL-based Linux distros, a compatible version is available in EPEL, and can be
|
|
easily installed on the master using yum:
|
|
|
|
.. code-block:: bash
|
|
|
|
# yum install GitPython
|
|
|
|
Ubuntu 14.04 LTS and Debian Wheezy (7.x) also have a compatible version packaged:
|
|
|
|
.. code-block:: bash
|
|
|
|
# apt-get install python-git
|
|
|
|
GitPython_ requires the ``git`` CLI utility to work. If installed from a system
|
|
package, then git should already be installed, but if installed via pip_ then
|
|
it may still be necessary to install git separately. For MacOS users,
|
|
GitPython_ comes bundled in with the Salt installer, but git must still be
|
|
installed for it to work properly. Git can be installed in several ways,
|
|
including by installing XCode_.
|
|
|
|
.. _pip: http://www.pip-installer.org/
|
|
.. _XCode: https://developer.apple.com/xcode/
|
|
|
|
.. warning::
|
|
|
|
Keep in mind that if GitPython has been previously installed on the master
|
|
using pip (even if it was subsequently uninstalled), then it may still
|
|
exist in the build cache (typically ``/tmp/pip-build-root/GitPython``) if
|
|
the cache is not cleared after installation. The package in the build cache
|
|
will override any requirement specifiers, so if you try upgrading to
|
|
version 0.3.2.RC1 by running ``pip install 'GitPython==0.3.2.RC1'`` then it
|
|
will ignore this and simply install the version from the cache directory.
|
|
Therefore, it may be necessary to delete the GitPython directory from the
|
|
build cache in order to ensure that the specified version is installed.
|
|
|
|
.. warning::
|
|
|
|
GitPython_ 2.0.9 and newer is not compatible with Python 2.6. If installing
|
|
GitPython_ using pip on a machine running Python 2.6, make sure that a
|
|
version earlier than 2.0.9 is installed. This can be done on the CLI by
|
|
running ``pip install 'GitPython<2.0.9'``, or in a :py:func:`pip.installed
|
|
<salt.states.pip_state.installed>` state using the following SLS:
|
|
|
|
.. code-block:: yaml
|
|
|
|
GitPython:
|
|
pip.installed:
|
|
- name: 'GitPython < 2.0.9'
|
|
|
|
|
|
Simple Configuration
|
|
====================
|
|
|
|
To use the gitfs backend, only two configuration changes are required on the
|
|
master:
|
|
|
|
1. Include ``gitfs`` in the :conf_master:`fileserver_backend` list in the
|
|
master config file:
|
|
|
|
.. code-block:: yaml
|
|
|
|
fileserver_backend:
|
|
- gitfs
|
|
|
|
.. note::
|
|
``git`` also works here. Prior to the 2018.3.0 release, *only* ``git``
|
|
would work.
|
|
|
|
2. Specify one or more ``git://``, ``https://``, ``file://``, or ``ssh://``
|
|
URLs in :conf_master:`gitfs_remotes` to configure which repositories to
|
|
cache and search for requested files:
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- https://github.com/saltstack-formulas/salt-formula.git
|
|
|
|
SSH remotes can also be configured using scp-like syntax:
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- git@github.com:user/repo.git
|
|
- ssh://user@domain.tld/path/to/repo.git
|
|
|
|
Information on how to authenticate to SSH remotes can be found :ref:`here
|
|
<gitfs-authentication>`.
|
|
|
|
3. Restart the master to load the new configuration.
|
|
|
|
|
|
.. note::
|
|
|
|
In a master/minion setup, files from a gitfs remote are cached once by the
|
|
master, so minions do not need direct access to the git repository.
|
|
|
|
|
|
Multiple Remotes
|
|
================
|
|
|
|
The ``gitfs_remotes`` option accepts an ordered list of git remotes to
|
|
cache and search, in listed order, for requested files.
|
|
|
|
A simple scenario illustrates this cascading lookup behavior:
|
|
|
|
If the ``gitfs_remotes`` option specifies three remotes:
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- git://github.com/example/first.git
|
|
- https://github.com/example/second.git
|
|
- file:///root/third
|
|
|
|
And each repository contains some files:
|
|
|
|
.. code-block:: yaml
|
|
|
|
first.git:
|
|
top.sls
|
|
edit/vim.sls
|
|
edit/vimrc
|
|
nginx/init.sls
|
|
|
|
second.git:
|
|
edit/dev_vimrc
|
|
haproxy/init.sls
|
|
|
|
third:
|
|
haproxy/haproxy.conf
|
|
edit/dev_vimrc
|
|
|
|
Salt will attempt to lookup the requested file from each gitfs remote
|
|
repository in the order in which they are defined in the configuration. The
|
|
:strong:`git://github.com/example/first.git` remote will be searched first.
|
|
If the requested file is found, then it is served and no further searching
|
|
is executed. For example:
|
|
|
|
* A request for the file :strong:`salt://haproxy/init.sls` will be served from
|
|
the :strong:`https://github.com/example/second.git` git repo.
|
|
* A request for the file :strong:`salt://haproxy/haproxy.conf` will be served from the
|
|
:strong:`file:///root/third` repo.
|
|
|
|
.. note::
|
|
|
|
This example is purposefully contrived to illustrate the behavior of the
|
|
gitfs backend. This example should not be read as a recommended way to lay
|
|
out files and git repos.
|
|
|
|
The :strong:`file://` prefix denotes a git repository in a local directory.
|
|
However, it will still use the given :strong:`file://` URL as a remote,
|
|
rather than copying the git repo to the salt cache. This means that any
|
|
refs you want accessible must exist as *local* refs in the specified repo.
|
|
|
|
.. warning::
|
|
|
|
Salt versions prior to 2014.1.0 are not tolerant of changing the
|
|
order of remotes or modifying the URI of existing remotes. In those
|
|
versions, when modifying remotes it is a good idea to remove the gitfs
|
|
cache directory (``/var/cache/salt/master/gitfs``) before restarting the
|
|
salt-master service.
|
|
|
|
.. _gitfs-per-remote-config:
|
|
|
|
Per-remote Configuration Parameters
|
|
===================================
|
|
|
|
.. versionadded:: 2014.7.0
|
|
|
|
The following master config parameters are global (that is, they apply to all
|
|
configured gitfs remotes):
|
|
|
|
* :conf_master:`gitfs_base`
|
|
* :conf_master:`gitfs_root`
|
|
* :conf_master:`gitfs_ssl_verify`
|
|
* :conf_master:`gitfs_mountpoint` (new in 2014.7.0)
|
|
* :conf_master:`gitfs_user` (**pygit2 only**, new in 2014.7.0)
|
|
* :conf_master:`gitfs_password` (**pygit2 only**, new in 2014.7.0)
|
|
* :conf_master:`gitfs_insecure_auth` (**pygit2 only**, new in 2014.7.0)
|
|
* :conf_master:`gitfs_pubkey` (**pygit2 only**, new in 2014.7.0)
|
|
* :conf_master:`gitfs_privkey` (**pygit2 only**, new in 2014.7.0)
|
|
* :conf_master:`gitfs_passphrase` (**pygit2 only**, new in 2014.7.0)
|
|
* :conf_master:`gitfs_refspecs` (new in 2017.7.0)
|
|
* :conf_master:`gitfs_disable_saltenv_mapping` (new in 2018.3.0)
|
|
* :conf_master:`gitfs_ref_types` (new in 2018.3.0)
|
|
* :conf_master:`gitfs_update_interval` (new in 2018.3.0)
|
|
|
|
.. note::
|
|
pygit2 only supports disabling SSL verification in versions 0.23.2 and
|
|
newer.
|
|
|
|
These parameters can now be overridden on a per-remote basis. This allows for a
|
|
tremendous amount of customization. Here's some example usage:
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_provider: pygit2
|
|
gitfs_base: develop
|
|
|
|
gitfs_remotes:
|
|
- https://foo.com/foo.git
|
|
- https://foo.com/bar.git:
|
|
- root: salt
|
|
- mountpoint: salt://bar
|
|
- base: salt-base
|
|
- ssl_verify: False
|
|
- update_interval: 120
|
|
- https://foo.com/bar.git:
|
|
- name: second_bar_repo
|
|
- root: other/salt
|
|
- mountpoint: salt://other/bar
|
|
- base: salt-base
|
|
- ref_types:
|
|
- branch
|
|
- http://foo.com/baz.git:
|
|
- root: salt/states
|
|
- user: joe
|
|
- password: mysupersecretpassword
|
|
- insecure_auth: True
|
|
- disable_saltenv_mapping: True
|
|
- saltenv:
|
|
- foo:
|
|
- ref: foo
|
|
- http://foo.com/quux.git:
|
|
- all_saltenvs: master
|
|
|
|
.. important::
|
|
|
|
There are two important distinctions which should be noted for per-remote
|
|
configuration:
|
|
|
|
1. The URL of a remote which has per-remote configuration must be suffixed
|
|
with a colon.
|
|
|
|
2. Per-remote configuration parameters are named like the global versions,
|
|
with the ``gitfs_`` removed from the beginning. The exception being the
|
|
``name``, ``saltenv``, and ``all_saltenvs`` parameters, which are only
|
|
available to per-remote configurations.
|
|
|
|
The ``all_saltenvs`` parameter is new in the 2018.3.0 release.
|
|
|
|
In the example configuration above, the following is true:
|
|
|
|
1. The first and fourth gitfs remotes will use the ``develop`` branch/tag as the
|
|
``base`` environment, while the second and third will use the ``salt-base``
|
|
branch/tag as the ``base`` environment.
|
|
|
|
2. The first remote will serve all files in the repository. The second
|
|
remote will only serve files from the ``salt`` directory (and its
|
|
subdirectories). The third remote will only server files from the
|
|
``other/salt`` directory (and its subdirectories), while the fourth remote
|
|
will only serve files from the ``salt/states`` directory (and its
|
|
subdirectories).
|
|
|
|
3. The third remote will only serve files from branches, and not from tags or
|
|
SHAs.
|
|
|
|
4. The fourth remote will only have two saltenvs available: ``base`` (pointed
|
|
at ``develop``), and ``foo`` (pointed at ``foo``).
|
|
|
|
5. The first and fourth remotes will have files located under the root of the
|
|
Salt fileserver namespace (``salt://``). The files from the second remote
|
|
will be located under ``salt://bar``, while the files from the third remote
|
|
will be located under ``salt://other/bar``.
|
|
|
|
6. The second and third remotes reference the same repository and unique names
|
|
need to be declared for duplicate gitfs remotes.
|
|
|
|
7. The fourth remote overrides the default behavior of :ref:`not authenticating
|
|
to insecure (non-HTTPS) remotes <gitfs-insecure-auth>`.
|
|
|
|
8. Because ``all_saltenvs`` is configured for the fifth remote, files from the
|
|
branch/tag ``master`` will appear in every fileserver environment.
|
|
|
|
.. note::
|
|
The use of ``http://`` (instead of ``https://``) is permitted here
|
|
*only* because authentication is not being used. Otherwise, the
|
|
``insecure_auth`` parameter must be used (as in the fourth remote) to
|
|
force Salt to authenticate to an ``http://`` remote.
|
|
|
|
9. The first remote will wait 120 seconds between updates instead of 60.
|
|
|
|
.. _gitfs-per-saltenv-config:
|
|
|
|
Per-Saltenv Configuration Parameters
|
|
====================================
|
|
|
|
.. versionadded:: 2016.11.0
|
|
|
|
For more granular control, Salt allows the following three things to be
|
|
overridden for individual saltenvs within a given repo:
|
|
|
|
- The :ref:`mountpoint <gitfs-walkthrough-mountpoint>`
|
|
- The :ref:`root <gitfs-walkthrough-root>`
|
|
- The branch/tag to be used for a given saltenv
|
|
|
|
Here is an example:
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_root: salt
|
|
|
|
gitfs_saltenv:
|
|
- dev:
|
|
- mountpoint: salt://gitfs-dev
|
|
- ref: develop
|
|
|
|
gitfs_remotes:
|
|
- https://foo.com/bar.git:
|
|
- saltenv:
|
|
- staging:
|
|
- ref: qa
|
|
- mountpoint: salt://bar-staging
|
|
- dev:
|
|
- ref: development
|
|
- https://foo.com/baz.git:
|
|
- saltenv:
|
|
- staging:
|
|
- mountpoint: salt://baz-staging
|
|
|
|
Given the above configuration, the following is true:
|
|
|
|
1. For all gitfs remotes, files for the ``dev`` saltenv will be located under
|
|
``salt://gitfs-dev``.
|
|
|
|
2. For the ``dev`` saltenv, files from the first remote will be sourced from
|
|
the ``development`` branch, while files from the second remote will be
|
|
sourced from the ``develop`` branch.
|
|
|
|
3. For the ``staging`` saltenv, files from the first remote will be located
|
|
under ``salt://bar-staging``, while files from the second remote will be
|
|
located under ``salt://baz-staging``.
|
|
|
|
4. For all gitfs remotes, and in all saltenvs, files will be served from the
|
|
``salt`` directory (and its subdirectories).
|
|
|
|
|
|
.. _gitfs-custom-refspecs:
|
|
|
|
Custom Refspecs
|
|
===============
|
|
|
|
.. versionadded:: 2017.7.0
|
|
|
|
GitFS will by default fetch remote branches and tags. However, sometimes it can
|
|
be useful to fetch custom refs (such as those created for `GitHub pull
|
|
requests`__). To change the refspecs GitFS fetches, use the
|
|
:conf_master:`gitfs_refspecs` config option:
|
|
|
|
.. __: https://help.github.com/articles/checking-out-pull-requests-locally/
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_refspecs:
|
|
- '+refs/heads/*:refs/remotes/origin/*'
|
|
- '+refs/tags/*:refs/tags/*'
|
|
- '+refs/pull/*/head:refs/remotes/origin/pr/*'
|
|
- '+refs/pull/*/merge:refs/remotes/origin/merge/*'
|
|
|
|
In the above example, in addition to fetching remote branches and tags,
|
|
GitHub's custom refs for pull requests and merged pull requests will also be
|
|
fetched. These special ``head`` refs represent the head of the branch which is
|
|
requesting to be merged, and the ``merge`` refs represent the result of the
|
|
base branch after the merge.
|
|
|
|
.. important::
|
|
When using custom refspecs, the destination of the fetched refs *must* be
|
|
under ``refs/remotes/origin/``, preferably in a subdirectory like in the
|
|
example above. These custom refspecs will map as environment names using
|
|
their relative path underneath ``refs/remotes/origin/``. For example,
|
|
assuming the configuration above, the head branch for pull request 12345
|
|
would map to fileserver environment ``pr/12345`` (slash included).
|
|
|
|
Refspecs can be configured on a :ref:`per-remote basis
|
|
<gitfs-per-remote-config>`. For example, the below configuration would only
|
|
alter the default refspecs for the *second* GitFS remote. The first remote
|
|
would only fetch branches and tags (the default).
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- https://domain.tld/foo.git
|
|
- https://domain.tld/bar.git:
|
|
- refspecs:
|
|
- '+refs/heads/*:refs/remotes/origin/*'
|
|
- '+refs/tags/*:refs/tags/*'
|
|
- '+refs/pull/*/head:refs/remotes/origin/pr/*'
|
|
- '+refs/pull/*/merge:refs/remotes/origin/merge/*'
|
|
|
|
|
|
.. _gitfs-global-remotes:
|
|
|
|
Global Remotes
|
|
==============
|
|
|
|
.. versionadded:: 2018.3.0
|
|
|
|
The ``all_saltenvs`` per-remote configuration parameter overrides the logic
|
|
Salt uses to map branches/tags to fileserver environments (i.e. saltenvs). This
|
|
allows a single branch/tag to appear in *all* saltenvs.
|
|
|
|
This is very useful in particular when working with :ref:`salt formulas
|
|
<conventions-formula>`. Prior to the addition of this feature, it was necessary
|
|
to push a branch/tag to the remote repo for each saltenv in which that formula
|
|
was to be used. If the formula needed to be updated, this update would need to
|
|
be reflected in all of the other branches/tags. This is both inconvenient and
|
|
not scalable.
|
|
|
|
With ``all_saltenvs``, it is now possible to define your formula once, in a
|
|
single branch.
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- http://foo.com/quux.git:
|
|
- all_saltenvs: anything
|
|
|
|
.. _gitfs-update-intervals:
|
|
|
|
Update Intervals
|
|
================
|
|
|
|
Prior to the 2018.3.0 release, GitFS would update its fileserver backends as part
|
|
of a dedicated "maintenance" process, in which various routine maintenance
|
|
tasks were performed. This tied the update interval to the
|
|
:conf_master:`loop_interval` config option, and also forced all fileservers to
|
|
update at the same interval.
|
|
|
|
Now it is possible to make GitFS update at its own interval, using
|
|
:conf_master:`gitfs_update_interval`:
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_update_interval: 180
|
|
|
|
gitfs_remotes:
|
|
- https://foo.com/foo.git
|
|
- https://foo.com/bar.git:
|
|
- update_interval: 120
|
|
|
|
Using the above configuration, the first remote would update every three
|
|
minutes, while the second remote would update every two minutes.
|
|
|
|
Configuration Order of Precedence
|
|
=================================
|
|
|
|
The order of precedence for GitFS configuration is as follows (each level
|
|
overrides all levels below it):
|
|
|
|
1. Per-saltenv configuration (defined under a per-remote ``saltenv``
|
|
param)
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- https://foo.com/bar.git:
|
|
- saltenv:
|
|
- dev:
|
|
- mountpoint: salt://bar
|
|
|
|
2. Global per-saltenv configuration (defined in :conf_master:`gitfs_saltenv`)
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_saltenv:
|
|
- dev:
|
|
- mountpoint: salt://bar
|
|
|
|
3. Per-remote configuration parameter
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- https://foo.com/bar.git:
|
|
- mountpoint: salt://bar
|
|
|
|
4. Global configuration parameter
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_mountpoint: salt://bar
|
|
|
|
.. note::
|
|
The one exception to the above is when :ref:`all_saltenvs
|
|
<gitfs-global-remotes>` is used. This value overrides all logic for mapping
|
|
branches/tags to fileserver environments. So, even if
|
|
:conf_master:`gitfs_saltenv` is used to globally override the mapping for a
|
|
given saltenv, :ref:`all_saltenvs <gitfs-global-remotes>` would take
|
|
precedence for any remote which uses it.
|
|
|
|
It's important to note however that any ``root`` and ``mountpoint`` values
|
|
configured in :conf_master:`gitfs_saltenv` (or :ref:`per-saltenv
|
|
configuration <gitfs-per-saltenv-config>`) would be unaffected by this.
|
|
|
|
.. _gitfs-walkthrough-root:
|
|
|
|
Serving from a Subdirectory
|
|
===========================
|
|
|
|
The :conf_master:`gitfs_root` parameter allows files to be served from a
|
|
subdirectory within the repository. This allows for only part of a repository
|
|
to be exposed to the Salt fileserver.
|
|
|
|
Assume the below layout:
|
|
|
|
.. code-block:: text
|
|
|
|
.gitignore
|
|
README.txt
|
|
foo/
|
|
foo/bar/
|
|
foo/bar/one.txt
|
|
foo/bar/two.txt
|
|
foo/bar/three.txt
|
|
foo/baz/
|
|
foo/baz/top.sls
|
|
foo/baz/edit/vim.sls
|
|
foo/baz/edit/vimrc
|
|
foo/baz/nginx/init.sls
|
|
|
|
The below configuration would serve only the files under ``foo/baz``, ignoring
|
|
the other files in the repository:
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- git://mydomain.com/stuff.git
|
|
|
|
gitfs_root: foo/baz
|
|
|
|
The root can also be configured on a :ref:`per-remote basis
|
|
<gitfs-per-remote-config>`.
|
|
|
|
|
|
.. _gitfs-walkthrough-mountpoint:
|
|
|
|
Mountpoints
|
|
===========
|
|
|
|
.. versionadded:: 2014.7.0
|
|
|
|
The :conf_master:`gitfs_mountpoint` parameter will prepend the specified path
|
|
to the files served from gitfs. This allows an existing repository to be used,
|
|
rather than needing to reorganize a repository or design it around the layout
|
|
of the Salt fileserver.
|
|
|
|
Before the addition of this feature, if a file being served up via gitfs was
|
|
deeply nested within the root directory (for example,
|
|
``salt://webapps/foo/files/foo.conf``, it would be necessary to ensure that the
|
|
file was properly located in the remote repository, and that all of the
|
|
parent directories were present (for example, the directories
|
|
``webapps/foo/files/`` would need to exist at the root of the repository).
|
|
|
|
The below example would allow for a file ``foo.conf`` at the root of the
|
|
repository to be served up from the Salt fileserver path
|
|
``salt://webapps/foo/files/foo.conf``.
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- https://mydomain.com/stuff.git
|
|
|
|
gitfs_mountpoint: salt://webapps/foo/files
|
|
|
|
Mountpoints can also be configured on a :ref:`per-remote basis
|
|
<gitfs-per-remote-config>`.
|
|
|
|
|
|
Using gitfs in Masterless Mode
|
|
==============================
|
|
|
|
Since 2014.7.0, gitfs can be used in masterless mode. To do so, simply add the
|
|
gitfs configuration parameters (and set :conf_master:`fileserver_backend`) in
|
|
the _minion_ config file instead of the master config file.
|
|
|
|
|
|
Using gitfs Alongside Other Backends
|
|
====================================
|
|
|
|
Sometimes it may make sense to use multiple backends; for instance, if ``sls``
|
|
files are stored in git but larger files are stored directly on the master.
|
|
|
|
The cascading lookup logic used for multiple remotes is also used with multiple
|
|
backends. If the :conf_master:`fileserver_backend` option contains multiple
|
|
backends:
|
|
|
|
.. code-block:: yaml
|
|
|
|
fileserver_backend:
|
|
- roots
|
|
- git
|
|
|
|
Then the ``roots`` backend (the default backend of files in ``/srv/salt``) will
|
|
be searched first for the requested file; then, if it is not found on the
|
|
master, each configured git remote will be searched.
|
|
|
|
Branches, Environments, and Top Files
|
|
=====================================
|
|
|
|
When using the GitFS backend, branches, and tags will be mapped to environments
|
|
using the branch/tag name as an identifier.
|
|
|
|
There is one exception to this rule: the ``master`` branch is implicitly mapped
|
|
to the ``base`` environment.
|
|
|
|
So, for a typical ``base``, ``qa``, ``dev`` setup, the following branches could
|
|
be used:
|
|
|
|
.. code-block:: yaml
|
|
|
|
master
|
|
qa
|
|
dev
|
|
|
|
``top.sls`` files from different branches will be merged into one at runtime.
|
|
Since this can lead to overly complex configurations, the recommended setup is
|
|
to have a separate repository, containing only the ``top.sls`` file with just
|
|
one single ``master`` branch.
|
|
|
|
To map a branch other than ``master`` as the ``base`` environment, use the
|
|
:conf_master:`gitfs_base` parameter.
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_base: salt-base
|
|
|
|
The base can also be configured on a :ref:`per-remote basis
|
|
<gitfs-per-remote-config>`.
|
|
|
|
|
|
.. _gitfs-whitelist-blacklist:
|
|
|
|
Environment Whitelist/Blacklist
|
|
===============================
|
|
|
|
.. versionadded:: 2014.7.0
|
|
|
|
The :conf_master:`gitfs_saltenv_whitelist` and
|
|
:conf_master:`gitfs_saltenv_blacklist` parameters allow for greater control
|
|
over which branches/tags are exposed as fileserver environments. Exact matches,
|
|
globs, and regular expressions are supported, and are evaluated in that order.
|
|
If using a regular expression, ``^`` and ``$`` must be omitted, and the
|
|
expression must match the entire branch/tag.
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_saltenv_whitelist:
|
|
- base
|
|
- v1.*
|
|
- 'mybranch\d+'
|
|
|
|
.. note::
|
|
|
|
``v1.*``, in this example, will match as both a glob and a regular
|
|
expression (though it will have been matched as a glob, since globs are
|
|
evaluated before regular expressions).
|
|
|
|
The behavior of the blacklist/whitelist will differ depending on which
|
|
combination of the two options is used:
|
|
|
|
* If only :conf_master:`gitfs_saltenv_whitelist` is used, then **only**
|
|
branches/tags which match the whitelist will be available as environments
|
|
|
|
* If only :conf_master:`gitfs_saltenv_blacklist` is used, then the
|
|
branches/tags which match the blacklist will **not** be available as
|
|
environments
|
|
|
|
* If both are used, then the branches/tags which match the whitelist, but do
|
|
**not** match the blacklist, will be available as environments.
|
|
|
|
.. _gitfs-authentication:
|
|
|
|
Authentication
|
|
==============
|
|
|
|
pygit2
|
|
------
|
|
|
|
.. versionadded:: 2014.7.0
|
|
|
|
Both HTTPS and SSH authentication are supported as of version 0.20.3, which is
|
|
the earliest version of pygit2_ supported by Salt for gitfs.
|
|
|
|
.. note::
|
|
|
|
The examples below make use of per-remote configuration parameters, a
|
|
feature new to Salt 2014.7.0. More information on these can be found
|
|
:ref:`here <gitfs-per-remote-config>`.
|
|
|
|
HTTPS
|
|
~~~~~
|
|
|
|
For HTTPS repositories which require authentication, the username and password
|
|
can be provided like so:
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- https://domain.tld/myrepo.git:
|
|
- user: git
|
|
- password: mypassword
|
|
|
|
.. _gitfs-insecure-auth:
|
|
|
|
If the repository is served over HTTP instead of HTTPS, then Salt will by
|
|
default refuse to authenticate to it. This behavior can be overridden by adding
|
|
an ``insecure_auth`` parameter:
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- http://domain.tld/insecure_repo.git:
|
|
- user: git
|
|
- password: mypassword
|
|
- insecure_auth: True
|
|
|
|
.. _pygit2-authentication-ssh:
|
|
|
|
SSH
|
|
~~~
|
|
|
|
SSH repositories can be configured using the ``ssh://`` protocol designation,
|
|
or using scp-like syntax. So, the following two configurations are equivalent:
|
|
|
|
* ``ssh://git@github.com/user/repo.git``
|
|
* ``git@github.com:user/repo.git``
|
|
|
|
Both :conf_master:`gitfs_pubkey` and :conf_master:`gitfs_privkey` (or their
|
|
:ref:`per-remote counterparts <gitfs-per-remote-config>`) must be configured in
|
|
order to authenticate to SSH-based repos. If the private key is protected with
|
|
a passphrase, it can be configured using :conf_master:`gitfs_passphrase` (or
|
|
simply ``passphrase`` if being configured :ref:`per-remote
|
|
<gitfs-per-remote-config>`). For example:
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- git@github.com:user/repo.git:
|
|
- pubkey: /root/.ssh/id_rsa.pub
|
|
- privkey: /root/.ssh/id_rsa
|
|
- passphrase: myawesomepassphrase
|
|
|
|
Finally, the SSH host key must be :ref:`added to the known_hosts file
|
|
<gitfs-ssh-fingerprint>`.
|
|
|
|
.. note::
|
|
There is a known issue with public-key SSH authentication to Microsoft
|
|
Visual Studio (VSTS) with pygit2. This is due to a bug or lack of support
|
|
for VSTS in older libssh2 releases. Known working releases include libssh2
|
|
1.7.0 and later, and known incompatible releases include 1.5.0 and older.
|
|
At the time of this writing, 1.6.0 has not been tested.
|
|
|
|
Since upgrading libssh2 would require rebuilding many other packages (curl,
|
|
etc.), followed by a rebuild of libgit2 and a reinstall of pygit2, an
|
|
easier workaround for systems with older libssh2 is to use GitPython with a
|
|
passphraseless key for authentication.
|
|
|
|
GitPython
|
|
---------
|
|
|
|
HTTPS
|
|
~~~~~
|
|
|
|
For HTTPS repositories which require authentication, the username and password
|
|
can be configured in one of two ways. The first way is to include them in the
|
|
URL using the format ``https://<user>:<password>@<url>``, like so:
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- https://git:mypassword@domain.tld/myrepo.git
|
|
|
|
The other way would be to configure the authentication in ``~/.netrc``:
|
|
|
|
.. code-block:: text
|
|
|
|
machine domain.tld
|
|
login git
|
|
password mypassword
|
|
|
|
|
|
If the repository is served over HTTP instead of HTTPS, then Salt will by
|
|
default refuse to authenticate to it. This behavior can be overridden by adding
|
|
an ``insecure_auth`` parameter:
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- http://git:mypassword@domain.tld/insecure_repo.git:
|
|
- insecure_auth: True
|
|
|
|
SSH
|
|
~~~
|
|
|
|
Only passphrase-less SSH public key authentication is supported using
|
|
GitPython. **The auth parameters (pubkey, privkey, etc.) shown in the pygit2
|
|
authentication examples above do not work with GitPython.**
|
|
|
|
.. code-block:: yaml
|
|
|
|
gitfs_remotes:
|
|
- ssh://git@github.com/example/salt-states.git
|
|
|
|
Since GitPython_ wraps the git CLI, the private key must be located in
|
|
``~/.ssh/id_rsa`` for the user under which the Master is running, and should
|
|
have permissions of ``0600``. Also, in the absence of a user in the repo URL,
|
|
GitPython_ will (just as SSH does) attempt to login as the current user (in
|
|
other words, the user under which the Master is running, usually ``root``).
|
|
|
|
If a key needs to be used, then ``~/.ssh/config`` can be configured to use
|
|
the desired key. Information on how to do this can be found by viewing the
|
|
manpage for ``ssh_config``. Here's an example entry which can be added to the
|
|
``~/.ssh/config`` to use an alternate key for gitfs:
|
|
|
|
.. code-block:: text
|
|
|
|
Host github.com
|
|
IdentityFile /root/.ssh/id_rsa_gitfs
|
|
|
|
The ``Host`` parameter should be a hostname (or hostname glob) that matches the
|
|
domain name of the git repository.
|
|
|
|
It is also necessary to :ref:`add the SSH host key to the known_hosts file
|
|
<gitfs-ssh-fingerprint>`. The exception to this would be if strict host key
|
|
checking is disabled, which can be done by adding ``StrictHostKeyChecking no``
|
|
to the entry in ``~/.ssh/config``
|
|
|
|
.. code-block:: text
|
|
|
|
Host github.com
|
|
IdentityFile /root/.ssh/id_rsa_gitfs
|
|
StrictHostKeyChecking no
|
|
|
|
However, this is generally regarded as insecure, and is not recommended.
|
|
|
|
.. _gitfs-ssh-fingerprint:
|
|
|
|
Adding the SSH Host Key to the known_hosts File
|
|
-----------------------------------------------
|
|
|
|
To use SSH authentication, it is necessary to have the remote repository's SSH
|
|
host key in the ``~/.ssh/known_hosts`` file. If the master is also a minion,
|
|
this can be done using the :mod:`ssh.set_known_host
|
|
<salt.modules.ssh.set_known_host>` function:
|
|
|
|
.. code-block:: bash
|
|
|
|
# salt mymaster ssh.set_known_host user=root hostname=github.com
|
|
mymaster:
|
|
----------
|
|
new:
|
|
----------
|
|
enc:
|
|
ssh-rsa
|
|
fingerprint:
|
|
16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
|
|
hostname:
|
|
|1|OiefWWqOD4kwO3BhoIGa0loR5AA=|BIXVtmcTbPER+68HvXmceodDcfI=
|
|
key:
|
|
AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
|
old:
|
|
None
|
|
status:
|
|
updated
|
|
|
|
If not, then the easiest way to add the key is to su to the user (usually
|
|
``root``) under which the salt-master runs and attempt to login to the
|
|
server via SSH:
|
|
|
|
.. code-block:: text
|
|
|
|
$ su -
|
|
Password:
|
|
# ssh github.com
|
|
The authenticity of host 'github.com (192.30.252.128)' can't be established.
|
|
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
|
|
Are you sure you want to continue connecting (yes/no)? yes
|
|
Warning: Permanently added 'github.com,192.30.252.128' (RSA) to the list of known hosts.
|
|
Permission denied (publickey).
|
|
|
|
It doesn't matter if the login was successful, as answering ``yes`` will write
|
|
the fingerprint to the known_hosts file.
|
|
|
|
Verifying the Fingerprint
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
To verify that the correct fingerprint was added, it is a good idea to look it
|
|
up. One way to do this is to use ``nmap``:
|
|
|
|
.. code-block:: bash
|
|
|
|
$ nmap -p 22 github.com --script ssh-hostkey
|
|
|
|
Starting Nmap 5.51 ( http://nmap.org ) at 2014-08-18 17:47 CDT
|
|
Nmap scan report for github.com (192.30.252.129)
|
|
Host is up (0.17s latency).
|
|
Not shown: 996 filtered ports
|
|
PORT STATE SERVICE
|
|
22/tcp open ssh
|
|
| ssh-hostkey: 1024 ad:1c:08:a4:40:e3:6f:9c:f5:66:26:5d:4b:33:5d:8c (DSA)
|
|
|_2048 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48 (RSA)
|
|
80/tcp open http
|
|
443/tcp open https
|
|
9418/tcp open git
|
|
|
|
Nmap done: 1 IP address (1 host up) scanned in 28.78 seconds
|
|
|
|
Another way is to check one's own ``known_hosts`` file, using this one-liner:
|
|
|
|
.. code-block:: bash
|
|
|
|
$ ssh-keygen -l -f /dev/stdin <<<`ssh-keyscan github.com 2>/dev/null` | awk '{print $2}'
|
|
16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
|
|
|
|
.. warning::
|
|
AWS tracks usage of nmap and may flag it as abuse. On AWS hosts, the
|
|
``ssh-keygen`` method is recommended for host key verification.
|
|
|
|
.. note::
|
|
As of `OpenSSH 6.8`_ the SSH fingerprint is now shown as a base64-encoded
|
|
SHA256 checksum of the host key. So, instead of the fingerprint looking
|
|
like ``16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48``, it would look
|
|
like ``SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8``.
|
|
|
|
.. _`OpenSSH 6.8`: http://www.openssh.com/txt/release-6.8
|
|
|
|
Refreshing gitfs Upon Push
|
|
==========================
|
|
|
|
By default, Salt updates the remote fileserver backends every 60 seconds.
|
|
However, if it is desirable to refresh quicker than that, the :ref:`Reactor
|
|
System <reactor>` can be used to signal the master to update the fileserver on
|
|
each push, provided that the git server is also a Salt minion. There are three
|
|
steps to this process:
|
|
|
|
1. On the master, create a file **/srv/reactor/update_fileserver.sls**, with
|
|
the following contents:
|
|
|
|
.. code-block:: yaml
|
|
|
|
update_fileserver:
|
|
runner.fileserver.update
|
|
|
|
2. Add the following reactor configuration to the master config file:
|
|
|
|
.. code-block:: yaml
|
|
|
|
reactor:
|
|
- 'salt/fileserver/gitfs/update':
|
|
- /srv/reactor/update_fileserver.sls
|
|
|
|
3. On the git server, add a `post-receive hook`_
|
|
|
|
a. If the user executing `git push` is the same as the minion user, use the following hook:
|
|
|
|
.. code-block:: bash
|
|
|
|
#!/usr/bin/env sh
|
|
salt-call event.fire_master update salt/fileserver/gitfs/update
|
|
|
|
b. To enable other git users to run the hook after a `push`, use sudo in the hook script:
|
|
|
|
.. code-block:: bash
|
|
|
|
#!/usr/bin/env sh
|
|
sudo -u root salt-call event.fire_master update salt/fileserver/gitfs/update
|
|
|
|
4. If using sudo in the git hook (above), the policy must be changed to permit
|
|
all users to fire the event. Add the following policy to the sudoers file
|
|
on the git server.
|
|
|
|
.. code-block:: bash
|
|
|
|
Cmnd_Alias SALT_GIT_HOOK = /bin/salt-call event.fire_master update salt/fileserver/gitfs/update
|
|
Defaults!SALT_GIT_HOOK !requiretty
|
|
ALL ALL=(root) NOPASSWD: SALT_GIT_HOOK
|
|
|
|
The ``update`` argument right after :mod:`event.fire_master
|
|
<salt.modules.event.fire_master>` in this example can really be anything, as it
|
|
represents the data being passed in the event, and the passed data is ignored
|
|
by this reactor.
|
|
|
|
Similarly, the tag name ``salt/fileserver/gitfs/update`` can be replaced by
|
|
anything, so long as the usage is consistent.
|
|
|
|
The ``root`` user name in the hook script and sudo policy should be changed to
|
|
match the user under which the minion is running.
|
|
|
|
.. _`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
|
|
======================================
|
|
|
|
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. This configuration schema is detailed :ref:`here
|
|
<git-pillar-configuration>`.
|
|
|
|
.. _faq-gitfs-bug:
|
|
|
|
Why aren't my custom modules/states/etc. syncing to my Minions?
|
|
===============================================================
|
|
|
|
In versions 0.16.3 and older, when using the :mod:`git fileserver backend
|
|
<salt.fileserver.gitfs>`, certain versions of GitPython may generate errors
|
|
when fetching, which Salt fails to catch. While not fatal to the fetch process,
|
|
these interrupt the fileserver update that takes place before custom types are
|
|
synced, and thus interrupt the sync itself. Try disabling the git fileserver
|
|
backend in the master config, restarting the master, and attempting the sync
|
|
again.
|
|
|
|
This issue is worked around in Salt 0.16.4 and newer.
|