1
0

test_win_groupadd.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  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 Libs
  8. import salt.modules.win_groupadd as win_groupadd
  9. import salt.utils.win_functions
  10. # Import Salt Testing Libs
  11. from tests.support.helpers import TstSuiteLoggingHandler
  12. from tests.support.mixins import LoaderModuleMockMixin
  13. from tests.support.mock import MagicMock, Mock, patch
  14. from tests.support.unit import TestCase, skipIf
  15. # Import Other Libs
  16. # pylint: disable=unused-import
  17. try:
  18. import win32com
  19. import pythoncom
  20. import pywintypes
  21. PYWINTYPES_ERROR = pywintypes.com_error(
  22. -1234, "Exception occurred.", (0, None, "C", None, 0, -2147352567), None
  23. )
  24. HAS_WIN_LIBS = True
  25. except ImportError:
  26. HAS_WIN_LIBS = False
  27. # pylint: enable=unused-import
  28. class MockMember(object):
  29. def __init__(self, name):
  30. self.ADSPath = name
  31. class MockGroupObj(object):
  32. def __init__(self, ads_name, ads_users):
  33. self._members = [MockMember(x) for x in ads_users]
  34. self.Name = ads_name
  35. def members(self):
  36. return self._members
  37. def Add(self, name):
  38. """
  39. This should be a no-op unless we want to test raising an error, in
  40. which case this should be overridden in a subclass.
  41. """
  42. def Remove(self, name):
  43. """
  44. This should be a no-op unless we want to test raising an error, in
  45. which case this should be overridden in a subclass.
  46. """
  47. sam_mock = MagicMock(side_effect=lambda x: "HOST\\" + x)
  48. @skipIf(
  49. not HAS_WIN_LIBS,
  50. "win_groupadd unit tests can only be run if win32com, pythoncom, and pywintypes are installed",
  51. )
  52. class WinGroupTestCase(TestCase, LoaderModuleMockMixin):
  53. """
  54. Test cases for salt.modules.win_groupadd
  55. """
  56. def setup_loader_modules(self):
  57. return {win_groupadd: {"__opts__": {"test": False}}}
  58. def test_add(self):
  59. """
  60. Test adding a new group
  61. """
  62. info = MagicMock(return_value=False)
  63. with patch.object(win_groupadd, "info", info), patch.object(
  64. win_groupadd, "_get_computer_object", Mock()
  65. ):
  66. self.assertTrue(win_groupadd.add("foo"))
  67. def test_add_group_exists(self):
  68. """
  69. Test adding a new group if the group already exists
  70. """
  71. info = MagicMock(
  72. return_value={
  73. "name": "foo",
  74. "passwd": None,
  75. "gid": None,
  76. "members": ["HOST\\spongebob"],
  77. }
  78. )
  79. with patch.object(win_groupadd, "info", info), patch.object(
  80. win_groupadd, "_get_computer_object", Mock()
  81. ):
  82. self.assertFalse(win_groupadd.add("foo"))
  83. def test_add_error(self):
  84. """
  85. Test adding a group and encountering an error
  86. """
  87. class CompObj(object):
  88. def Create(self, type, name):
  89. raise PYWINTYPES_ERROR
  90. obj_comp_mock = MagicMock(return_value=CompObj())
  91. info = MagicMock(return_value=False)
  92. with patch.object(win_groupadd, "info", info), patch.object(
  93. win_groupadd, "_get_computer_object", obj_comp_mock
  94. ):
  95. self.assertFalse(win_groupadd.add("foo"))
  96. def test_delete(self):
  97. """
  98. Test removing a group
  99. """
  100. info = MagicMock(
  101. return_value={
  102. "name": "foo",
  103. "passwd": None,
  104. "gid": None,
  105. "members": ["HOST\\spongebob"],
  106. }
  107. )
  108. with patch.object(win_groupadd, "info", info), patch.object(
  109. win_groupadd, "_get_computer_object", Mock()
  110. ):
  111. self.assertTrue(win_groupadd.delete("foo"))
  112. def test_delete_no_group(self):
  113. """
  114. Test removing a group that doesn't exists
  115. """
  116. info = MagicMock(return_value=False)
  117. with patch.object(win_groupadd, "info", info), patch.object(
  118. win_groupadd, "_get_computer_object", Mock()
  119. ):
  120. self.assertFalse(win_groupadd.delete("foo"))
  121. def test_delete_error(self):
  122. """
  123. Test removing a group and encountering an error
  124. """
  125. class CompObj(object):
  126. def Delete(self, type, name):
  127. raise PYWINTYPES_ERROR
  128. obj_comp_mock = MagicMock(return_value=CompObj())
  129. info = MagicMock(
  130. return_value={
  131. "name": "foo",
  132. "passwd": None,
  133. "gid": None,
  134. "members": ["HOST\\spongebob"],
  135. }
  136. )
  137. with patch.object(win_groupadd, "info", info), patch.object(
  138. win_groupadd, "_get_computer_object", obj_comp_mock
  139. ):
  140. self.assertFalse(win_groupadd.delete("foo"))
  141. def test_info(self):
  142. """
  143. Test if it return information about a group.
  144. """
  145. obj_group_mock = MagicMock(
  146. return_value=MockGroupObj("salt", ["WinNT://HOST/steve"])
  147. )
  148. with patch.object(win_groupadd, "_get_group_object", obj_group_mock):
  149. self.assertDictEqual(
  150. win_groupadd.info("salt"),
  151. {
  152. "gid": None,
  153. "members": ["HOST\\steve"],
  154. "passwd": None,
  155. "name": "salt",
  156. },
  157. )
  158. def test_getent(self):
  159. obj_group_mock = MagicMock(
  160. return_value=[
  161. MockGroupObj("salt", ["WinNT://HOST/steve"]),
  162. MockGroupObj("salty", ["WinNT://HOST/spongebob"]),
  163. ]
  164. )
  165. mock_g_to_g = MagicMock(side_effect=[1, 2])
  166. with patch.object(win_groupadd, "_get_all_groups", obj_group_mock), patch.dict(
  167. win_groupadd.__salt__, {"file.group_to_gid": mock_g_to_g}
  168. ):
  169. self.assertListEqual(
  170. win_groupadd.getent(),
  171. [
  172. {
  173. "gid": 1,
  174. "members": ["HOST\\steve"],
  175. "name": "salt",
  176. "passwd": "x",
  177. },
  178. {
  179. "gid": 2,
  180. "members": ["HOST\\spongebob"],
  181. "name": "salty",
  182. "passwd": "x",
  183. },
  184. ],
  185. )
  186. def test_getent_context(self):
  187. """
  188. Test group.getent is using the values in __context__
  189. """
  190. with patch.dict(win_groupadd.__context__, {"group.getent": True}):
  191. self.assertTrue(win_groupadd.getent())
  192. def test_adduser(self):
  193. """
  194. Test adding a user to a group
  195. """
  196. obj_group_mock = MagicMock(
  197. return_value=MockGroupObj("foo", ["WinNT://HOST/steve"])
  198. )
  199. with patch.object(
  200. win_groupadd, "_get_group_object", obj_group_mock
  201. ), patch.object(salt.utils.win_functions, "get_sam_name", sam_mock):
  202. self.assertTrue(win_groupadd.adduser("foo", "spongebob"))
  203. def test_adduser_already_exists(self):
  204. """
  205. Test adding a user that already exists
  206. """
  207. obj_group_mock = MagicMock(
  208. return_value=MockGroupObj("foo", ["WinNT://HOST/steve"])
  209. )
  210. with patch.object(
  211. win_groupadd, "_get_group_object", obj_group_mock
  212. ), patch.object(salt.utils.win_functions, "get_sam_name", sam_mock):
  213. self.assertFalse(win_groupadd.adduser("foo", "steve"))
  214. def test_adduser_error(self):
  215. """
  216. Test adding a user and encountering an error
  217. """
  218. msg = "An unknown directory object was requested"
  219. error = pywintypes.com_error(
  220. -1234, "Exception occurred.", (0, None, msg, None, 0, -2147352567), None
  221. )
  222. # Create mock group object with mocked Add function which raises the
  223. # exception we need in order to test the error case.
  224. class GroupObj(MockGroupObj):
  225. def Add(self, name):
  226. raise error
  227. obj_group_mock = MagicMock(return_value=GroupObj("foo", ["WinNT://HOST/steve"]))
  228. with patch.object(
  229. win_groupadd, "_get_group_object", obj_group_mock
  230. ), patch.object(salt.utils.win_functions, "get_sam_name", sam_mock):
  231. with TstSuiteLoggingHandler() as handler:
  232. self.assertFalse(win_groupadd.adduser("foo", "username"))
  233. expected = "ERROR:Failed to add HOST\\username to group foo. An unknown directory object was requested"
  234. self.assertIn(expected, handler.messages)
  235. def test_adduser_group_does_not_exist(self):
  236. obj_group_mock = MagicMock(side_effect=PYWINTYPES_ERROR)
  237. with patch.object(win_groupadd, "_get_group_object", obj_group_mock):
  238. self.assertFalse(win_groupadd.adduser("foo", "spongebob"))
  239. def test_deluser(self):
  240. """
  241. Test removing a user from a group
  242. """
  243. # Test removing a user
  244. obj_group_mock = MagicMock(
  245. return_value=MockGroupObj("foo", ["WinNT://HOST/spongebob"])
  246. )
  247. with patch.object(
  248. win_groupadd, "_get_group_object", obj_group_mock
  249. ), patch.object(salt.utils.win_functions, "get_sam_name", sam_mock):
  250. self.assertTrue(win_groupadd.deluser("foo", "spongebob"))
  251. def test_deluser_no_user(self):
  252. """
  253. Test removing a user from a group and that user is not a member of the
  254. group
  255. """
  256. obj_group_mock = MagicMock(
  257. return_value=MockGroupObj("foo", ["WinNT://HOST/steve"])
  258. )
  259. with patch.object(
  260. win_groupadd, "_get_group_object", obj_group_mock
  261. ), patch.object(salt.utils.win_functions, "get_sam_name", sam_mock):
  262. self.assertFalse(win_groupadd.deluser("foo", "spongebob"))
  263. def test_deluser_error(self):
  264. """
  265. Test removing a user and encountering an error
  266. """
  267. class GroupObj(MockGroupObj):
  268. def Remove(self, name):
  269. raise PYWINTYPES_ERROR
  270. obj_group_mock = MagicMock(
  271. return_value=GroupObj("foo", ["WinNT://HOST/spongebob"])
  272. )
  273. with patch.object(
  274. win_groupadd, "_get_group_object", obj_group_mock
  275. ), patch.object(salt.utils.win_functions, "get_sam_name", sam_mock):
  276. self.assertFalse(win_groupadd.deluser("foo", "spongebob"))
  277. def test_deluser_group_does_not_exist(self):
  278. obj_group_mock = MagicMock(side_effect=PYWINTYPES_ERROR)
  279. with patch.object(win_groupadd, "_get_group_object", obj_group_mock):
  280. self.assertFalse(win_groupadd.deluser("foo", "spongebob"))
  281. def test_members(self):
  282. """
  283. Test adding a list of members to a group, all existing users removed
  284. """
  285. obj_group_mock = MagicMock(
  286. return_value=MockGroupObj("foo", ["WinNT://HOST/steve"])
  287. )
  288. with patch.object(
  289. win_groupadd, "_get_group_object", obj_group_mock
  290. ), patch.object(salt.utils.win_functions, "get_sam_name", sam_mock):
  291. self.assertTrue(win_groupadd.members("foo", "spongebob,patrick,squidward"))
  292. obj_group_mock.assert_called_once_with("foo")
  293. def test_members_correct_membership(self):
  294. """
  295. Test adding a list of users where the list of users already exists
  296. """
  297. members_list = [
  298. "WinNT://HOST/spongebob",
  299. "WinNT://HOST/squidward",
  300. "WinNT://HOST/patrick",
  301. ]
  302. obj_group_mock = MagicMock(return_value=MockGroupObj("foo", members_list))
  303. with patch.object(
  304. win_groupadd, "_get_group_object", obj_group_mock
  305. ), patch.object(salt.utils.win_functions, "get_sam_name", sam_mock):
  306. self.assertTrue(win_groupadd.members("foo", "spongebob,patrick,squidward"))
  307. obj_group_mock.assert_called_once_with("foo")
  308. def test_members_group_does_not_exist(self):
  309. """
  310. Test adding a list of users where the group does not exist
  311. """
  312. obj_group_mock = MagicMock(side_effect=PYWINTYPES_ERROR)
  313. with patch.object(
  314. salt.utils.win_functions, "get_sam_name", sam_mock
  315. ), patch.object(win_groupadd, "_get_group_object", obj_group_mock):
  316. self.assertFalse(win_groupadd.members("foo", "spongebob"))
  317. def test_members_fail_to_remove(self):
  318. """
  319. Test adding a list of members and fail to remove members not in the list
  320. """
  321. class GroupObj(MockGroupObj):
  322. def Remove(self, name):
  323. raise PYWINTYPES_ERROR
  324. obj_group_mock = MagicMock(
  325. return_value=GroupObj("foo", ["WinNT://HOST/spongebob"])
  326. )
  327. with patch.object(
  328. win_groupadd, "_get_group_object", obj_group_mock
  329. ), patch.object(salt.utils.win_functions, "get_sam_name", sam_mock):
  330. self.assertFalse(win_groupadd.members("foo", "patrick"))
  331. obj_group_mock.assert_called_once_with("foo")
  332. def test_members_fail_to_add(self):
  333. """
  334. Test adding a list of members and failing to add
  335. """
  336. class GroupObj(MockGroupObj):
  337. def Add(self, name):
  338. raise PYWINTYPES_ERROR
  339. obj_group_mock = MagicMock(
  340. return_value=GroupObj("foo", ["WinNT://HOST/spongebob"])
  341. )
  342. with patch.object(
  343. win_groupadd, "_get_group_object", obj_group_mock
  344. ), patch.object(salt.utils.win_functions, "get_sam_name", sam_mock):
  345. self.assertFalse(win_groupadd.members("foo", "patrick"))
  346. obj_group_mock.assert_called_once_with("foo")
  347. def test_list_groups(self):
  348. """
  349. Test that list groups returns a list of groups by name
  350. """
  351. obj_group_mock = MagicMock(
  352. return_value=[
  353. MockGroupObj("salt", ["WinNT://HOST/steve"]),
  354. MockGroupObj("salty", ["WinNT://HOST/Administrator"]),
  355. ]
  356. )
  357. with patch.object(win_groupadd, "_get_all_groups", obj_group_mock):
  358. self.assertListEqual(win_groupadd.list_groups(), ["salt", "salty"])
  359. def test_list_groups_context(self):
  360. """
  361. Test group.list_groups is using the values in __context__
  362. """
  363. with patch.dict(win_groupadd.__context__, {"group.list_groups": True}):
  364. self.assertTrue(win_groupadd.list_groups())