test_roots.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. # -*- coding: utf-8 -*-
  2. """
  3. :codeauthor: Mike Place <mp@saltstack.com>
  4. """
  5. from __future__ import absolute_import, print_function, unicode_literals
  6. import copy
  7. import os
  8. import pathlib
  9. import shutil
  10. import tempfile
  11. import salt.fileclient
  12. import salt.fileserver.roots as roots
  13. import salt.utils.files
  14. import salt.utils.hashutils
  15. import salt.utils.platform
  16. from tests.support.mixins import (
  17. AdaptedConfigurationTestCaseMixin,
  18. LoaderModuleMockMixin,
  19. )
  20. from tests.support.mock import patch
  21. from tests.support.runtests import RUNTIME_VARS
  22. from tests.support.unit import TestCase, skipIf
  23. UNICODE_FILENAME = "питон.txt"
  24. UNICODE_DIRNAME = UNICODE_ENVNAME = "соль"
  25. class RootsTest(TestCase, AdaptedConfigurationTestCaseMixin, LoaderModuleMockMixin):
  26. def setup_loader_modules(self):
  27. self.opts = self.get_temp_config("master")
  28. empty_dir = os.path.join(RUNTIME_VARS.TMP_STATE_TREE, "empty_dir")
  29. if not os.path.isdir(empty_dir):
  30. os.makedirs(empty_dir)
  31. return {roots: {"__opts__": self.opts}}
  32. @classmethod
  33. def setUpClass(cls):
  34. cls.tmp_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
  35. full_path_to_file = os.path.join(RUNTIME_VARS.BASE_FILES, "testfile")
  36. shutil.copyfile(full_path_to_file, os.path.join(cls.tmp_dir, "testfile"))
  37. @classmethod
  38. def tearDownClass(cls):
  39. salt.utils.files.rm_rf(cls.tmp_dir)
  40. def tearDown(self):
  41. del self.opts
  42. def test_file_list(self):
  43. ret = roots.file_list({"saltenv": "base"})
  44. self.assertIn("testfile", ret)
  45. self.assertIn(UNICODE_FILENAME, ret)
  46. def test_find_file(self):
  47. ret = roots.find_file("testfile")
  48. self.assertEqual("testfile", ret["rel"])
  49. full_path_to_file = os.path.join(RUNTIME_VARS.BASE_FILES, "testfile")
  50. self.assertEqual(full_path_to_file, ret["path"])
  51. def test_serve_file(self):
  52. with patch.dict(roots.__opts__, {"file_buffer_size": 262144}):
  53. load = {
  54. "saltenv": "base",
  55. "path": os.path.join(self.tmp_dir, "testfile"),
  56. "loc": 0,
  57. }
  58. fnd = {"path": os.path.join(self.tmp_dir, "testfile"), "rel": "testfile"}
  59. ret = roots.serve_file(load, fnd)
  60. with salt.utils.files.fopen(
  61. os.path.join(RUNTIME_VARS.BASE_FILES, "testfile"), "rb"
  62. ) as fp_:
  63. data = fp_.read()
  64. self.assertDictEqual(ret, {"data": data, "dest": "testfile"})
  65. def test_envs(self):
  66. opts = {"file_roots": copy.copy(self.opts["file_roots"])}
  67. opts["file_roots"][UNICODE_ENVNAME] = opts["file_roots"]["base"]
  68. with patch.dict(roots.__opts__, opts):
  69. ret = roots.envs()
  70. self.assertIn("base", ret)
  71. self.assertIn(UNICODE_ENVNAME, ret)
  72. def test_file_hash(self):
  73. load = {
  74. "saltenv": "base",
  75. "path": os.path.join(self.tmp_dir, "testfile"),
  76. }
  77. fnd = {"path": os.path.join(self.tmp_dir, "testfile"), "rel": "testfile"}
  78. ret = roots.file_hash(load, fnd)
  79. # Hashes are different in Windows. May be how git translates line
  80. # endings
  81. with salt.utils.files.fopen(
  82. os.path.join(RUNTIME_VARS.BASE_FILES, "testfile"), "rb"
  83. ) as fp_:
  84. hsum = salt.utils.hashutils.sha256_digest(fp_.read())
  85. self.assertDictEqual(ret, {"hsum": hsum, "hash_type": "sha256"})
  86. def test_file_list_emptydirs(self):
  87. ret = roots.file_list_emptydirs({"saltenv": "base"})
  88. self.assertIn("empty_dir", ret)
  89. def test_file_list_with_slash(self):
  90. opts = {"file_roots": copy.copy(self.opts["file_roots"])}
  91. opts["file_roots"]["foo/bar"] = opts["file_roots"]["base"]
  92. load = {
  93. "saltenv": "foo/bar",
  94. }
  95. with patch.dict(roots.__opts__, opts):
  96. ret = roots.file_list(load)
  97. self.assertIn("testfile", ret)
  98. self.assertIn(UNICODE_FILENAME, ret)
  99. def test_dir_list(self):
  100. ret = roots.dir_list({"saltenv": "base"})
  101. self.assertIn("empty_dir", ret)
  102. self.assertIn(UNICODE_DIRNAME, ret)
  103. def test_symlink_list(self):
  104. source_sym = pathlib.Path(RUNTIME_VARS.TMP_BASEENV_STATE_TREE) / "source_sym"
  105. source_sym.write_text("")
  106. dest_sym = pathlib.Path(RUNTIME_VARS.TMP_BASEENV_STATE_TREE) / "dest_sym"
  107. dest_sym.symlink_to(str(source_sym))
  108. self.addCleanup(dest_sym.unlink)
  109. self.addCleanup(source_sym.unlink)
  110. ret = roots.symlink_list({"saltenv": "base"})
  111. self.assertDictEqual(ret, {"dest_sym": str(source_sym)})
  112. def test_dynamic_file_roots(self):
  113. dyn_root_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
  114. top_sls = os.path.join(dyn_root_dir, "top.sls")
  115. with salt.utils.files.fopen(top_sls, "w") as fp_:
  116. fp_.write("{{saltenv}}:\n '*':\n - dynamo\n")
  117. dynamo_sls = os.path.join(dyn_root_dir, "dynamo.sls")
  118. with salt.utils.files.fopen(dynamo_sls, "w") as fp_:
  119. fp_.write("foo:\n test.nop\n")
  120. opts = {"file_roots": copy.copy(self.opts["file_roots"])}
  121. opts["file_roots"]["__env__"] = [dyn_root_dir]
  122. with patch.dict(roots.__opts__, opts):
  123. ret1 = roots.find_file("dynamo.sls", "dyn")
  124. ret2 = roots.file_list({"saltenv": "dyn"})
  125. self.assertEqual("dynamo.sls", ret1["rel"])
  126. self.assertIn("top.sls", ret2)
  127. self.assertIn("dynamo.sls", ret2)
  128. @skipIf(
  129. salt.utils.platform.is_windows(),
  130. "Windows does not support this master function",
  131. )
  132. def test_update_no_change(self):
  133. # process all changes that have happen
  134. # changes will always take place the first time during testing
  135. ret = roots.update()
  136. self.assertTrue(ret["changed"])
  137. # check if no changes took place
  138. ret = roots.update()
  139. self.assertFalse(ret["changed"])
  140. self.assertEqual(ret["files"]["changed"], [])
  141. self.assertEqual(ret["files"]["removed"], [])
  142. self.assertEqual(ret["files"]["added"], [])