salt/tests/unit/fileserver/test_gitfs.py
Erik Johnson 2d6760ee40
Add update_interval to gitfs, "fs" to several virtual names
This also adds "fs" to all of the fileserver virtualnames which did not
already have them. This both A) normalizes the usage of the non-roots
backends, and B) makes it easier for the FileserverUpdate process to get
the default update interval for each backend from the opts.
2018-01-09 19:11:17 -06:00

297 lines
10 KiB
Python

# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Erik Johnson <erik@saltstack.com>`
'''
# Import Python libs
from __future__ import absolute_import
import errno
import os
import shutil
import tempfile
import textwrap
import tornado.ioloop
import logging
import stat
try:
import pwd
except ImportError:
pass
# Import 3rd-party libs
try:
import git # pylint: disable=unused-import
HAS_GITPYTHON = True
GITFS_AVAILABLE = True
except ImportError:
HAS_GITPYTHON = False
GITFS_AVAILABLE = False
# Import Salt Testing Libs
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import TestCase, skipIf
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, patch
from tests.support.paths import TMP, FILES
# Import salt libs
import salt.fileserver.gitfs as gitfs
import salt.utils.gitfs
import salt.utils.platform
import salt.utils.win_functions
import salt.utils.yaml
log = logging.getLogger(__name__)
TMP_SOCK_DIR = tempfile.mkdtemp(dir=TMP)
TMP_REPO_DIR = os.path.join(TMP, 'gitfs_root')
INTEGRATION_BASE_FILES = os.path.join(FILES, 'file', 'base')
def _rmtree_error(func, path, excinfo):
os.chmod(path, stat.S_IWRITE)
func(path)
@skipIf(not HAS_GITPYTHON, 'GitPython is not installed')
class GitfsConfigTestCase(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
self.tmp_cachedir = tempfile.mkdtemp(dir=TMP)
return {
gitfs: {
'__opts__': {
'cachedir': self.tmp_cachedir,
'sock_dir': TMP_SOCK_DIR,
'gitfs_root': 'salt',
'fileserver_backend': ['gitfs'],
'gitfs_base': 'master',
'fileserver_events': True,
'transport': 'zeromq',
'gitfs_mountpoint': '',
'gitfs_saltenv': [],
'gitfs_env_whitelist': [],
'gitfs_env_blacklist': [],
'gitfs_saltenv_whitelist': [],
'gitfs_saltenv_blacklist': [],
'gitfs_user': '',
'gitfs_password': '',
'gitfs_insecure_auth': False,
'gitfs_privkey': '',
'gitfs_pubkey': '',
'gitfs_passphrase': '',
'gitfs_refspecs': [
'+refs/heads/*:refs/remotes/origin/*',
'+refs/tags/*:refs/tags/*'
],
'gitfs_ssl_verify': True,
'gitfs_disable_saltenv_mapping': False,
'gitfs_ref_types': ['branch', 'tag', 'sha'],
'gitfs_update_interval': 60,
'__role': 'master',
}
}
}
@classmethod
def setUpClass(cls):
# Clear the instance map so that we make sure to create a new instance
# for this test class.
try:
del salt.utils.gitfs.GitFS.instance_map[tornado.ioloop.IOLoop.current()]
except KeyError:
pass
def tearDown(self):
shutil.rmtree(self.tmp_cachedir)
def test_per_saltenv_config(self):
opts_override = textwrap.dedent('''
gitfs_saltenv:
- baz:
# when loaded, the "salt://" prefix will be removed
- mountpoint: salt://baz_mountpoint
- ref: baz_branch
- root: baz_root
gitfs_remotes:
- file://tmp/repo1:
- saltenv:
- foo:
- ref: foo_branch
- root: foo_root
- file://tmp/repo2:
- mountpoint: repo2
- saltenv:
- baz:
- mountpoint: abc
''')
with patch.dict(gitfs.__opts__, salt.utils.yaml.safe_load(opts_override)):
git_fs = salt.utils.gitfs.GitFS(
gitfs.__opts__,
gitfs.__opts__['gitfs_remotes'],
per_remote_overrides=gitfs.PER_REMOTE_OVERRIDES,
per_remote_only=gitfs.PER_REMOTE_ONLY)
# repo1 (branch: foo)
# The mountpoint should take the default (from gitfs_mountpoint), while
# ref and root should take the per-saltenv params.
self.assertEqual(git_fs.remotes[0].mountpoint('foo'), '')
self.assertEqual(git_fs.remotes[0].ref('foo'), 'foo_branch')
self.assertEqual(git_fs.remotes[0].root('foo'), 'foo_root')
# repo1 (branch: bar)
# The 'bar' branch does not have a per-saltenv configuration set, so
# each of the below values should fall back to global values.
self.assertEqual(git_fs.remotes[0].mountpoint('bar'), '')
self.assertEqual(git_fs.remotes[0].ref('bar'), 'bar')
self.assertEqual(git_fs.remotes[0].root('bar'), 'salt')
# repo1 (branch: baz)
# The 'baz' branch does not have a per-saltenv configuration set, but
# it is defined in the gitfs_saltenv parameter, so the values
# from that parameter should be returned.
self.assertEqual(git_fs.remotes[0].mountpoint('baz'), 'baz_mountpoint')
self.assertEqual(git_fs.remotes[0].ref('baz'), 'baz_branch')
self.assertEqual(git_fs.remotes[0].root('baz'), 'baz_root')
# repo2 (branch: foo)
# The mountpoint should take the per-remote mountpoint value of
# 'repo2', while ref and root should fall back to global values.
self.assertEqual(git_fs.remotes[1].mountpoint('foo'), 'repo2')
self.assertEqual(git_fs.remotes[1].ref('foo'), 'foo')
self.assertEqual(git_fs.remotes[1].root('foo'), 'salt')
# repo2 (branch: bar)
# The 'bar' branch does not have a per-saltenv configuration set, so
# the mountpoint should take the per-remote mountpoint value of
# 'repo2', while ref and root should fall back to global values.
self.assertEqual(git_fs.remotes[1].mountpoint('bar'), 'repo2')
self.assertEqual(git_fs.remotes[1].ref('bar'), 'bar')
self.assertEqual(git_fs.remotes[1].root('bar'), 'salt')
# repo2 (branch: baz)
# The 'baz' branch has the mountpoint configured as a per-saltenv
# parameter. The other two should take the values defined in
# gitfs_saltenv.
self.assertEqual(git_fs.remotes[1].mountpoint('baz'), 'abc')
self.assertEqual(git_fs.remotes[1].ref('baz'), 'baz_branch')
self.assertEqual(git_fs.remotes[1].root('baz'), 'baz_root')
LOAD = {'saltenv': 'base'}
@skipIf(not GITFS_AVAILABLE, "GitFS could not be loaded. Skipping GitFS tests!")
@skipIf(NO_MOCK, NO_MOCK_REASON)
class GitFSTest(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
self.tmp_cachedir = tempfile.mkdtemp(dir=TMP)
return {
gitfs: {
'__opts__': {
'cachedir': self.tmp_cachedir,
'sock_dir': TMP_SOCK_DIR,
'gitfs_remotes': ['file://' + TMP_REPO_DIR],
'gitfs_root': '',
'fileserver_backend': ['gitfs'],
'gitfs_base': 'master',
'fileserver_events': True,
'transport': 'zeromq',
'gitfs_mountpoint': '',
'gitfs_saltenv': [],
'gitfs_env_whitelist': [],
'gitfs_env_blacklist': [],
'gitfs_saltenv_whitelist': [],
'gitfs_saltenv_blacklist': [],
'gitfs_user': '',
'gitfs_password': '',
'gitfs_insecure_auth': False,
'gitfs_privkey': '',
'gitfs_pubkey': '',
'gitfs_passphrase': '',
'gitfs_refspecs': [
'+refs/heads/*:refs/remotes/origin/*',
'+refs/tags/*:refs/tags/*'
],
'gitfs_ssl_verify': True,
'gitfs_disable_saltenv_mapping': False,
'gitfs_ref_types': ['branch', 'tag', 'sha'],
'gitfs_update_interval': 60,
'__role': 'master',
}
}
}
@classmethod
def setUpClass(cls):
# Clear the instance map so that we make sure to create a new instance
# for this test class.
try:
del salt.utils.gitfs.GitFS.instance_map[tornado.ioloop.IOLoop.current()]
except KeyError:
pass
# Create the dir if it doesn't already exist
try:
shutil.copytree(INTEGRATION_BASE_FILES, TMP_REPO_DIR + '/')
except OSError:
# We probably caught an error because files already exist. Ignore
pass
try:
repo = git.Repo(TMP_REPO_DIR)
except git.exc.InvalidGitRepositoryError:
repo = git.Repo.init(TMP_REPO_DIR)
if 'USERNAME' not in os.environ:
try:
if salt.utils.platform.is_windows():
os.environ['USERNAME'] = salt.utils.win_functions.get_current_user()
else:
os.environ['USERNAME'] = pwd.getpwuid(os.geteuid()).pw_name
except AttributeError:
log.error('Unable to get effective username, falling back to '
'\'root\'.')
os.environ['USERNAME'] = 'root'
repo.index.add([x for x in os.listdir(TMP_REPO_DIR)
if x != '.git'])
repo.index.commit('Test')
def setUp(self):
'''
We don't want to check in another .git dir into GH because that just
gets messy. Instead, we'll create a temporary repo on the fly for the
tests to examine.
'''
if not gitfs.__virtual__():
self.skipTest("GitFS could not be loaded. Skipping GitFS tests!")
self.tmp_cachedir = tempfile.mkdtemp(dir=TMP)
gitfs.update()
def tearDown(self):
'''
Remove the temporary git repository and gitfs cache directory to ensure
a clean environment for each test.
'''
try:
shutil.rmtree(self.tmp_cachedir, onerror=_rmtree_error)
except OSError as exc:
if exc.errno != errno.EEXIST:
raise
def test_file_list(self):
ret = gitfs.file_list(LOAD)
self.assertIn('testfile', ret)
def test_dir_list(self):
ret = gitfs.dir_list(LOAD)
self.assertIn('grail', ret)
def test_envs(self):
ret = gitfs.envs()
self.assertIn('base', ret)