test_roots.py 6.7 KB

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