test_roots.py 6.9 KB

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