test_hosts.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. # -*- coding: utf-8 -*-
  2. '''
  3. :codeauthor: Jayesh Kariya <jayeshk@saltstack.com>
  4. '''
  5. # Import Python libs
  6. from __future__ import absolute_import, print_function, unicode_literals
  7. # Import Salt Testing Libs
  8. from tests.support.mixins import LoaderModuleMockMixin
  9. from tests.support.unit import TestCase
  10. from tests.support.mock import (
  11. MagicMock,
  12. mock_open,
  13. patch,
  14. )
  15. # Import Salt Libs
  16. import salt.modules.hosts as hosts
  17. import salt.utils.data
  18. import salt.utils.platform
  19. import salt.utils.stringutils
  20. from salt.ext.six.moves import StringIO
  21. from salt.ext import six
  22. class HostsTestCase(TestCase, LoaderModuleMockMixin):
  23. '''
  24. TestCase for salt.modules.hosts
  25. '''
  26. def setup_loader_modules(self):
  27. return {hosts: {}}
  28. # 'list_hosts' function tests: 1
  29. def test_list_hosts(self):
  30. '''
  31. Tests return the hosts found in the hosts file
  32. '''
  33. with patch('salt.modules.hosts._list_hosts',
  34. MagicMock(return_value={'10.10.10.10': ['Salt1', 'Salt2']})):
  35. self.assertDictEqual({'10.10.10.10': ['Salt1', 'Salt2']},
  36. hosts.list_hosts())
  37. # 'get_ip' function tests: 3
  38. def test_get_ip(self):
  39. '''
  40. Tests return ip associated with the named host
  41. '''
  42. with patch('salt.modules.hosts._list_hosts',
  43. MagicMock(return_value={'10.10.10.10': ['Salt1', 'Salt2']})):
  44. self.assertEqual('10.10.10.10', hosts.get_ip('Salt1'))
  45. self.assertEqual('', hosts.get_ip('Salt3'))
  46. def test_get_ip_none(self):
  47. '''
  48. Tests return ip associated with the named host
  49. '''
  50. with patch('salt.modules.hosts._list_hosts', MagicMock(return_value='')):
  51. self.assertEqual('', hosts.get_ip('Salt1'))
  52. # 'get_alias' function tests: 2
  53. def test_get_alias(self):
  54. '''
  55. Tests return the list of aliases associated with an ip
  56. '''
  57. with patch('salt.modules.hosts._list_hosts',
  58. MagicMock(return_value={'10.10.10.10': ['Salt1', 'Salt2']})):
  59. self.assertListEqual(['Salt1', 'Salt2'], hosts.get_alias('10.10.10.10'))
  60. def test_get_alias_none(self):
  61. '''
  62. Tests return the list of aliases associated with an ip
  63. '''
  64. with patch('salt.modules.hosts._list_hosts',
  65. MagicMock(return_value={'10.10.10.10': ['Salt1', 'Salt2']})):
  66. self.assertListEqual([], hosts.get_alias('10.10.10.11'))
  67. # 'has_pair' function tests: 1
  68. def test_has_pair(self):
  69. '''
  70. Tests return True / False if the alias is set
  71. '''
  72. with patch('salt.modules.hosts._list_hosts',
  73. MagicMock(return_value={'10.10.10.10': ['Salt1', 'Salt2']})):
  74. self.assertTrue(hosts.has_pair('10.10.10.10', 'Salt1'))
  75. self.assertFalse(hosts.has_pair('10.10.10.10', 'Salt3'))
  76. # 'set_host' function tests: 3
  77. def test_set_host(self):
  78. '''
  79. Tests true if the alias is set
  80. '''
  81. hosts_file = '/etc/hosts'
  82. if salt.utils.platform.is_windows():
  83. hosts_file = r'C:\Windows\System32\Drivers\etc\hosts'
  84. with patch('salt.modules.hosts.__get_hosts_filename',
  85. MagicMock(return_value=hosts_file)), \
  86. patch('os.path.isfile', MagicMock(return_value=False)), \
  87. patch.dict(hosts.__salt__,
  88. {'config.option': MagicMock(return_value=None)}):
  89. self.assertFalse(hosts.set_host('10.10.10.10', 'Salt1'))
  90. def test_set_host_true(self):
  91. '''
  92. Tests true if the alias is set
  93. '''
  94. with patch('salt.modules.hosts.__get_hosts_filename',
  95. MagicMock(return_value='/etc/hosts')), \
  96. patch('os.path.isfile', MagicMock(return_value=True)), \
  97. patch('salt.utils.files.fopen', mock_open(b'')):
  98. mock_opt = MagicMock(return_value=None)
  99. with patch.dict(hosts.__salt__, {'config.option': mock_opt}):
  100. self.assertTrue(hosts.set_host('10.10.10.10', 'Salt1'))
  101. def test_set_host_true_remove(self):
  102. '''
  103. Test if an empty hosts value removes existing entries
  104. '''
  105. with patch('salt.modules.hosts.__get_hosts_filename',
  106. MagicMock(return_value='/etc/hosts')), \
  107. patch('os.path.isfile', MagicMock(return_value=True)):
  108. data = ['\n'.join((
  109. '1.1.1.1 foo.foofoo foo',
  110. '2.2.2.2 bar.barbar bar',
  111. '3.3.3.3 asdf.asdfadsf asdf',
  112. '1.1.1.1 foofoo.foofoo foofoo',
  113. ))]
  114. class TmpStringIO(StringIO, object):
  115. def __init__(self, fn, mode='r'):
  116. self.mode = mode
  117. initial_value = data[0]
  118. if 'w' in self.mode:
  119. initial_value = ''
  120. super(TmpStringIO, self).__init__(initial_value)
  121. def __enter__(self):
  122. return self
  123. def __exit__(self, exc_type, exc_value, traceback):
  124. self.close()
  125. def close(self):
  126. # Don't save unless there's something there. In Windows
  127. # the class gets initialized the first time with mode = w
  128. # which sets the initial value to ''. When the class closes
  129. # it clears out data and causes the test to fail.
  130. # I don't know why it get's initialized with a mode of 'w'
  131. # For the purposes of this test data shouldn't be empty
  132. # This is a problem with this class and not with the hosts
  133. # module
  134. if self.getvalue():
  135. data[0] = self.getvalue()
  136. StringIO.close(self)
  137. def read(self, *args):
  138. ret = super(TmpStringIO, self).read(*args)
  139. if six.PY3 and 'b' in self.mode:
  140. return salt.utils.stringutils.to_bytes(ret)
  141. else:
  142. return ret
  143. def write(self, s, *args):
  144. if six.PY3:
  145. if 'b' in self.mode:
  146. if not isinstance(s, bytes):
  147. # Make this act like a binary filehandle
  148. raise TypeError("a bytes-like object is required, not 'str'")
  149. # The StringIO wants a str type, it won't take
  150. # bytes. Convert before writing to it.
  151. return super(TmpStringIO, self).write(
  152. salt.utils.stringutils.to_str(s), *args)
  153. else:
  154. if not isinstance(s, str):
  155. # Make this act like a non-binary filehandle
  156. raise TypeError("write() argument must be str, not bytes")
  157. return super(TmpStringIO, self).write(s, *args)
  158. def readlines(self):
  159. ret = super(TmpStringIO, self).readlines()
  160. if six.PY3 and 'b' in self.mode:
  161. return salt.utils.data.encode(ret)
  162. else:
  163. return ret
  164. def writelines(self, lines):
  165. for line in lines:
  166. self.write(line)
  167. expected = '\n'.join((
  168. '2.2.2.2 bar.barbar bar',
  169. '3.3.3.3 asdf.asdfadsf asdf',
  170. )) + '\n'
  171. with patch('salt.utils.files.fopen', TmpStringIO):
  172. mock_opt = MagicMock(return_value=None)
  173. with patch.dict(hosts.__salt__, {'config.option': mock_opt}):
  174. self.assertTrue(hosts.set_host('1.1.1.1', ' '))
  175. self.assertEqual(data[0], expected)
  176. # 'rm_host' function tests: 2
  177. def test_rm_host(self):
  178. '''
  179. Tests if specified host entry gets removed from the hosts file
  180. '''
  181. with patch('salt.utils.files.fopen', mock_open(b'')), \
  182. patch('salt.modules.hosts.__get_hosts_filename',
  183. MagicMock(return_value='/etc/hosts')), \
  184. patch('salt.modules.hosts.has_pair',
  185. MagicMock(return_value=True)), \
  186. patch('os.path.isfile', MagicMock(return_value=True)):
  187. mock_opt = MagicMock(return_value=None)
  188. with patch.dict(hosts.__salt__, {'config.option': mock_opt}):
  189. self.assertTrue(hosts.rm_host('10.10.10.10', 'Salt1'))
  190. def test_rm_host_false(self):
  191. '''
  192. Tests if specified host entry gets removed from the hosts file
  193. '''
  194. with patch('salt.modules.hosts.has_pair', MagicMock(return_value=False)):
  195. self.assertTrue(hosts.rm_host('10.10.10.10', 'Salt1'))
  196. # 'add_host' function tests: 3
  197. def test_add_host(self):
  198. '''
  199. Tests if specified host entry gets added from the hosts file
  200. '''
  201. hosts_file = '/etc/hosts'
  202. if salt.utils.platform.is_windows():
  203. hosts_file = r'C:\Windows\System32\Drivers\etc\hosts'
  204. with patch('salt.utils.files.fopen', mock_open()), \
  205. patch('salt.modules.hosts.__get_hosts_filename',
  206. MagicMock(return_value=hosts_file)):
  207. mock_opt = MagicMock(return_value=None)
  208. with patch.dict(hosts.__salt__, {'config.option': mock_opt}):
  209. self.assertTrue(hosts.add_host('10.10.10.10', 'Salt1'))
  210. def test_add_host_no_file(self):
  211. '''
  212. Tests if specified host entry gets added from the hosts file
  213. '''
  214. with patch('salt.utils.files.fopen', mock_open()), \
  215. patch('os.path.isfile', MagicMock(return_value=False)):
  216. mock_opt = MagicMock(return_value=None)
  217. with patch.dict(hosts.__salt__, {'config.option': mock_opt}):
  218. self.assertFalse(hosts.add_host('10.10.10.10', 'Salt1'))
  219. def test_add_host_create_entry(self):
  220. '''
  221. Tests if specified host entry gets added from the hosts file
  222. '''
  223. with patch('salt.utils.files.fopen', mock_open()), \
  224. patch('os.path.isfile', MagicMock(return_value=True)):
  225. mock_opt = MagicMock(return_value=None)
  226. with patch.dict(hosts.__salt__, {'config.option': mock_opt}):
  227. self.assertTrue(hosts.add_host('10.10.10.10', 'Salt1'))