test_gitfs.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. # -*- coding: utf-8 -*-
  2. """
  3. :codeauthor: Erik Johnson <erik@saltstack.com>
  4. """
  5. # Import Python libs
  6. from __future__ import absolute_import, print_function, unicode_literals
  7. import errno
  8. import logging
  9. import os
  10. import shutil
  11. import stat
  12. import tempfile
  13. import textwrap
  14. import salt.ext.six
  15. import salt.ext.tornado.ioloop
  16. # Import salt libs
  17. import salt.fileserver.gitfs as gitfs
  18. import salt.utils.files
  19. import salt.utils.gitfs
  20. import salt.utils.platform
  21. import salt.utils.win_functions
  22. import salt.utils.yaml
  23. from salt.utils.gitfs import (
  24. GITPYTHON_MINVER,
  25. GITPYTHON_VERSION,
  26. LIBGIT2_MINVER,
  27. LIBGIT2_VERSION,
  28. PYGIT2_MINVER,
  29. PYGIT2_VERSION,
  30. )
  31. from tests.support.helpers import patched_environ
  32. from tests.support.mixins import LoaderModuleMockMixin
  33. from tests.support.mock import patch
  34. # Import Salt Testing Libs
  35. from tests.support.runtests import RUNTIME_VARS
  36. from tests.support.unit import TestCase, skipIf
  37. try:
  38. import pwd # pylint: disable=unused-import
  39. except ImportError:
  40. pass
  41. try:
  42. import git
  43. # We still need to use GitPython here for temp repo setup, so we do need to
  44. # actually import it. But we don't need import pygit2 in this module, we
  45. # can just use the LooseVersion instances imported along with
  46. # salt.utils.gitfs to check if we have a compatible version.
  47. HAS_GITPYTHON = GITPYTHON_VERSION >= GITPYTHON_MINVER
  48. except (ImportError, AttributeError):
  49. HAS_GITPYTHON = False
  50. try:
  51. HAS_PYGIT2 = PYGIT2_VERSION >= PYGIT2_MINVER and LIBGIT2_VERSION >= LIBGIT2_MINVER
  52. except AttributeError:
  53. HAS_PYGIT2 = False
  54. log = logging.getLogger(__name__)
  55. UNICODE_FILENAME = "питон.txt"
  56. UNICODE_DIRNAME = UNICODE_ENVNAME = "соль"
  57. TAG_NAME = "mytag"
  58. def _rmtree_error(func, path, excinfo):
  59. os.chmod(path, stat.S_IWRITE)
  60. func(path)
  61. def _clear_instance_map():
  62. try:
  63. del salt.utils.gitfs.GitFS.instance_map[
  64. salt.ext.tornado.ioloop.IOLoop.current()
  65. ]
  66. except KeyError:
  67. pass
  68. @skipIf(not HAS_GITPYTHON, "GitPython >= {0} required".format(GITPYTHON_MINVER))
  69. class GitfsConfigTestCase(TestCase, LoaderModuleMockMixin):
  70. def setup_loader_modules(self):
  71. opts = {
  72. "sock_dir": self.tmp_sock_dir,
  73. "gitfs_remotes": ["file://" + self.tmp_repo_dir],
  74. "gitfs_root": "",
  75. "fileserver_backend": ["gitfs"],
  76. "gitfs_base": "master",
  77. "gitfs_fallback": "",
  78. "fileserver_events": True,
  79. "transport": "zeromq",
  80. "gitfs_mountpoint": "",
  81. "gitfs_saltenv": [],
  82. "gitfs_saltenv_whitelist": [],
  83. "gitfs_saltenv_blacklist": [],
  84. "gitfs_user": "",
  85. "gitfs_password": "",
  86. "gitfs_insecure_auth": False,
  87. "gitfs_privkey": "",
  88. "gitfs_pubkey": "",
  89. "gitfs_passphrase": "",
  90. "gitfs_refspecs": [
  91. "+refs/heads/*:refs/remotes/origin/*",
  92. "+refs/tags/*:refs/tags/*",
  93. ],
  94. "gitfs_ssl_verify": True,
  95. "gitfs_disable_saltenv_mapping": False,
  96. "gitfs_ref_types": ["branch", "tag", "sha"],
  97. "gitfs_update_interval": 60,
  98. "__role": "master",
  99. }
  100. opts["cachedir"] = self.tmp_cachedir
  101. opts["sock_dir"] = self.tmp_sock_dir
  102. return {gitfs: {"__opts__": opts}}
  103. @classmethod
  104. def setUpClass(cls):
  105. # Clear the instance map so that we make sure to create a new instance
  106. # for this test class.
  107. _clear_instance_map()
  108. cls.tmp_repo_dir = os.path.join(RUNTIME_VARS.TMP, "gitfs_root")
  109. if salt.utils.platform.is_windows():
  110. cls.tmp_repo_dir = cls.tmp_repo_dir.replace("\\", "/")
  111. cls.tmp_cachedir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
  112. cls.tmp_sock_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
  113. @classmethod
  114. def tearDownClass(cls):
  115. """
  116. Remove the temporary git repository and gitfs cache directory to ensure
  117. a clean environment for the other test class(es).
  118. """
  119. for path in (cls.tmp_cachedir, cls.tmp_sock_dir):
  120. try:
  121. shutil.rmtree(path, onerror=_rmtree_error)
  122. except OSError as exc:
  123. if exc.errno == errno.EACCES:
  124. log.error("Access error removeing file %s", path)
  125. continue
  126. if exc.errno != errno.EEXIST:
  127. raise
  128. def test_per_saltenv_config(self):
  129. opts_override = textwrap.dedent(
  130. """
  131. gitfs_root: salt
  132. gitfs_saltenv:
  133. - baz:
  134. # when loaded, the "salt://" prefix will be removed
  135. - mountpoint: salt://baz_mountpoint
  136. - ref: baz_branch
  137. - root: baz_root
  138. gitfs_remotes:
  139. - file://{0}tmp/repo1:
  140. - saltenv:
  141. - foo:
  142. - ref: foo_branch
  143. - root: foo_root
  144. - file://{0}tmp/repo2:
  145. - mountpoint: repo2
  146. - saltenv:
  147. - baz:
  148. - mountpoint: abc
  149. """.format(
  150. "/" if salt.utils.platform.is_windows() else ""
  151. )
  152. )
  153. with patch.dict(gitfs.__opts__, salt.utils.yaml.safe_load(opts_override)):
  154. git_fs = salt.utils.gitfs.GitFS(
  155. gitfs.__opts__,
  156. gitfs.__opts__["gitfs_remotes"],
  157. per_remote_overrides=gitfs.PER_REMOTE_OVERRIDES,
  158. per_remote_only=gitfs.PER_REMOTE_ONLY,
  159. )
  160. # repo1 (branch: foo)
  161. # The mountpoint should take the default (from gitfs_mountpoint), while
  162. # ref and root should take the per-saltenv params.
  163. self.assertEqual(git_fs.remotes[0].mountpoint("foo"), "")
  164. self.assertEqual(git_fs.remotes[0].ref("foo"), "foo_branch")
  165. self.assertEqual(git_fs.remotes[0].root("foo"), "foo_root")
  166. # repo1 (branch: bar)
  167. # The 'bar' branch does not have a per-saltenv configuration set, so
  168. # each of the below values should fall back to global values.
  169. self.assertEqual(git_fs.remotes[0].mountpoint("bar"), "")
  170. self.assertEqual(git_fs.remotes[0].ref("bar"), "bar")
  171. self.assertEqual(git_fs.remotes[0].root("bar"), "salt")
  172. # repo1 (branch: baz)
  173. # The 'baz' branch does not have a per-saltenv configuration set, but
  174. # it is defined in the gitfs_saltenv parameter, so the values
  175. # from that parameter should be returned.
  176. self.assertEqual(git_fs.remotes[0].mountpoint("baz"), "baz_mountpoint")
  177. self.assertEqual(git_fs.remotes[0].ref("baz"), "baz_branch")
  178. self.assertEqual(git_fs.remotes[0].root("baz"), "baz_root")
  179. # repo2 (branch: foo)
  180. # The mountpoint should take the per-remote mountpoint value of
  181. # 'repo2', while ref and root should fall back to global values.
  182. self.assertEqual(git_fs.remotes[1].mountpoint("foo"), "repo2")
  183. self.assertEqual(git_fs.remotes[1].ref("foo"), "foo")
  184. self.assertEqual(git_fs.remotes[1].root("foo"), "salt")
  185. # repo2 (branch: bar)
  186. # The 'bar' branch does not have a per-saltenv configuration set, so
  187. # the mountpoint should take the per-remote mountpoint value of
  188. # 'repo2', while ref and root should fall back to global values.
  189. self.assertEqual(git_fs.remotes[1].mountpoint("bar"), "repo2")
  190. self.assertEqual(git_fs.remotes[1].ref("bar"), "bar")
  191. self.assertEqual(git_fs.remotes[1].root("bar"), "salt")
  192. # repo2 (branch: baz)
  193. # The 'baz' branch has the mountpoint configured as a per-saltenv
  194. # parameter. The other two should take the values defined in
  195. # gitfs_saltenv.
  196. self.assertEqual(git_fs.remotes[1].mountpoint("baz"), "abc")
  197. self.assertEqual(git_fs.remotes[1].ref("baz"), "baz_branch")
  198. self.assertEqual(git_fs.remotes[1].root("baz"), "baz_root")
  199. LOAD = {"saltenv": "base"}
  200. class GitFSTestFuncs(object):
  201. """
  202. These are where the tests go, so that they can be run using both GitPython
  203. and pygit2.
  204. NOTE: The gitfs.update() has to happen AFTER the setUp is called. This is
  205. because running it inside the setUp will spawn a new singleton, which means
  206. that tests which need to mock the __opts__ will be too late; the setUp will
  207. have created a new singleton that will bypass our mocking. To ensure that
  208. our tests are reliable and correct, we want to make sure that each test
  209. uses a new gitfs object, allowing different manipulations of the opts to be
  210. tested.
  211. Therefore, keep the following in mind:
  212. 1. Each test needs to call gitfs.update() *after* any patching, and
  213. *before* calling the function being tested.
  214. 2. Do *NOT* move the gitfs.update() into the setUp.
  215. """
  216. def test_file_list(self):
  217. gitfs.update()
  218. ret = gitfs.file_list(LOAD)
  219. self.assertIn("testfile", ret)
  220. self.assertIn(UNICODE_FILENAME, ret)
  221. # This function does not use os.sep, the Salt fileserver uses the
  222. # forward slash, hence it being explicitly used to join here.
  223. self.assertIn("/".join((UNICODE_DIRNAME, "foo.txt")), ret)
  224. def test_dir_list(self):
  225. gitfs.update()
  226. ret = gitfs.dir_list(LOAD)
  227. self.assertIn("grail", ret)
  228. self.assertIn(UNICODE_DIRNAME, ret)
  229. def test_find_and_serve_file(self):
  230. with patch.dict(gitfs.__opts__, {"file_buffer_size": 262144}):
  231. gitfs.update()
  232. # find_file
  233. ret = gitfs.find_file("testfile")
  234. self.assertEqual("testfile", ret["rel"])
  235. full_path_to_file = salt.utils.path.join(
  236. gitfs.__opts__["cachedir"], "gitfs", "refs", "base", "testfile"
  237. )
  238. self.assertEqual(full_path_to_file, ret["path"])
  239. # serve_file
  240. load = {"saltenv": "base", "path": full_path_to_file, "loc": 0}
  241. fnd = {"path": full_path_to_file, "rel": "testfile"}
  242. ret = gitfs.serve_file(load, fnd)
  243. with salt.utils.files.fopen(
  244. os.path.join(RUNTIME_VARS.BASE_FILES, "testfile"), "r"
  245. ) as fp_: # NB: Why not 'rb'?
  246. data = fp_.read()
  247. self.assertDictEqual(ret, {"data": data, "dest": "testfile"})
  248. def test_file_list_fallback(self):
  249. with patch.dict(gitfs.__opts__, {"gitfs_fallback": "master"}):
  250. gitfs.update()
  251. ret = gitfs.file_list({"saltenv": "notexisting"})
  252. self.assertIn("testfile", ret)
  253. self.assertIn(UNICODE_FILENAME, ret)
  254. # This function does not use os.sep, the Salt fileserver uses the
  255. # forward slash, hence it being explicitly used to join here.
  256. self.assertIn("/".join((UNICODE_DIRNAME, "foo.txt")), ret)
  257. def test_dir_list_fallback(self):
  258. with patch.dict(gitfs.__opts__, {"gitfs_fallback": "master"}):
  259. gitfs.update()
  260. ret = gitfs.dir_list({"saltenv": "notexisting"})
  261. self.assertIn("grail", ret)
  262. self.assertIn(UNICODE_DIRNAME, ret)
  263. def test_find_and_serve_file_fallback(self):
  264. with patch.dict(
  265. gitfs.__opts__, {"file_buffer_size": 262144, "gitfs_fallback": "master"}
  266. ):
  267. gitfs.update()
  268. # find_file
  269. ret = gitfs.find_file("testfile", tgt_env="notexisting")
  270. self.assertEqual("testfile", ret["rel"])
  271. full_path_to_file = salt.utils.path.join(
  272. gitfs.__opts__["cachedir"], "gitfs", "refs", "notexisting", "testfile"
  273. )
  274. self.assertEqual(full_path_to_file, ret["path"])
  275. # serve_file
  276. load = {"saltenv": "notexisting", "path": full_path_to_file, "loc": 0}
  277. fnd = {"path": full_path_to_file, "rel": "testfile"}
  278. ret = gitfs.serve_file(load, fnd)
  279. with salt.utils.files.fopen(
  280. os.path.join(RUNTIME_VARS.BASE_FILES, "testfile"), "r"
  281. ) as fp_: # NB: Why not 'rb'?
  282. data = fp_.read()
  283. self.assertDictEqual(ret, {"data": data, "dest": "testfile"})
  284. def test_envs(self):
  285. gitfs.update()
  286. ret = gitfs.envs(ignore_cache=True)
  287. self.assertIn("base", ret)
  288. self.assertIn(UNICODE_ENVNAME, ret)
  289. self.assertIn(TAG_NAME, ret)
  290. def test_ref_types_global(self):
  291. """
  292. Test the global gitfs_ref_types config option
  293. """
  294. with patch.dict(gitfs.__opts__, {"gitfs_ref_types": ["branch"]}):
  295. gitfs.update()
  296. ret = gitfs.envs(ignore_cache=True)
  297. # Since we are restricting to branches only, the tag should not
  298. # appear in the envs list.
  299. self.assertIn("base", ret)
  300. self.assertIn(UNICODE_ENVNAME, ret)
  301. self.assertNotIn(TAG_NAME, ret)
  302. def test_ref_types_per_remote(self):
  303. """
  304. Test the per_remote ref_types config option, using a different
  305. ref_types setting than the global test.
  306. """
  307. remotes = [{"file://" + self.tmp_repo_dir: [{"ref_types": ["tag"]}]}]
  308. with patch.dict(gitfs.__opts__, {"gitfs_remotes": remotes}):
  309. gitfs.update()
  310. ret = gitfs.envs(ignore_cache=True)
  311. # Since we are restricting to tags only, the tag should appear in
  312. # the envs list, but the branches should not.
  313. self.assertNotIn("base", ret)
  314. self.assertNotIn(UNICODE_ENVNAME, ret)
  315. self.assertIn(TAG_NAME, ret)
  316. def test_disable_saltenv_mapping_global_with_mapping_defined_globally(self):
  317. """
  318. Test the global gitfs_disable_saltenv_mapping config option, combined
  319. with the per-saltenv mapping being defined in the global gitfs_saltenv
  320. option.
  321. """
  322. opts = salt.utils.yaml.safe_load(
  323. textwrap.dedent(
  324. """\
  325. gitfs_disable_saltenv_mapping: True
  326. gitfs_saltenv:
  327. - foo:
  328. - ref: somebranch
  329. """
  330. )
  331. )
  332. with patch.dict(gitfs.__opts__, opts):
  333. gitfs.update()
  334. ret = gitfs.envs(ignore_cache=True)
  335. # Since we are restricting to tags only, the tag should appear in
  336. # the envs list, but the branches should not.
  337. self.assertEqual(ret, ["base", "foo"])
  338. def test_saltenv_blacklist(self):
  339. """
  340. test saltenv_blacklist
  341. """
  342. opts = salt.utils.yaml.safe_load(
  343. textwrap.dedent(
  344. """\
  345. gitfs_saltenv_blacklist: base
  346. """
  347. )
  348. )
  349. with patch.dict(gitfs.__opts__, opts):
  350. gitfs.update()
  351. ret = gitfs.envs(ignore_cache=True)
  352. assert "base" not in ret
  353. assert UNICODE_ENVNAME in ret
  354. assert "mytag" in ret
  355. def test_saltenv_whitelist(self):
  356. """
  357. test saltenv_whitelist
  358. """
  359. opts = salt.utils.yaml.safe_load(
  360. textwrap.dedent(
  361. """\
  362. gitfs_saltenv_whitelist: base
  363. """
  364. )
  365. )
  366. with patch.dict(gitfs.__opts__, opts):
  367. gitfs.update()
  368. ret = gitfs.envs(ignore_cache=True)
  369. assert "base" in ret
  370. assert UNICODE_ENVNAME not in ret
  371. assert "mytag" not in ret
  372. def test_env_deprecated_opts(self):
  373. """
  374. ensure deprecated options gitfs_env_whitelist
  375. and gitfs_env_blacklist do not cause gitfs to
  376. not load.
  377. """
  378. opts = salt.utils.yaml.safe_load(
  379. textwrap.dedent(
  380. """\
  381. gitfs_env_whitelist: base
  382. gitfs_env_blacklist: ''
  383. """
  384. )
  385. )
  386. with patch.dict(gitfs.__opts__, opts):
  387. gitfs.update()
  388. ret = gitfs.envs(ignore_cache=True)
  389. assert "base" in ret
  390. assert UNICODE_ENVNAME in ret
  391. assert "mytag" in ret
  392. def test_disable_saltenv_mapping_global_with_mapping_defined_per_remote(self):
  393. """
  394. Test the global gitfs_disable_saltenv_mapping config option, combined
  395. with the per-saltenv mapping being defined in the remote itself via the
  396. "saltenv" per-remote option.
  397. """
  398. opts = salt.utils.yaml.safe_load(
  399. textwrap.dedent(
  400. """\
  401. gitfs_disable_saltenv_mapping: True
  402. gitfs_remotes:
  403. - {0}:
  404. - saltenv:
  405. - bar:
  406. - ref: somebranch
  407. """.format(
  408. self.tmp_repo_dir
  409. )
  410. )
  411. )
  412. with patch.dict(gitfs.__opts__, opts):
  413. gitfs.update()
  414. ret = gitfs.envs(ignore_cache=True)
  415. # Since we are restricting to tags only, the tag should appear in
  416. # the envs list, but the branches should not.
  417. self.assertEqual(ret, ["bar", "base"])
  418. def test_disable_saltenv_mapping_per_remote_with_mapping_defined_globally(self):
  419. """
  420. Test the per-remote disable_saltenv_mapping config option, combined
  421. with the per-saltenv mapping being defined in the global gitfs_saltenv
  422. option.
  423. """
  424. opts = salt.utils.yaml.safe_load(
  425. textwrap.dedent(
  426. """\
  427. gitfs_remotes:
  428. - {0}:
  429. - disable_saltenv_mapping: True
  430. gitfs_saltenv:
  431. - hello:
  432. - ref: somebranch
  433. """.format(
  434. self.tmp_repo_dir
  435. )
  436. )
  437. )
  438. with patch.dict(gitfs.__opts__, opts):
  439. gitfs.update()
  440. ret = gitfs.envs(ignore_cache=True)
  441. # Since we are restricting to tags only, the tag should appear in
  442. # the envs list, but the branches should not.
  443. self.assertEqual(ret, ["base", "hello"])
  444. def test_disable_saltenv_mapping_per_remote_with_mapping_defined_per_remote(self):
  445. """
  446. Test the per-remote disable_saltenv_mapping config option, combined
  447. with the per-saltenv mapping being defined in the remote itself via the
  448. "saltenv" per-remote option.
  449. """
  450. opts = salt.utils.yaml.safe_load(
  451. textwrap.dedent(
  452. """\
  453. gitfs_remotes:
  454. - {0}:
  455. - disable_saltenv_mapping: True
  456. - saltenv:
  457. - world:
  458. - ref: somebranch
  459. """.format(
  460. self.tmp_repo_dir
  461. )
  462. )
  463. )
  464. with patch.dict(gitfs.__opts__, opts):
  465. gitfs.update()
  466. ret = gitfs.envs(ignore_cache=True)
  467. # Since we are restricting to tags only, the tag should appear in
  468. # the envs list, but the branches should not.
  469. self.assertEqual(ret, ["base", "world"])
  470. class GitFSTestBase(object):
  471. @classmethod
  472. def setUpClass(cls):
  473. cls.tmp_repo_dir = os.path.join(RUNTIME_VARS.TMP, "gitfs_root")
  474. if salt.utils.platform.is_windows():
  475. cls.tmp_repo_dir = cls.tmp_repo_dir.replace("\\", "/")
  476. cls.tmp_cachedir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
  477. cls.tmp_sock_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
  478. try:
  479. shutil.rmtree(cls.tmp_repo_dir)
  480. except OSError as exc:
  481. if exc.errno == errno.EACCES:
  482. log.error("Access error removing file %s", cls.tmp_repo_dir)
  483. elif exc.errno != errno.ENOENT:
  484. raise
  485. shutil.copytree(
  486. salt.ext.six.text_type(RUNTIME_VARS.BASE_FILES),
  487. salt.ext.six.text_type(cls.tmp_repo_dir + "/"),
  488. symlinks=True,
  489. )
  490. repo = git.Repo.init(cls.tmp_repo_dir)
  491. try:
  492. if salt.utils.platform.is_windows():
  493. username = salt.utils.win_functions.get_current_user()
  494. else:
  495. username = pwd.getpwuid(os.geteuid()).pw_name
  496. except AttributeError:
  497. log.error("Unable to get effective username, falling back to 'root'.")
  498. username = str("root")
  499. with patched_environ(USERNAME=username):
  500. repo.index.add([x for x in os.listdir(cls.tmp_repo_dir) if x != ".git"])
  501. repo.index.commit("Test")
  502. # Add another branch with unicode characters in the name
  503. repo.create_head(UNICODE_ENVNAME, "HEAD")
  504. # Add a tag
  505. repo.create_tag(TAG_NAME, "HEAD")
  506. # Older GitPython versions do not have a close method.
  507. if hasattr(repo, "close"):
  508. repo.close()
  509. @classmethod
  510. def tearDownClass(cls):
  511. """
  512. Remove the temporary git repository and gitfs cache directory to ensure
  513. a clean environment for the other test class(es).
  514. """
  515. for path in (cls.tmp_cachedir, cls.tmp_sock_dir, cls.tmp_repo_dir):
  516. try:
  517. salt.utils.files.rm_rf(path)
  518. except OSError as exc:
  519. if exc.errno == errno.EACCES:
  520. log.error("Access error removeing file %s", path)
  521. elif exc.errno != errno.EEXIST:
  522. raise
  523. def setUp(self):
  524. """
  525. We don't want to check in another .git dir into GH because that just
  526. gets messy. Instead, we'll create a temporary repo on the fly for the
  527. tests to examine.
  528. Also ensure we A) don't re-use the singleton, and B) that the cachedirs
  529. are cleared. This keeps these performance enhancements from affecting
  530. the results of subsequent tests.
  531. """
  532. if not gitfs.__virtual__():
  533. self.skipTest("GitFS could not be loaded. Skipping GitFS tests!")
  534. _clear_instance_map()
  535. for subdir in ("gitfs", "file_lists"):
  536. try:
  537. salt.utils.files.rm_rf(os.path.join(self.tmp_cachedir, subdir))
  538. except OSError as exc:
  539. if exc.errno == errno.EACCES:
  540. log.warning(
  541. "Access error removeing file %s",
  542. os.path.join(self.tmp_cachedir, subdir),
  543. )
  544. continue
  545. if exc.errno != errno.ENOENT:
  546. raise
  547. if salt.ext.six.PY3 and salt.utils.platform.is_windows():
  548. self.setUpClass()
  549. self.setup_loader_modules()
  550. @skipIf(not HAS_GITPYTHON, "GitPython >= {0} required".format(GITPYTHON_MINVER))
  551. class GitPythonTest(GitFSTestBase, GitFSTestFuncs, TestCase, LoaderModuleMockMixin):
  552. def setup_loader_modules(self):
  553. opts = {
  554. "sock_dir": self.tmp_sock_dir,
  555. "gitfs_remotes": ["file://" + self.tmp_repo_dir],
  556. "gitfs_root": "",
  557. "fileserver_backend": ["gitfs"],
  558. "gitfs_base": "master",
  559. "gitfs_fallback": "",
  560. "fileserver_events": True,
  561. "transport": "zeromq",
  562. "gitfs_mountpoint": "",
  563. "gitfs_saltenv": [],
  564. "gitfs_saltenv_whitelist": [],
  565. "gitfs_saltenv_blacklist": [],
  566. "gitfs_user": "",
  567. "gitfs_password": "",
  568. "gitfs_insecure_auth": False,
  569. "gitfs_privkey": "",
  570. "gitfs_pubkey": "",
  571. "gitfs_passphrase": "",
  572. "gitfs_refspecs": [
  573. "+refs/heads/*:refs/remotes/origin/*",
  574. "+refs/tags/*:refs/tags/*",
  575. ],
  576. "gitfs_ssl_verify": True,
  577. "gitfs_disable_saltenv_mapping": False,
  578. "gitfs_ref_types": ["branch", "tag", "sha"],
  579. "gitfs_update_interval": 60,
  580. "__role": "master",
  581. }
  582. opts["cachedir"] = self.tmp_cachedir
  583. opts["sock_dir"] = self.tmp_sock_dir
  584. opts["gitfs_provider"] = "gitpython"
  585. return {gitfs: {"__opts__": opts}}
  586. @skipIf(
  587. not HAS_GITPYTHON,
  588. "GitPython >= {0} required for temp repo setup".format(GITPYTHON_MINVER),
  589. )
  590. @skipIf(
  591. not HAS_PYGIT2,
  592. "pygit2 >= {0} and libgit2 >= {1} required".format(PYGIT2_MINVER, LIBGIT2_MINVER),
  593. )
  594. @skipIf(
  595. salt.utils.platform.is_windows(),
  596. "Skip Pygit2 on windows, due to pygit2 access error on windows",
  597. )
  598. class Pygit2Test(GitFSTestBase, GitFSTestFuncs, TestCase, LoaderModuleMockMixin):
  599. def setup_loader_modules(self):
  600. opts = {
  601. "sock_dir": self.tmp_sock_dir,
  602. "gitfs_remotes": ["file://" + self.tmp_repo_dir],
  603. "gitfs_root": "",
  604. "fileserver_backend": ["gitfs"],
  605. "gitfs_base": "master",
  606. "gitfs_fallback": "",
  607. "fileserver_events": True,
  608. "transport": "zeromq",
  609. "gitfs_mountpoint": "",
  610. "gitfs_saltenv": [],
  611. "gitfs_saltenv_whitelist": [],
  612. "gitfs_saltenv_blacklist": [],
  613. "gitfs_user": "",
  614. "gitfs_password": "",
  615. "gitfs_insecure_auth": False,
  616. "gitfs_privkey": "",
  617. "gitfs_pubkey": "",
  618. "gitfs_passphrase": "",
  619. "gitfs_refspecs": [
  620. "+refs/heads/*:refs/remotes/origin/*",
  621. "+refs/tags/*:refs/tags/*",
  622. ],
  623. "gitfs_ssl_verify": True,
  624. "gitfs_disable_saltenv_mapping": False,
  625. "gitfs_ref_types": ["branch", "tag", "sha"],
  626. "gitfs_update_interval": 60,
  627. "__role": "master",
  628. }
  629. opts["cachedir"] = self.tmp_cachedir
  630. opts["sock_dir"] = self.tmp_sock_dir
  631. opts["gitfs_provider"] = "pygit2"
  632. return {gitfs: {"__opts__": opts}}