test_roots.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. # -*- coding: utf-8 -*-
  2. '''
  3. :codeauthor: Mike Place <mp@saltstack.com>
  4. '''
  5. # Import Python libs
  6. from __future__ import absolute_import, print_function, unicode_literals
  7. import copy
  8. import os
  9. import tempfile
  10. # Import Salt Testing libs
  11. from tests.integration import AdaptedConfigurationTestCaseMixin
  12. from tests.support.mixins import LoaderModuleMockMixin
  13. from tests.support.paths import BASE_FILES, TMP, TMP_STATE_TREE
  14. from tests.support.unit import TestCase, skipIf
  15. from tests.support.mock import patch, NO_MOCK, NO_MOCK_REASON
  16. # Import Salt libs
  17. import salt.fileserver.roots as roots
  18. import salt.fileclient
  19. import salt.utils.files
  20. import salt.utils.hashutils
  21. import salt.utils.platform
  22. try:
  23. import win32file
  24. except ImportError:
  25. pass
  26. UNICODE_FILENAME = 'питон.txt'
  27. UNICODE_DIRNAME = UNICODE_ENVNAME = 'соль'
  28. @skipIf(NO_MOCK, NO_MOCK_REASON)
  29. class RootsTest(TestCase, AdaptedConfigurationTestCaseMixin, LoaderModuleMockMixin):
  30. def setup_loader_modules(self):
  31. self.tmp_cachedir = tempfile.mkdtemp(dir=TMP)
  32. self.opts = self.get_temp_config('master')
  33. self.opts['cachedir'] = self.tmp_cachedir
  34. empty_dir = os.path.join(TMP_STATE_TREE, 'empty_dir')
  35. if not os.path.isdir(empty_dir):
  36. os.makedirs(empty_dir)
  37. return {roots: {'__opts__': self.opts}}
  38. @classmethod
  39. def setUpClass(cls):
  40. '''
  41. Create special file_roots for symlink test on Windows
  42. '''
  43. if salt.utils.platform.is_windows():
  44. root_dir = tempfile.mkdtemp(dir=TMP)
  45. source_sym = os.path.join(root_dir, 'source_sym')
  46. with salt.utils.files.fopen(source_sym, 'w') as fp_:
  47. fp_.write('hello world!\n')
  48. cwd = os.getcwd()
  49. try:
  50. os.chdir(root_dir)
  51. win32file.CreateSymbolicLink('dest_sym', 'source_sym', 0)
  52. finally:
  53. os.chdir(cwd)
  54. cls.test_symlink_list_file_roots = {'base': [root_dir]}
  55. else:
  56. cls.test_symlink_list_file_roots = None
  57. cls.tmp_dir = tempfile.mkdtemp(dir=TMP)
  58. full_path_to_file = os.path.join(BASE_FILES, 'testfile')
  59. with salt.utils.files.fopen(full_path_to_file, 'rb') as s_fp:
  60. with salt.utils.files.fopen(os.path.join(cls.tmp_dir, 'testfile'), 'wb') as d_fp:
  61. for line in s_fp:
  62. d_fp.write(line)
  63. @classmethod
  64. def tearDownClass(cls):
  65. '''
  66. Remove special file_roots for symlink test
  67. '''
  68. if salt.utils.platform.is_windows():
  69. try:
  70. salt.utils.files.rm_rf(cls.test_symlink_list_file_roots['base'][0])
  71. except OSError:
  72. pass
  73. salt.utils.files.rm_rf(cls.tmp_dir)
  74. def tearDown(self):
  75. del self.opts
  76. def test_file_list(self):
  77. ret = roots.file_list({'saltenv': 'base'})
  78. self.assertIn('testfile', ret)
  79. self.assertIn(UNICODE_FILENAME, ret)
  80. def test_find_file(self):
  81. ret = roots.find_file('testfile')
  82. self.assertEqual('testfile', ret['rel'])
  83. full_path_to_file = os.path.join(BASE_FILES, 'testfile')
  84. self.assertEqual(full_path_to_file, ret['path'])
  85. def test_serve_file(self):
  86. with patch.dict(roots.__opts__, {'file_buffer_size': 262144}):
  87. load = {'saltenv': 'base',
  88. 'path': os.path.join(self.tmp_dir, 'testfile'),
  89. 'loc': 0
  90. }
  91. fnd = {'path': os.path.join(self.tmp_dir, 'testfile'),
  92. 'rel': 'testfile'}
  93. ret = roots.serve_file(load, fnd)
  94. with salt.utils.files.fopen(
  95. os.path.join(BASE_FILES, 'testfile'), 'rb') as fp_:
  96. data = fp_.read()
  97. self.assertDictEqual(
  98. ret,
  99. {'data': data,
  100. 'dest': 'testfile'})
  101. def test_envs(self):
  102. opts = {'file_roots': copy.copy(self.opts['file_roots'])}
  103. opts['file_roots'][UNICODE_ENVNAME] = opts['file_roots']['base']
  104. with patch.dict(roots.__opts__, opts):
  105. ret = roots.envs()
  106. self.assertIn('base', ret)
  107. self.assertIn(UNICODE_ENVNAME, ret)
  108. def test_file_hash(self):
  109. load = {
  110. 'saltenv': 'base',
  111. 'path': os.path.join(self.tmp_dir, 'testfile'),
  112. }
  113. fnd = {
  114. 'path': os.path.join(self.tmp_dir, 'testfile'),
  115. 'rel': 'testfile'
  116. }
  117. ret = roots.file_hash(load, fnd)
  118. # Hashes are different in Windows. May be how git translates line
  119. # endings
  120. with salt.utils.files.fopen(
  121. os.path.join(BASE_FILES, 'testfile'), 'rb') as fp_:
  122. hsum = salt.utils.hashutils.sha256_digest(fp_.read())
  123. self.assertDictEqual(
  124. ret,
  125. {
  126. 'hsum': hsum,
  127. 'hash_type': 'sha256'
  128. }
  129. )
  130. def test_file_list_emptydirs(self):
  131. ret = roots.file_list_emptydirs({'saltenv': 'base'})
  132. self.assertIn('empty_dir', ret)
  133. def test_file_list_with_slash(self):
  134. opts = {'file_roots': copy.copy(self.opts['file_roots'])}
  135. opts['file_roots']['foo/bar'] = opts['file_roots']['base']
  136. load = {
  137. 'saltenv': 'foo/bar',
  138. }
  139. with patch.dict(roots.__opts__, opts):
  140. ret = roots.file_list(load)
  141. self.assertIn('testfile', ret)
  142. self.assertIn(UNICODE_FILENAME, ret)
  143. def test_dir_list(self):
  144. ret = roots.dir_list({'saltenv': 'base'})
  145. self.assertIn('empty_dir', ret)
  146. self.assertIn(UNICODE_DIRNAME, ret)
  147. def test_symlink_list(self):
  148. orig_file_roots = self.opts['file_roots']
  149. try:
  150. if self.test_symlink_list_file_roots:
  151. self.opts['file_roots'] = self.test_symlink_list_file_roots
  152. ret = roots.symlink_list({'saltenv': 'base'})
  153. self.assertDictEqual(ret, {'dest_sym': 'source_sym'})
  154. finally:
  155. if self.test_symlink_list_file_roots:
  156. self.opts['file_roots'] = orig_file_roots
  157. def test_dynamic_file_roots(self):
  158. dyn_root_dir = tempfile.mkdtemp(dir=TMP)
  159. top_sls = os.path.join(dyn_root_dir, 'top.sls')
  160. with salt.utils.files.fopen(top_sls, 'w') as fp_:
  161. fp_.write("{{saltenv}}:\n '*':\n - dynamo\n")
  162. dynamo_sls = os.path.join(dyn_root_dir, 'dynamo.sls')
  163. with salt.utils.files.fopen(dynamo_sls, 'w') as fp_:
  164. fp_.write("foo:\n test.nop\n")
  165. opts = {'file_roots': copy.copy(self.opts['file_roots'])}
  166. opts['file_roots']['__env__'] = [dyn_root_dir]
  167. with patch.dict(roots.__opts__, opts):
  168. ret1 = roots.find_file('dynamo.sls', 'dyn')
  169. ret2 = roots.file_list({'saltenv': 'dyn'})
  170. self.assertEqual('dynamo.sls', ret1['rel'])
  171. self.assertIn('top.sls', ret2)
  172. self.assertIn('dynamo.sls', ret2)