1
0

test_nxos.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. # -*- coding: utf-8 -*-
  2. """
  3. :codeauthor: Mike Wiebe <@mikewiebe>
  4. """
  5. # Copyright (c) 2019 Cisco and/or its affiliates.
  6. #
  7. # Licensed under the Apache License, Version 2.0 (the "License");
  8. # you may not use this file except in compliance with the License.
  9. # You may obtain a copy of the License at
  10. #
  11. # http://www.apache.org/licenses/LICENSE-2.0
  12. #
  13. # Unless required by applicable law or agreed to in writing, software
  14. # distributed under the License is distributed on an "AS IS" BASIS,
  15. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. # See the License for the specific language governing permissions and
  17. # limitations under the License.
  18. # Import Python Libs
  19. from __future__ import absolute_import, print_function, unicode_literals
  20. import salt.proxy.nxos as nxos_proxy
  21. import salt.utils.nxos as nxos_utils
  22. from salt.exceptions import CommandExecutionError
  23. # Import Salt Testing Libs
  24. from tests.support.mixins import LoaderModuleMockMixin
  25. from tests.support.mock import MagicMock, create_autospec, patch
  26. from tests.support.unit import TestCase
  27. from tests.unit.modules.nxos.nxos_grains import n9k_grains
  28. from tests.unit.modules.nxos.nxos_show_cmd_output import n9k_show_ver_list
  29. class NxosNxapiProxyTestCase(TestCase, LoaderModuleMockMixin):
  30. def setup_loader_modules(self):
  31. return {nxos_proxy: {"CONNECTION": "nxapi"}}
  32. def test_check_virtual(self):
  33. """ UT: nxos module:check_virtual method - return value """
  34. result = nxos_proxy.__virtual__()
  35. self.assertIn("nxos", result)
  36. def test_init(self):
  37. """ UT: nxos module:init method - nxapi proxy """
  38. with patch.object(nxos_proxy, "__opts__", {"proxy": {"connection": "nxapi"}}):
  39. with patch("salt.proxy.nxos._init_nxapi", autospec=True) as init_nxapi:
  40. result = nxos_proxy.init()
  41. self.assertEqual(result, init_nxapi.return_value)
  42. def test_init_opts_none(self):
  43. """ UT: nxos module:init method - __opts__ connection is None """
  44. with patch.object(nxos_proxy, "__opts__", {"proxy": {"connection": None}}):
  45. with patch("salt.proxy.nxos._init_nxapi", autospec=True) as init_nxapi:
  46. result = nxos_proxy.init()
  47. self.assertEqual(result, init_nxapi.return_value)
  48. def test_init_bad_connection_type(self):
  49. """ UT: nxos module:init method - bad CONNECTION type """
  50. with patch.object(nxos_proxy, "__opts__", {"proxy": {"connection": "unknown"}}):
  51. self.assertFalse(nxos_proxy.init())
  52. def test_initialized(self):
  53. """ UT: nxos module:initialized method - nxapi proxy """
  54. with patch(
  55. "salt.proxy.nxos._initialized_nxapi", autospec=True
  56. ) as initialized_nxapi:
  57. result = nxos_proxy.initialized()
  58. self.assertEqual(result, initialized_nxapi.return_value)
  59. def test_ping(self):
  60. """ UT: nxos module:ping method - nxapi proxy """
  61. with patch("salt.proxy.nxos._ping_nxapi", autospec=True) as ping_nxapi:
  62. result = nxos_proxy.ping()
  63. self.assertEqual(result, ping_nxapi.return_value)
  64. def test_grains(self):
  65. """ UT: nxos module:grains method - nxapi grains """
  66. with patch(
  67. "salt.proxy.nxos.sendline", autospec=True, return_value=n9k_show_ver_list
  68. ):
  69. result = nxos_proxy.grains()
  70. self.assertEqual(result, n9k_grains)
  71. def test_grains_cache_set(self):
  72. """ UT: nxos module:grains method - nxapi grains cache set """
  73. with patch(
  74. "salt.proxy.nxos.DEVICE_DETAILS", {"grains_cache": n9k_grains["nxos"]}
  75. ):
  76. with patch(
  77. "salt.proxy.nxos.sendline",
  78. autospec=True,
  79. return_value=n9k_show_ver_list,
  80. ):
  81. result = nxos_proxy.grains()
  82. self.assertEqual(result, n9k_grains)
  83. def test_grains_refresh(self):
  84. """ UT: nxos module:grains_refresh method - nxapi grains """
  85. device_details = {"grains_cache": None}
  86. with patch("salt.proxy.nxos.DEVICE_DETAILS", device_details):
  87. with patch("salt.proxy.nxos.grains", autospec=True) as grains:
  88. result = nxos_proxy.grains_refresh()
  89. self.assertEqual(nxos_proxy.DEVICE_DETAILS["grains_cache"], {})
  90. self.assertEqual(result, grains.return_value)
  91. def test_sendline(self):
  92. """ UT: nxos module:sendline method - nxapi """
  93. command = "show version"
  94. with patch("salt.proxy.nxos._nxapi_request", autospec=True) as nxapi_request:
  95. result = nxos_proxy.sendline(command)
  96. self.assertEqual(result, nxapi_request.return_value)
  97. def test_proxy_config(self):
  98. """ UT: nxos module:proxy_config method - nxapi success path"""
  99. commands = ["feature bgp", "router bgp 65535"]
  100. with patch("salt.proxy.nxos.DEVICE_DETAILS", {"save_config": False}):
  101. with patch(
  102. "salt.proxy.nxos._nxapi_request", autospec=True
  103. ) as nxapi_request:
  104. result = nxos_proxy.proxy_config(commands)
  105. self.assertEqual(result, [commands, nxapi_request.return_value])
  106. def test_proxy_config_save_config(self):
  107. """ UT: nxos module:proxy_config method - nxapi success path"""
  108. commands = ["feature bgp", "router bgp 65535"]
  109. with patch("salt.proxy.nxos.DEVICE_DETAILS", {"save_config": None}):
  110. with patch(
  111. "salt.proxy.nxos._nxapi_request", autospec=True
  112. ) as nxapi_request:
  113. result = nxos_proxy.proxy_config(commands, save_config=True)
  114. self.assertEqual(result, [commands, nxapi_request.return_value])
  115. def test__init_nxapi(self):
  116. """ UT: nxos module:_init_nxapi method - successful connectinon """
  117. opts = {"proxy": {"arg1": None}}
  118. nxapi_request = create_autospec(nxos_utils.nxapi_request, return_value="data")
  119. with patch("salt.proxy.nxos.DEVICE_DETAILS", {}) as device_details:
  120. with patch(
  121. "salt.proxy.nxos.__utils__", {"nxos.nxapi_request": nxapi_request}
  122. ):
  123. result = nxos_proxy._init_nxapi(opts)
  124. self.assertTrue(device_details["initialized"])
  125. self.assertTrue(device_details["up"])
  126. self.assertTrue(device_details["save_config"])
  127. self.assertTrue(result)
  128. nxapi_request.assert_called_with("show clock", **opts["proxy"])
  129. def test_bad__init_nxapi(self):
  130. class NXAPIException(Exception):
  131. pass
  132. nxapi_request = create_autospec(
  133. nxos_utils.nxapi_request, side_effect=NXAPIException
  134. )
  135. with patch("salt.proxy.nxos.__utils__", {"nxos.nxapi_request": nxapi_request}):
  136. with patch("salt.proxy.nxos.log", autospec=True) as log:
  137. with self.assertRaises(NXAPIException):
  138. nxos_proxy._init_nxapi({"proxy": {"host": "HOST"}})
  139. log.error.assert_called()
  140. def test__initialized_nxapi(self):
  141. """ UT: nxos module:_initialized_nxapi method """
  142. result = nxos_proxy._initialized_nxapi()
  143. self.assertFalse(result)
  144. with patch("salt.proxy.nxos.DEVICE_DETAILS", {"initialized": True}):
  145. result = nxos_proxy._initialized_nxapi()
  146. self.assertTrue(result)
  147. def test__ping_nxapi(self):
  148. """ UT: nxos module:_ping_nxapi method """
  149. result = nxos_proxy._ping_nxapi()
  150. self.assertFalse(result)
  151. with patch("salt.proxy.nxos.DEVICE_DETAILS", {"up": True}):
  152. result = nxos_proxy._ping_nxapi()
  153. self.assertTrue(result)
  154. def test__shutdown_nxapi(self):
  155. """ UT: nxos module:_shutdown_nxapi method """
  156. opts = {"id": "value"}
  157. with patch("salt.proxy.nxos.log", autospec=True):
  158. nxos_proxy._shutdown_nxapi()
  159. # nothing to test
  160. def test__nxapi_request_ssh_return(self):
  161. """ UT: nxos module:_nxapi_request method - CONNECTION == 'ssh' """
  162. commands = "show version"
  163. with patch("salt.proxy.nxos.CONNECTION", "ssh"):
  164. result = nxos_proxy._nxapi_request(commands)
  165. self.assertEqual("_nxapi_request is not available for ssh proxy", result)
  166. def test__nxapi_request_connect(self):
  167. """ UT: nxos module:_nxapi_request method """
  168. commands = "show version"
  169. nxapi_request = create_autospec(nxos_utils.nxapi_request, return_value="data")
  170. with patch("salt.proxy.nxos.DEVICE_DETAILS", {"conn_args": {"arg1": None}}):
  171. with patch(
  172. "salt.proxy.nxos.__utils__", {"nxos.nxapi_request": nxapi_request}
  173. ):
  174. result = nxos_proxy._nxapi_request(commands)
  175. self.assertEqual("data", result)
  176. nxapi_request.assert_called_with(commands, method="cli_conf", arg1=None)
  177. class NxosSSHProxyTestCase(TestCase, LoaderModuleMockMixin):
  178. def setup_loader_modules(self):
  179. return {
  180. nxos_proxy: {
  181. "__opts__": {
  182. "proxy": {
  183. "host": "dt-n9k5-1.cisco.com",
  184. "username": "admin",
  185. "password": "password",
  186. }
  187. },
  188. "CONNECTION": "ssh",
  189. }
  190. }
  191. def test_init(self):
  192. """ UT: nxos module:init method - ssh proxy """
  193. with patch("salt.proxy.nxos._init_ssh", autospec=True) as init_ssh:
  194. result = nxos_proxy.init()
  195. self.assertEqual(result, init_ssh.return_value)
  196. def test_init_opts_none(self):
  197. """ UT: nxos module:init method - __opts__ connection is None """
  198. with patch("salt.proxy.nxos.__opts__", {"proxy": {"connection": None}}):
  199. with patch("salt.proxy.nxos._init_ssh", autospec=True) as init_ssh:
  200. result = nxos_proxy.init()
  201. self.assertEqual(result, init_ssh.return_value)
  202. def test_initialized(self):
  203. """ UT: nxos module:initialized method - ssh proxy """
  204. with patch(
  205. "salt.proxy.nxos._initialized_ssh", autospec=True
  206. ) as initialized_ssh:
  207. result = nxos_proxy.initialized()
  208. self.assertEqual(result, initialized_ssh.return_value)
  209. def test_ping(self):
  210. """ UT: nxos module:ping method - ssh proxy """
  211. with patch("salt.proxy.nxos._ping_ssh", autospec=True) as ping_ssh:
  212. result = nxos_proxy.ping()
  213. self.assertEqual(result, ping_ssh.return_value)
  214. def test_grains(self):
  215. """ UT: nxos module:grains method - ssh grains """
  216. with patch(
  217. "salt.proxy.nxos.sendline", autospec=True, return_value=n9k_show_ver_list[0]
  218. ):
  219. result = nxos_proxy.grains()
  220. self.assertEqual(result, n9k_grains)
  221. def test_sendline(self):
  222. """ UT: nxos module:sendline method - nxapi """
  223. command = "show version"
  224. with patch("salt.proxy.nxos._sendline_ssh", autospec=True) as sendline_ssh:
  225. result = nxos_proxy.sendline(command)
  226. self.assertEqual(result, sendline_ssh.return_value)
  227. def test_proxy_config(self):
  228. """ UT: nxos module:proxy_config method - ssh success path """
  229. commands = ["feature bgp", "router bgp 65535"]
  230. with patch("salt.proxy.nxos.DEVICE_DETAILS", {"save_config": False}):
  231. with patch("salt.proxy.nxos._sendline_ssh", autospec=True) as sendline_ssh:
  232. result = nxos_proxy.proxy_config(commands)
  233. self.assertEqual(result, [commands, sendline_ssh.return_value])
  234. def test_proxy_config_save_config(self):
  235. """ UT: nxos module:proxy_config method - ssh success path """
  236. commands = ["feature bgp", "router bgp 65535"]
  237. with patch("salt.proxy.nxos.DEVICE_DETAILS", {"save_config": None}):
  238. with patch("salt.proxy.nxos._sendline_ssh", autospec=True) as sendline_ssh:
  239. result = nxos_proxy.proxy_config(commands, save_config=True)
  240. self.assertEqual(result, [commands, sendline_ssh.return_value])
  241. def test_proxy_config_error(self):
  242. """ UT: nxos module:proxy_config method - CommandExecutionError """
  243. with patch(
  244. "salt.proxy.nxos._sendline_ssh",
  245. autospec=True,
  246. side_effect=CommandExecutionError,
  247. ):
  248. with self.assertRaises(CommandExecutionError):
  249. nxos_proxy.proxy_config("show version", save_config=True)
  250. def test__init_ssh_device_details(self):
  251. with patch("salt.proxy.nxos.SSHConnection", autospec=True) as SSHConnection:
  252. SSHConnection().sendline.return_value = ["", ""]
  253. with patch("salt.proxy.nxos.DEVICE_DETAILS", {}) as device_details:
  254. nxos_proxy._init_ssh(None)
  255. self.assertIn(nxos_proxy._worker_name(), device_details)
  256. self.assertTrue(device_details["initialized"])
  257. self.assertTrue(device_details["save_config"])
  258. with patch.dict(nxos_proxy.__opts__["proxy"], {"save_config": False}):
  259. with patch("salt.proxy.nxos.DEVICE_DETAILS", {}) as device_details:
  260. nxos_proxy._init_ssh(None)
  261. self.assertIn(nxos_proxy._worker_name(), device_details)
  262. self.assertTrue(device_details["initialized"])
  263. self.assertFalse(device_details["save_config"])
  264. def test__init_ssh_opts(self):
  265. """ UT: nxos module:_init_ssh method - successful connectinon """
  266. with patch("salt.proxy.nxos.DEVICE_DETAILS", {}):
  267. with patch("salt.proxy.nxos.SSHConnection", autospec=True) as SSHConnection:
  268. SSHConnection().sendline.return_value = ["", ""]
  269. nxos_proxy._init_ssh(None)
  270. self.assertEqual(
  271. nxos_proxy.__opts__["proxy"]["host"],
  272. SSHConnection.call_args[1]["host"],
  273. )
  274. opts = MagicMock()
  275. nxos_proxy._init_ssh(opts)
  276. self.assertEqual(
  277. opts["proxy"]["host"], SSHConnection.call_args[1]["host"]
  278. )
  279. def test__init_ssh_prompt(self):
  280. """ UT: nxos module:_init_ssh method - prompt regex """
  281. with patch("salt.proxy.nxos.DEVICE_DETAILS", {}):
  282. with patch("salt.proxy.nxos.SSHConnection", autospec=True) as SSHConnection:
  283. SSHConnection().sendline.return_value = ["", ""]
  284. with patch.dict(
  285. nxos_proxy.__opts__["proxy"], {"prompt_regex": "n9k.*device"}
  286. ):
  287. nxos_proxy._init_ssh(None)
  288. self.assertEqual(
  289. "n9k.*device", SSHConnection.call_args[1]["prompt"]
  290. )
  291. with patch.dict(
  292. nxos_proxy.__opts__["proxy"], {"prompt_name": "n9k-device"}
  293. ):
  294. nxos_proxy._init_ssh(None)
  295. self.assertEqual(
  296. "n9k-device.*#", SSHConnection.call_args[1]["prompt"]
  297. )
  298. nxos_proxy._init_ssh(None)
  299. self.assertEqual(".+#$", SSHConnection.call_args[1]["prompt"])
  300. def test__initialized_ssh(self):
  301. """ UT: nxos module:_initialized_ssh method """
  302. with patch("salt.proxy.nxos.DEVICE_DETAILS", {"initialized": True}):
  303. result = nxos_proxy._initialized_ssh()
  304. self.assertTrue(result)
  305. with patch("salt.proxy.nxos.DEVICE_DETAILS", {}):
  306. result = nxos_proxy._initialized_ssh()
  307. self.assertFalse(result)
  308. def test__parse_output_for_errors(self):
  309. """ UT: nxos module:_parse_output_for_errors method """
  310. data = "% Incomplete command at '^' marker."
  311. command = "show"
  312. with self.assertRaises(CommandExecutionError):
  313. nxos_proxy._parse_output_for_errors(
  314. data, command, error_pattern="Incomplete"
  315. )
  316. data = "% Incomplete command at '^' marker."
  317. command = "show"
  318. with self.assertRaises(CommandExecutionError):
  319. nxos_proxy._parse_output_for_errors(
  320. data, command, error_pattern=["Incomplete", "marker"]
  321. )
  322. data = "% Invalid command at '^' marker."
  323. command = "show bep"
  324. with self.assertRaises(CommandExecutionError):
  325. nxos_proxy._parse_output_for_errors(data, command)
  326. data = "% Incomplete command at '^' marker."
  327. command = "show"
  328. nxos_proxy._parse_output_for_errors(data, command)
  329. data = "% Incomplete command at '^' marker."
  330. command = "show"
  331. nxos_proxy._parse_output_for_errors(data, command, error_pattern="foo")
  332. def test__init_ssh_raise_exception(self):
  333. """ UT: nxos module:_init_ssh method - raise exception """
  334. class SSHException(Exception):
  335. pass
  336. with patch("salt.proxy.nxos.SSHConnection", autospec=True) as SSHConnection:
  337. with patch("salt.proxy.nxos.log", autospec=True) as log:
  338. with self.assertRaises(SSHException):
  339. SSHConnection.side_effect = SSHException
  340. nxos_proxy._init_ssh(None)
  341. log.error.assert_called()