cisco_node_utils 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +13 -0
  5. data/.travis.yml +4 -1
  6. data/CHANGELOG.md +81 -2
  7. data/CONTRIBUTING.md +2 -17
  8. data/Gemfile +5 -0
  9. data/README.md +92 -47
  10. data/Rakefile +23 -1
  11. data/bin/git/hooks/hook_lib +7 -0
  12. data/bin/git/hooks/pre-commit/check_unstaged_changes +18 -0
  13. data/bin/git/hooks/pre-commit/rubocop +7 -2
  14. data/bin/git/hooks/pre-commit/validate-diffs +18 -4
  15. data/bin/git/hooks/pre-commit/validate-yaml +18 -0
  16. data/bin/git/update-hooks +64 -6
  17. data/cisco_node_utils.gemspec +9 -6
  18. data/docs/README-develop-best-practices.md +149 -50
  19. data/docs/README-develop-node-utils-APIs.md +92 -42
  20. data/docs/README-maintainers.md +7 -4
  21. data/docs/README-test-execution.md +57 -0
  22. data/docs/cisco_node_utils.yaml.example +30 -0
  23. data/docs/template-router.rb +4 -0
  24. data/ext/mkrf_conf.rb +63 -0
  25. data/lib/.rubocop.yml +2 -2
  26. data/lib/cisco_node_utils.rb +5 -0
  27. data/lib/cisco_node_utils/aaa_authentication_login.rb +5 -6
  28. data/lib/cisco_node_utils/aaa_authorization_service.rb +1 -1
  29. data/lib/cisco_node_utils/ace.rb +165 -12
  30. data/lib/cisco_node_utils/acl.rb +2 -1
  31. data/lib/cisco_node_utils/bgp.rb +184 -21
  32. data/lib/cisco_node_utils/bgp_af.rb +94 -249
  33. data/lib/cisco_node_utils/bgp_neighbor.rb +94 -14
  34. data/lib/cisco_node_utils/bgp_neighbor_af.rb +75 -8
  35. data/lib/cisco_node_utils/bridge_domain.rb +183 -0
  36. data/lib/cisco_node_utils/bridge_domain_vni.rb +206 -0
  37. data/lib/cisco_node_utils/cisco_cmn_utils.rb +85 -2
  38. data/lib/cisco_node_utils/client.rb +35 -0
  39. data/lib/cisco_node_utils/client/client.rb +234 -0
  40. data/lib/cisco_node_utils/client/grpc.rb +33 -0
  41. data/lib/cisco_node_utils/client/grpc/client.rb +311 -0
  42. data/lib/cisco_node_utils/client/grpc/ems.proto +148 -0
  43. data/lib/cisco_node_utils/client/grpc/ems.rb +111 -0
  44. data/lib/cisco_node_utils/client/grpc/ems_services.rb +49 -0
  45. data/lib/cisco_node_utils/client/nxapi.rb +31 -0
  46. data/lib/cisco_node_utils/client/nxapi/client.rb +305 -0
  47. data/lib/cisco_node_utils/client/utils.rb +164 -0
  48. data/lib/cisco_node_utils/cmd_ref/README_YAML.md +222 -254
  49. data/lib/cisco_node_utils/cmd_ref/aaa_auth_login_service.yaml +11 -8
  50. data/lib/cisco_node_utils/cmd_ref/aaa_authentication_login.yaml +22 -15
  51. data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +11 -8
  52. data/lib/cisco_node_utils/cmd_ref/acl.yaml +21 -16
  53. data/lib/cisco_node_utils/cmd_ref/bgp.yaml +239 -109
  54. data/lib/cisco_node_utils/cmd_ref/bgp_af.yaml +114 -55
  55. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor.yaml +76 -52
  56. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor_af.yaml +106 -62
  57. data/lib/cisco_node_utils/cmd_ref/bridge_domain.yaml +71 -0
  58. data/lib/cisco_node_utils/cmd_ref/bridge_domain_vni.yaml +33 -0
  59. data/lib/cisco_node_utils/cmd_ref/dnsclient.yaml +35 -14
  60. data/lib/cisco_node_utils/cmd_ref/encapsulation.yaml +25 -0
  61. data/lib/cisco_node_utils/cmd_ref/evpn_vni.yaml +23 -17
  62. data/lib/cisco_node_utils/cmd_ref/fabricpath.yaml +94 -83
  63. data/lib/cisco_node_utils/cmd_ref/fabricpath_topology.yaml +22 -17
  64. data/lib/cisco_node_utils/cmd_ref/feature.yaml +76 -26
  65. data/lib/cisco_node_utils/cmd_ref/images.yaml +3 -2
  66. data/lib/cisco_node_utils/cmd_ref/interface.yaml +381 -153
  67. data/lib/cisco_node_utils/cmd_ref/interface_channel_group.yaml +21 -11
  68. data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +21 -21
  69. data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +30 -21
  70. data/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml +18 -13
  71. data/lib/cisco_node_utils/cmd_ref/inventory.yaml +26 -31
  72. data/lib/cisco_node_utils/cmd_ref/itd_device_group.yaml +83 -0
  73. data/lib/cisco_node_utils/cmd_ref/itd_service.yaml +119 -0
  74. data/lib/cisco_node_utils/cmd_ref/memory.yaml +17 -6
  75. data/lib/cisco_node_utils/cmd_ref/ntp_config.yaml +10 -3
  76. data/lib/cisco_node_utils/cmd_ref/ntp_server.yaml +17 -5
  77. data/lib/cisco_node_utils/cmd_ref/ospf.yaml +33 -29
  78. data/lib/cisco_node_utils/cmd_ref/overlay_global.yaml +12 -10
  79. data/lib/cisco_node_utils/cmd_ref/pim.yaml +16 -19
  80. data/lib/cisco_node_utils/cmd_ref/portchannel_global.yaml +40 -25
  81. data/lib/cisco_node_utils/cmd_ref/radius_global.yaml +17 -12
  82. data/lib/cisco_node_utils/cmd_ref/radius_server.yaml +71 -35
  83. data/lib/cisco_node_utils/cmd_ref/radius_server_group.yaml +10 -5
  84. data/lib/cisco_node_utils/cmd_ref/show_system.yaml +6 -2
  85. data/lib/cisco_node_utils/cmd_ref/show_version.yaml +47 -43
  86. data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +13 -11
  87. data/lib/cisco_node_utils/cmd_ref/snmp_group.yaml +4 -2
  88. data/lib/cisco_node_utils/cmd_ref/snmp_notification_receiver.yaml +23 -21
  89. data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +26 -22
  90. data/lib/cisco_node_utils/cmd_ref/snmp_user.yaml +19 -17
  91. data/lib/cisco_node_utils/cmd_ref/snmpnotification.yaml +18 -6
  92. data/lib/cisco_node_utils/cmd_ref/stp_global.yaml +234 -0
  93. data/lib/cisco_node_utils/cmd_ref/syslog_server.yaml +24 -9
  94. data/lib/cisco_node_utils/cmd_ref/syslog_settings.yaml +5 -3
  95. data/lib/cisco_node_utils/cmd_ref/system.yaml +4 -3
  96. data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +22 -20
  97. data/lib/cisco_node_utils/cmd_ref/tacacs_server_group.yaml +27 -15
  98. data/lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml +45 -16
  99. data/lib/cisco_node_utils/cmd_ref/vdc.yaml +21 -11
  100. data/lib/cisco_node_utils/cmd_ref/virtual_service.yaml +3 -2
  101. data/lib/cisco_node_utils/cmd_ref/vlan.yaml +60 -32
  102. data/lib/cisco_node_utils/cmd_ref/vpc.yaml +118 -101
  103. data/lib/cisco_node_utils/cmd_ref/vrf.yaml +54 -58
  104. data/lib/cisco_node_utils/cmd_ref/vrf_af.yaml +118 -0
  105. data/lib/cisco_node_utils/cmd_ref/vtp.yaml +19 -25
  106. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +28 -18
  107. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml +34 -17
  108. data/lib/cisco_node_utils/cmd_ref/yum.yaml +6 -4
  109. data/lib/cisco_node_utils/command_reference.rb +261 -142
  110. data/lib/cisco_node_utils/constants.rb +33 -0
  111. data/lib/cisco_node_utils/encapsulation.rb +112 -0
  112. data/lib/cisco_node_utils/environment.rb +102 -0
  113. data/lib/cisco_node_utils/evpn_vni.rb +5 -3
  114. data/lib/cisco_node_utils/exceptions.rb +111 -0
  115. data/lib/cisco_node_utils/fabricpath_global.rb +52 -35
  116. data/lib/cisco_node_utils/fabricpath_topology.rb +44 -57
  117. data/lib/cisco_node_utils/feature.rb +165 -3
  118. data/lib/cisco_node_utils/interface.rb +1051 -260
  119. data/lib/cisco_node_utils/interface_channel_group.rb +11 -10
  120. data/lib/cisco_node_utils/interface_ospf.rb +1 -2
  121. data/lib/cisco_node_utils/interface_portchannel.rb +4 -12
  122. data/lib/cisco_node_utils/interface_service_vni.rb +7 -7
  123. data/lib/cisco_node_utils/itd_device_group.rb +248 -0
  124. data/lib/cisco_node_utils/itd_device_group_node.rb +144 -0
  125. data/lib/cisco_node_utils/itd_service.rb +523 -0
  126. data/lib/cisco_node_utils/logger.rb +75 -0
  127. data/lib/cisco_node_utils/node.rb +62 -192
  128. data/lib/cisco_node_utils/node_util.rb +56 -10
  129. data/lib/cisco_node_utils/overlay_global.rb +2 -2
  130. data/lib/cisco_node_utils/pim.rb +2 -13
  131. data/lib/cisco_node_utils/pim_group_list.rb +1 -1
  132. data/lib/cisco_node_utils/pim_rp_address.rb +1 -1
  133. data/lib/cisco_node_utils/platform.rb +52 -21
  134. data/lib/cisco_node_utils/portchannel_global.rb +89 -19
  135. data/lib/cisco_node_utils/radius_server.rb +168 -37
  136. data/lib/cisco_node_utils/router_ospf.rb +20 -35
  137. data/lib/cisco_node_utils/router_ospf_vrf.rb +4 -4
  138. data/lib/cisco_node_utils/snmpserver.rb +1 -6
  139. data/lib/cisco_node_utils/snmpuser.rb +6 -4
  140. data/lib/cisco_node_utils/stp_global.rb +676 -0
  141. data/lib/cisco_node_utils/syslog_server.rb +77 -18
  142. data/lib/cisco_node_utils/syslog_settings.rb +1 -1
  143. data/lib/cisco_node_utils/tacacs_server_group.rb +8 -4
  144. data/lib/cisco_node_utils/tacacs_server_host.rb +115 -25
  145. data/lib/cisco_node_utils/vdc.rb +12 -0
  146. data/lib/cisco_node_utils/version.rb +1 -1
  147. data/lib/cisco_node_utils/vlan.rb +147 -29
  148. data/lib/cisco_node_utils/vpc.rb +55 -3
  149. data/lib/cisco_node_utils/vrf.rb +72 -11
  150. data/lib/cisco_node_utils/vrf_af.rb +114 -29
  151. data/lib/cisco_node_utils/vtp.rb +34 -52
  152. data/lib/cisco_node_utils/vxlan_vtep.rb +34 -8
  153. data/lib/cisco_node_utils/vxlan_vtep_vni.rb +36 -4
  154. data/lib/minitest/environment_plugin.rb +31 -0
  155. data/lib/minitest/log_level_plugin.rb +41 -0
  156. data/spec/client_spec.rb +7 -0
  157. data/spec/environment_spec.rb +263 -0
  158. data/spec/grpc_client_spec.rb +23 -0
  159. data/spec/isolate/all_clients_spec.rb +9 -0
  160. data/spec/isolate/grpc_only_spec.rb +16 -0
  161. data/spec/isolate/no_clients_spec.rb +26 -0
  162. data/spec/isolate/nxapi_only_spec.rb +16 -0
  163. data/spec/nxapi_client_spec.rb +42 -0
  164. data/spec/schema.yaml +75 -0
  165. data/spec/shared_examples_for_clients.rb +14 -0
  166. data/spec/spec_helper.rb +91 -0
  167. data/spec/whitespace_spec.rb +10 -0
  168. data/spec/yaml_spec.rb +42 -0
  169. data/tests/.rubocop.yml +2 -2
  170. data/tests/CSCuxdublin-1.0.0-7.0.3.I3.1.lib32_n9000.rpm +0 -0
  171. data/tests/basetest.rb +96 -36
  172. data/tests/ciscotest.rb +220 -12
  173. data/tests/cmd_config.yaml +71 -49
  174. data/tests/cmd_config_invalid.yaml +1 -1
  175. data/tests/test_aaa_authentication_login.rb +1 -0
  176. data/tests/test_aaa_authentication_login_service.rb +9 -0
  177. data/tests/test_aaa_authorization_service.rb +173 -367
  178. data/tests/test_ace.rb +171 -100
  179. data/tests/test_acl.rb +10 -1
  180. data/tests/test_bgp_af.rb +395 -728
  181. data/tests/test_bgp_neighbor.rb +274 -115
  182. data/tests/test_bgp_neighbor_af.rb +178 -77
  183. data/tests/test_bridge_domain.rb +191 -0
  184. data/tests/test_bridge_domain_vni.rb +116 -0
  185. data/tests/test_client_utils.rb +111 -0
  186. data/tests/test_command_config.rb +9 -5
  187. data/tests/test_command_reference.rb +380 -102
  188. data/tests/test_dns_domain.rb +13 -3
  189. data/tests/test_domain_name.rb +13 -3
  190. data/tests/test_encapsulation.rb +77 -0
  191. data/tests/test_evpn_vni.rb +25 -7
  192. data/tests/test_fabricpath_global.rb +167 -163
  193. data/tests/test_fabricpath_topology.rb +12 -33
  194. data/tests/test_feature.rb +215 -0
  195. data/tests/test_grpc.rb +166 -0
  196. data/tests/test_interface.rb +585 -344
  197. data/tests/test_interface_bdi.rb +80 -0
  198. data/tests/test_interface_channel_group.rb +6 -3
  199. data/tests/test_interface_ospf.rb +26 -24
  200. data/tests/test_interface_portchannel.rb +1 -0
  201. data/tests/test_interface_private_vlan.rb +724 -0
  202. data/tests/test_interface_service_vni.rb +37 -66
  203. data/tests/test_interface_svi.rb +98 -101
  204. data/tests/test_interface_switchport.rb +419 -549
  205. data/tests/test_itd_device_group.rb +145 -0
  206. data/tests/test_itd_device_group_node.rb +199 -0
  207. data/tests/test_itd_service.rb +298 -0
  208. data/tests/test_logger.rb +43 -0
  209. data/tests/test_name_server.rb +11 -2
  210. data/tests/test_node.rb +16 -75
  211. data/tests/test_node_ext.rb +174 -163
  212. data/tests/test_node_util.rb +119 -0
  213. data/tests/test_ntp_config.rb +5 -1
  214. data/tests/test_ntp_server.rb +2 -2
  215. data/tests/test_nxapi.rb +221 -0
  216. data/tests/test_overlay_global.rb +47 -38
  217. data/tests/test_pim.rb +2 -0
  218. data/tests/test_pim_group_list.rb +2 -0
  219. data/tests/test_pim_rp_address.rb +2 -0
  220. data/tests/test_platform.rb +86 -39
  221. data/tests/test_portchannel_global.rb +211 -135
  222. data/tests/test_radius_global.rb +13 -5
  223. data/tests/test_radius_server.rb +256 -104
  224. data/tests/test_radius_server_group.rb +2 -0
  225. data/tests/test_router_bgp.rb +781 -485
  226. data/tests/test_router_ospf.rb +26 -103
  227. data/tests/test_router_ospf_vrf.rb +52 -57
  228. data/tests/test_snmp_notification_receiver.rb +2 -0
  229. data/tests/test_snmpcommunity.rb +2 -0
  230. data/tests/test_snmpgroup.rb +2 -0
  231. data/tests/test_snmpnotification.rb +40 -21
  232. data/tests/test_snmpserver.rb +2 -0
  233. data/tests/test_snmpuser.rb +2 -0
  234. data/tests/test_stp_global.rb +563 -0
  235. data/tests/test_syslog_server.rb +32 -8
  236. data/tests/test_syslog_settings.rb +22 -9
  237. data/tests/test_tacacs_server.rb +32 -27
  238. data/tests/test_tacacs_server_group.rb +100 -45
  239. data/tests/test_tacacs_server_host.rb +135 -43
  240. data/tests/test_vdc.rb +2 -16
  241. data/tests/test_vlan.rb +106 -54
  242. data/tests/test_vlan_mt_full.rb +11 -21
  243. data/tests/test_vlan_private.rb +669 -0
  244. data/tests/test_vpc.rb +312 -159
  245. data/tests/test_vrf.rb +122 -113
  246. data/tests/test_vrf_af.rb +238 -0
  247. data/tests/test_vtp.rb +58 -102
  248. data/tests/test_vxlan_vtep.rb +38 -17
  249. data/tests/test_vxlan_vtep_vni.rb +61 -9
  250. data/tests/test_yum.rb +49 -25
  251. metadata +122 -36
  252. data/lib/cisco_node_utils/cmd_ref/fex.yaml +0 -9
  253. data/lib/cisco_node_utils/cmd_ref/vni.yaml +0 -76
  254. data/lib/cisco_node_utils/vni.rb +0 -227
  255. data/tests/test_vni.rb +0 -106
@@ -0,0 +1,43 @@
1
+ # January 2015, Jie Yang
2
+ #
3
+ # Copyright (c) 2015 Cisco and/or its affiliates.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative 'basetest'
18
+ require_relative '../lib/cisco_node_utils/logger'
19
+
20
+ # TestLogger - unit tests for Cisco::Logger module
21
+ class TestLogger < TestCase
22
+ def test_logger_methods
23
+ assert(defined?(Cisco::Logger.debug), 'debug method not defined')
24
+ assert(defined?(Cisco::Logger.info), 'info method not defined')
25
+ assert(defined?(Cisco::Logger.warn), 'warning method not defined')
26
+ assert(defined?(Cisco::Logger.error), 'error method not defined')
27
+ end
28
+
29
+ # Due to current limitation of minitest, the following test case actually
30
+ # will never fail. But it will print out all the messages that the tested
31
+ # functions are supposed to print. So I still keep this test here
32
+ def test_default_logger_output
33
+ level = Cisco::Logger.level
34
+ Cisco::Logger.level = Logger::DEBUG
35
+ assert_equal(Logger::DEBUG, Cisco::Logger.level)
36
+ assert_output { Cisco::Logger.debug('Test default debug output') }
37
+ assert_output { Cisco::Logger.info('Test default info output') }
38
+ assert_output { Cisco::Logger.warn('Test default warn output') }
39
+ assert_output { Cisco::Logger.error('Test default error output') }
40
+ Cisco::Logger.level = level
41
+ assert_equal(level, Cisco::Logger.level)
42
+ end
43
+ end
@@ -20,22 +20,31 @@ require_relative '../lib/cisco_node_utils/name_server'
20
20
 
21
21
  # TestNameServer - Minitest for NameServer node utility.
22
22
  class TestNameServer < CiscoTestCase
23
+ @skip_unless_supported = 'dnsclient'
24
+
23
25
  def setup
24
26
  # setup runs at the beginning of each test
25
27
  super
28
+ @backup_resolve = backup_resolv_file
26
29
  no_nameserver_google
27
30
  end
28
31
 
29
32
  def teardown
30
33
  # teardown runs at the end of each test
31
34
  no_nameserver_google
35
+ restore_resolv_file(@backup_resolve)
32
36
  super
33
37
  end
34
38
 
35
39
  def no_nameserver_google
36
40
  # Turn the feature off for a clean test.
37
- config('no ip name-server 7.7.7.7',
38
- 'no ip name-server 2001:4860:4860::7777')
41
+ if platform == :ios_xr
42
+ config('no domain name-server 7.7.7.7',
43
+ 'no domain name-server 2001:4860:4860::7777')
44
+ else
45
+ config('no ip name-server 7.7.7.7',
46
+ 'no ip name-server 2001:4860:4860::7777')
47
+ end
39
48
  end
40
49
 
41
50
  # TESTS
data/tests/test_node.rb CHANGED
@@ -19,91 +19,32 @@ require_relative '../lib/cisco_node_utils/command_reference'
19
19
 
20
20
  include Cisco
21
21
 
22
- Node.lazy_connect = true # we'll specify the connection info later
23
-
24
22
  # TestNode - Minitest for core functionality of Node class
25
23
  class TestNode < TestCase
26
24
  def setup
25
+ super
26
+ # Clear out the environment so we have control over which parameters
27
+ # we provide to Node to connect with.
28
+ Node.instance_variable_set(:@instance, nil)
27
29
  end
28
30
 
29
- def teardown
30
- GC.start
31
- end
32
-
33
- # As Node is now a singleton, we cannot instantiate it.
34
-
35
- def test_node_create_not_allowed
36
- assert_raises(NoMethodError) do
31
+ def test_connect_no_environment
32
+ environment = Node::Environment.default_environment_name
33
+ Node::Environment.default_environment_name = '!@#$&@#$' # nonexistent
34
+ # No UDS present on the test host, so default environment fails to connect
35
+ assert_raises(Cisco::ConnectionRefused) do
37
36
  Node.new
38
37
  end
39
- end
40
-
41
- def test_node_connect_zero_arguments
42
- node = Node.instance
43
- # No UDS present on the test host, so default logic fails to connect
44
- assert_raises(RuntimeError) do
45
- node.connect
46
- end
47
- end
48
-
49
- def test_node_connect_one_argument
50
- node = Node.instance
51
- assert_raises(TypeError) do
52
- node.connect(address)
53
- end
54
- end
55
-
56
- def test_node_connect_two_arguments
57
- node = Node.instance
58
- assert_raises(TypeError) do
59
- node.connect(username, password)
60
- end
61
- end
62
-
63
- def test_node_connect_nil_username
64
- node = Node.instance
65
- assert_raises(TypeError) do
66
- node.connect(address, nil, password)
67
- end
68
- end
69
-
70
- def test_node_connect_invalid_username
71
- node = Node.instance
72
- assert_raises(TypeError) do
73
- node.connect(address, node, password)
74
- end
75
- end
76
-
77
- def test_node_connect_username_zero_length
78
- node = Node.instance
79
- assert_raises(ArgumentError) do
80
- node.connect(address, '', password)
81
- end
82
- end
83
-
84
- def test_node_connect_nil_password
85
- node = Node.instance
86
- assert_raises(TypeError) do
87
- node.connect(address, username, nil)
88
- end
89
- end
90
-
91
- def test_node_connect_invalid_password
92
- node = Node.instance
93
- assert_raises(TypeError) do
94
- node.connect(address, username, node)
95
- end
96
- end
97
-
98
- def test_node_connect_password_zero_length
99
- node = Node.instance
100
- assert_raises(ArgumentError) do
101
- node.connect(address, username, '')
38
+ assert_raises(Cisco::ConnectionRefused) do
39
+ Node.instance
102
40
  end
41
+ ensure
42
+ Node::Environment.default_environment_name = environment
103
43
  end
104
44
 
105
- def test_node_connect
45
+ def test_singleton
106
46
  node = Node.instance
107
- node.connect(address, username, password)
47
+ node2 = Node.instance
48
+ assert_equal(node, node2)
108
49
  end
109
50
  end
@@ -16,135 +16,99 @@ require_relative 'ciscotest'
16
16
 
17
17
  # TestNodeExt - Minitest for abstracted Node APIs
18
18
  class TestNodeExt < CiscoTestCase
19
+ def setup
20
+ super
21
+ @chassis = (platform == :nexus) ? 'Chassis' : 'Rack 0'
22
+ @domain = (platform == :nexus) ? 'ip domain-name' : 'domain name'
23
+ end
24
+
19
25
  def assert_output_check(command: nil, pattern: nil, msg: nil, check: nil)
26
+ command += ' | no-more' if platform == :nexus
20
27
  md = assert_show_match(command: command, pattern: pattern, msg: msg)
21
28
  assert_equal(md[1], check, msg)
22
29
  end
23
30
 
24
- def show_run_ospf
25
- "\
26
- router ospf foo
27
- vrf red
28
- log-adjacency-changes
29
- router ospf bar
30
- log-adjacency-changes
31
- vrf red
32
- log-adjacency-changes detail
33
- vrf blue
34
- !
35
- router ospf baz
36
- log-adjacency-changes detail"
37
- end
38
-
39
- def test_node_find_subconfig
40
- result = find_subconfig(show_run_ospf, /router ospf bar/)
41
- assert_equal("\
42
- log-adjacency-changes
43
- vrf red
44
- log-adjacency-changes detail
45
- vrf blue",
46
- result)
47
-
48
- assert_nil(find_subconfig(result, /vrf blue/))
49
-
50
- assert_equal('log-adjacency-changes detail',
51
- find_subconfig(result, /vrf red/))
52
-
53
- assert_nil(find_subconfig(result, /vrf green/))
54
- end
55
-
56
- def test_node_find_ascii
57
- # Find an entry in the parent submode, ignoring nested submodes
58
- assert_equal(['log-adjacency-changes'],
59
- find_ascii(show_run_ospf, /^log-adjacency-changes.*$/,
60
- /router ospf bar/))
61
- # Find an entry in a nested submode
62
- assert_equal(['log-adjacency-changes detail'],
63
- find_ascii(show_run_ospf, /^log-adjacency-changes.*$/,
64
- /router ospf bar/, /vrf red/))
65
- # Submode exists but does not have a match
66
- assert_nil(find_ascii(show_run_ospf, /^log-adjacency-changes.*$/,
67
- /router ospf bar/, /vrf blue/))
68
- # Submode does not exist
69
- assert_nil(find_ascii(show_run_ospf, /^log-adjacency-changes.*$/,
70
- /router ospf bar/, /vrf green/))
71
-
72
- # Entry exists in submode only
73
- assert_nil(find_ascii(show_run_ospf, /^log-adjacency-changes.*$/,
74
- /router ospf foo/))
75
- end
76
-
77
- def test_node_config_get
31
+ def test_config_get
78
32
  result = node.config_get('show_version', 'system_image')
79
33
  assert_equal(result, node.system)
80
34
  end
81
35
 
82
- def test_node_config_get_regexp_tokens
83
- node.client.config(['interface loopback0', 'shutdown'])
84
- node.client.config(['interface loopback1', 'no shutdown'])
36
+ def test_config_get_regexp_tokens
37
+ node.client.set(context: ['interface loopback0'], values: ['shutdown'])
38
+ node.client.set(values: ['interface loopback1', 'no shutdown'])
85
39
 
86
- result = node.config_get('interface', 'shutdown', 'loopback1')
40
+ result = node.config_get('interface', 'shutdown', name: 'loopback1')
87
41
  refute(result)
88
42
  end
89
43
 
90
- def test_node_config_get_invalid
44
+ def test_config_get_invalid
91
45
  assert_raises IndexError do # no entry
92
- node.config_get('feature', 'name')
46
+ node.config_get('foobar', 'name')
93
47
  end
94
48
  assert_raises IndexError do # entry but no config_get
95
49
  node.config_get('show_system', 'resources')
96
50
  end
97
51
  end
98
52
 
99
- def test_node_config_get_default
100
- result = node.config_get_default('snmp_server', 'aaa_user_cache_timeout')
101
- assert_equal(result, 3600)
53
+ def test_config_get_default
54
+ result = node.config_get_default('bgp', 'graceful_restart_timers_restart')
55
+ assert_equal(120, result)
102
56
  end
103
57
 
104
- def test_node_config_get_default_invalid
58
+ def test_config_get_default_invalid
105
59
  assert_raises IndexError do # no name entry
106
60
  node.config_get_default('show_version', 'foobar')
107
61
  end
108
62
  assert_raises IndexError do # no feature entry
109
- node.config_get_default('feature', 'name')
63
+ node.config_get_default('foobar', 'name')
110
64
  end
111
65
  assert_raises IndexError do # no default_value defined
112
66
  node.config_get_default('show_version', 'version')
113
67
  end
114
68
  end
115
69
 
116
- def test_node_config_set
117
- node.config_set('snmp_server', 'aaa_user_cache_timeout', '', 100)
118
- run = node.client.show('show run all | inc snmp')
119
- val = find_ascii(run, /snmp-server aaa-user cache-timeout (\d+)/)
120
- assert_equal(['100'], val)
70
+ def test_config_set
71
+ node.config_set('interface', 'create', name: 'loopback122')
72
+ run = node.client.get(command: 'show run | inc interface')
73
+ val = Client.filter_cli(cli_output: run, value: /interface loopback122/i)
74
+ assert_match(/interface loopback122/i, val[0])
121
75
 
122
- node.config_set('snmp_server', 'aaa_user_cache_timeout', 'no', 100)
123
- run = node.client.show('show run all | inc snmp')
124
- val = find_ascii(run, /snmp-server aaa-user cache-timeout (\d+)/)
125
- assert_equal(['3600'], val)
76
+ node.config_set('interface', 'destroy', name: 'loopback122')
77
+ run = node.client.get(command: 'show run | inc interface')
78
+ val = Client.filter_cli(cli_output: run, value: /interface loopback122/i)
79
+ assert_nil(val)
126
80
  end
127
81
 
128
- def test_node_config_set_invalid
82
+ def test_config_set_invalid
129
83
  assert_raises IndexError do
130
- node.config_set('feature', 'name')
84
+ node.config_set('foobar', 'name')
131
85
  end
132
- assert_raises IndexError do # feature exists but no config_set
86
+ assert_raises(IndexError, Cisco::UnsupportedError) do
87
+ # feature exists but no config_set
133
88
  node.config_set('show_version', 'system_image')
134
89
  end
135
- assert_raises ArgumentError do # not enough args
136
- node.config_set('vtp', 'domain')
137
- end
138
- assert_raises ArgumentError do # too many args
139
- node.config_set('vtp', 'domain', 'example.com', 'baz')
90
+ # TODO: none of the supported classes on IOS XR use printf-style args
91
+ if platform == :nexus # rubocop:disable Style/GuardClause
92
+ assert_raises ArgumentError do # not enough args
93
+ node.config_set('vtp', 'domain')
94
+ end
95
+ assert_raises ArgumentError do # too many args
96
+ node.config_set('vtp', 'domain', 'example.com', 'baz')
97
+ end
140
98
  end
141
99
  end
142
100
 
143
- def test_node_cli_caching
101
+ def test_cli_caching
144
102
  # don't use config() here because we are testing caching and flushing
145
- @device.cmd('conf t ; ip domain-name minitest ; end')
103
+ @device.cmd('conf t')
104
+ @device.cmd("#{@domain} minitest")
105
+ @device.cmd('commit') if platform == :ios_xr
106
+ @device.cmd('end')
146
107
  dom1 = node.domain_name
147
- @device.cmd('conf t ; no ip domain-name minitest ; end')
108
+ @device.cmd('conf t')
109
+ @device.cmd("no #{@domain} minitest")
110
+ @device.cmd('commit') if platform == :ios_xr
111
+ @device.cmd('end')
148
112
  dom2 = node.domain_name
149
113
  assert_equal(dom1, dom2) # cached output was used for dom2
150
114
 
@@ -153,56 +117,78 @@ vrf blue",
153
117
  refute_equal(dom1, dom3)
154
118
  end
155
119
 
156
- def test_node_get_product_description
120
+ def test_get_product_description
157
121
  product_description = node.product_description
158
- ref = cmd_ref.lookup('show_version', 'description')
159
- assert(ref, 'Error, reference not found')
160
122
 
161
- assert_output_check(command: ref.test_config_get,
162
- pattern: ref.test_config_get_regex,
123
+ command = node.cmd_ref.lookup('show_version', 'description').get_command
124
+
125
+ # Hardware
126
+ # cisco Nexus9000 C9396PX Chassis
127
+ #
128
+ # Other variants for the line of interest:
129
+ # cisco Nexus9000 C9504 (4 Slot) Chassis ("Supervisor Module")
130
+ # ^-module_id-ignore!-^
131
+ # cisco Nexus3000 C3132Q Chassis
132
+ # cisco N3K-C3048TP-1GE
133
+ pattern = /Hardware\n cisco (([^(\n]+|\(\d+ Slot\))+\w+)/ if
134
+ platform[/nexus/]
135
+ pattern = /DESCR: "(.*)"/ if platform[/ios_xr/]
136
+
137
+ assert_output_check(command: command,
138
+ pattern: pattern,
163
139
  check: product_description,
164
140
  msg: 'Error, Product description does not match')
165
141
  end
166
142
 
167
- def test_node_get_product_id
168
- assert_output_check(command: 'show inventory | no-more',
169
- pattern: /NAME: \"Chassis\".*\nPID: (\S+)/,
143
+ def test_get_product_id
144
+ assert_output_check(command: 'show inventory',
145
+ pattern: /NAME: \"#{@chassis}\".*\nPID: (\S+)/,
170
146
  check: node.product_id,
171
147
  msg: 'Error, Product id does not match')
172
148
  end
173
149
 
174
- def test_node_get_product_version_id
175
- assert_output_check(command: 'show inventory | no-more',
176
- pattern: /NAME: \"Chassis\".*\n.*VID: (\w+)/,
150
+ def test_get_product_version_id
151
+ assert_output_check(command: 'show inventory',
152
+ pattern: /NAME: \"#{@chassis}\".*\n.*VID: (\w+)/,
177
153
  check: node.product_version_id,
178
154
  msg: 'Error, Version id does not match')
179
155
  end
180
156
 
181
- def test_node_get_product_serial_number
182
- assert_output_check(command: 'show inventory | no-more',
183
- pattern: /NAME: \"Chassis\".*\n.*SN: (\w+)/,
157
+ def test_get_product_serial_number
158
+ assert_output_check(command: 'show inventory',
159
+ pattern: /NAME: \"#{@chassis}\".*\n.*SN: ([-\w]+)/,
184
160
  check: node.product_serial_number,
185
161
  msg: 'Error, Serial number does not match')
186
162
  end
187
163
 
188
- def test_node_get_os
189
- assert_output_check(command: 'show version | no-more',
190
- pattern: /\n(Cisco.*)\n/,
164
+ def test_get_os
165
+ assert_output_check(command: 'show version',
166
+ pattern: /\n(Cisco.*Software)/,
191
167
  check: node.os,
192
168
  msg: 'Error, OS version does not match')
193
169
  end
194
170
 
195
- def test_node_get_os_version
196
- ref = cmd_ref.lookup('show_version', 'version')
197
- assert(ref, 'Error, reference not found')
198
- assert_output_check(command: ref.test_config_get,
199
- pattern: ref.test_config_get_regex[1],
171
+ def test_get_os_version
172
+ # /N(5|6|7)/
173
+ # system: version 7.3(0)D1(1) [build 7.3(0)D1(1)]
174
+ # /N(3|8|9)/
175
+ # NXOS: version 7.0(3)I3(1) [build 7.0(3)I3(1)]
176
+
177
+ pattern = /(?:system|NXOS):\s+version (.*)\n/ if platform[/nexus/]
178
+ pattern = /IOS XR.*Version (.*)$/ if platform[/ios_xr/]
179
+
180
+ assert_output_check(command: 'show version',
181
+ pattern: pattern,
200
182
  check: node.os_version,
201
183
  msg: 'Error, OS version does not match')
202
184
  end
203
185
 
204
- def test_node_get_host_name_when_not_set
205
- s = @device.cmd('show running-config all | no-more')
186
+ def test_get_host_name_when_not_set
187
+ if platform == :nexus
188
+ s = @device.cmd('show running-config all | no-more')
189
+ else
190
+ s = @device.cmd('show running-config all')
191
+ end
206
192
  pattern = /.*\nhostname (\S+)/
207
193
  md = pattern.match(s)
208
194
  if md
@@ -223,15 +209,23 @@ vrf blue",
223
209
  switchname ? config('no switchname') : config('no hostname')
224
210
 
225
211
  name = node.host_name
226
- assert_equal('switch', name)
212
+ if platform == :nexus
213
+ assert_equal('switch', name)
214
+ else
215
+ assert_equal('ios', name)
216
+ end
227
217
 
228
218
  return unless configured_name
229
219
  config("hostname #{configured_name}") if switchname == false
230
220
  config("switchname #{configured_name}") if switchname == true
231
221
  end
232
222
 
233
- def test_node_get_host_name_when_set
234
- s = @device.cmd('show running-config all | no-more')
223
+ def test_get_host_name_when_set
224
+ if platform == :nexus
225
+ s = @device.cmd('show running-config all | no-more')
226
+ else
227
+ s = @device.cmd('show running-config all')
228
+ end
235
229
  pattern = /.*\nhostname (\S+)/
236
230
  md = pattern.match(s)
237
231
  if md
@@ -263,10 +257,10 @@ vrf blue",
263
257
  end
264
258
  end
265
259
 
266
- def test_node_get_domain_name_when_not_set
260
+ def test_get_domain_name_when_not_set
267
261
  # Test with default vrf only
268
- s = @device.cmd("show running-config | incl '^ip domain-name'")
269
- pattern = /^ip domain-name (\S+)/
262
+ s = @device.cmd("show running-config | incl '^#{@domain}'")
263
+ pattern = /^#{@domain} (\S+)/
270
264
  md = pattern.match(s)
271
265
  if md
272
266
  configured_domain_name = md[1]
@@ -274,21 +268,22 @@ vrf blue",
274
268
  configured_domain_name = nil
275
269
  end
276
270
 
277
- config("no ip domain-name #{configured_domain_name}")
271
+ config("no #{@domain} #{configured_domain_name}") unless
272
+ configured_domain_name.nil?
278
273
 
279
274
  domain_name = node.domain_name
280
275
  assert_equal('', domain_name)
281
276
 
282
277
  if configured_domain_name
283
- config("ip domain-name #{configured_domain_name}")
278
+ config("#{@domain} #{configured_domain_name}")
284
279
  else
285
- config('no ip domain-name abc.com')
280
+ config("no #{@domain} abc.com")
286
281
  end
287
282
  end
288
283
 
289
- def test_node_get_domain_name_when_set
284
+ def test_get_domain_name_when_set
290
285
  s = @device.cmd('show running-config | no-more')
291
- pattern = /.*\nip domain-name (\S+)/
286
+ pattern = /.*\n#{@domain} (\S+)/
292
287
  md = pattern.match(s)
293
288
  if md
294
289
  configured_domain_name = md[1]
@@ -296,26 +291,25 @@ vrf blue",
296
291
  configured_domain_name = nil
297
292
  end
298
293
 
299
- config('ip domain-name abc.com')
294
+ config("#{@domain} abc.com")
300
295
 
301
296
  domain_name = node.domain_name
302
297
  assert_equal('abc.com', domain_name)
303
298
 
304
299
  if configured_domain_name
305
- config("ip domain-name #{configured_domain_name}")
300
+ config("#{@domain} #{configured_domain_name}")
306
301
  else
307
- config('no ip domain-name abc.com')
302
+ config("no #{@domain} abc.com")
308
303
  end
309
304
  end
310
305
 
311
- def test_node_get_system_uptime
306
+ def test_get_system_uptime
312
307
  node.cache_flush
313
- # rubocop:disable Metrics/LineLength
314
- pattern = /.*System uptime:\s+(\d+) days, (\d+) hours, (\d+) minutes, (\d+) seconds/
315
- # rubocop:enable Metrics/LineLength
316
308
 
317
- md = assert_show_match(command: 'show system uptime | no-more',
318
- pattern: pattern)
309
+ cmd = node.cmd_ref.lookup('show_system', 'uptime').get_command
310
+ pattern = node.cmd_ref.lookup('show_system', 'uptime').get_value
311
+
312
+ md = assert_show_match(command: cmd, pattern: pattern)
319
313
  node_uptime = node.system_uptime
320
314
 
321
315
  observed_system_uptime = (
@@ -329,58 +323,75 @@ vrf blue",
329
323
  "Error, System uptime delta is (#{delta}), expected (delta < 10)")
330
324
  end
331
325
 
332
- def test_node_get_last_reset_time
333
- last_reset_time = node.last_reset_time
334
- ref = cmd_ref.lookup('show_version', 'last_reset_time')
335
- assert(ref, 'Error, reference not found')
336
- # N9k doesn't provide this info at present.
337
- if !last_reset_time.empty?
338
- assert_output_check(command: ref.test_config_get,
339
- pattern: ref.test_config_get_regex,
340
- check: last_reset_time,
341
- msg: 'Error, Last reset time does not match')
342
- else
343
- refute_show_match(command: ref.test_config_get,
344
- pattern: ref.test_config_get_regex,
345
- msg: 'output found in ASCII but not in node')
326
+ def test_get_last_reset_time
327
+ if validate_property_excluded?('show_version', 'last_reset_time')
328
+ assert_nil(node.last_reset_time)
329
+ return
346
330
  end
331
+ assert_output_check(command: 'show version',
332
+ pattern: /.*\nLast reset at \d+ usecs after (.*)\n/,
333
+ check: node.last_reset_time,
334
+ msg: 'Error, Last reset time does not match')
347
335
  end
348
336
 
349
- def test_node_get_last_reset_reason
350
- ref = cmd_ref.lookup('show_version', 'last_reset_reason')
351
- assert(ref, 'Error, reference not found')
352
- assert_output_check(command: ref.test_config_get,
353
- pattern: ref.test_config_get_regex,
337
+ def test_get_last_reset_reason
338
+ if validate_property_excluded?('show_version', 'last_reset_reason')
339
+ assert_nil(node.last_reset_reason)
340
+ return
341
+ end
342
+ assert_output_check(command: 'show version',
343
+ pattern: /.*\nLast reset.*\n\n? Reason: (.*)\n/,
354
344
  check: node.last_reset_reason,
355
345
  msg: 'Error, Last reset reason does not match')
356
346
  end
357
347
 
358
- def test_node_get_system_cpu_utilization
348
+ def test_get_system_cpu_utilization
349
+ if validate_property_excluded?('system', 'resources')
350
+ assert_nil(node.system_cpu_utilization)
351
+ return
352
+ end
359
353
  cpu_utilization = node.system_cpu_utilization
360
- ref = cmd_ref.lookup('system', 'resources')
361
- assert(ref, 'Error, reference not found')
362
- md = assert_show_match(command: ref.test_config_get,
363
- pattern: ref.test_config_get_regex)
354
+ md = assert_show_match(
355
+ command: 'show system resources',
356
+ pattern: /.*CPU states : (\d+\.\d+)% user, (\d+\.\d+)% kernel/)
364
357
  observed_cpu_utilization = md[1].to_f + md[2].to_f
365
358
  delta = cpu_utilization - observed_cpu_utilization
366
359
  assert(delta > -15.0 && delta < 15.0,
367
360
  "Error: delta #{delta}, not +- 15.0")
368
361
  end
369
362
 
370
- def test_node_get_boot
371
- ref = cmd_ref.lookup('show_version', 'boot_image')
372
- assert(ref, 'Error, reference not found')
373
- assert_output_check(command: ref.test_config_get,
374
- pattern: ref.test_config_get_regex,
363
+ def test_get_boot
364
+ if validate_property_excluded?('show_version', 'boot_image')
365
+ assert_nil(node.boot)
366
+ return
367
+ end
368
+
369
+ # /N(5|6|7)/
370
+ # kickstart image file is: bootflash:///n7000-s2-kickstart.7.3.0.D1.1.bin
371
+ # /N(3|8|9)/
372
+ # NXOS image file is: bootflash:///nxos.7.0.3.I3.1.bin
373
+
374
+ pattern = /(?:kickstart|NXOS) image file is:\s+(.*)$/
375
+ assert_output_check(command: 'show version',
376
+ pattern: pattern,
375
377
  check: node.boot,
376
378
  msg: 'Error, Kickstart Image does not match')
377
379
  end
378
380
 
379
- def test_node_get_system
380
- ref = cmd_ref.lookup('show_version', 'system_image')
381
- assert(ref, 'Error, reference not found')
382
- assert_output_check(command: ref.test_config_get,
383
- pattern: ref.test_config_get_regex,
381
+ def test_get_system
382
+ if validate_property_excluded?('system', 'resources')
383
+ assert_nil(node.system)
384
+ return
385
+ end
386
+
387
+ # /N(5|6|7)/
388
+ # system image file is: bootflash:///n7000-s2-kickstart.7.3.0.D1.1.bin
389
+ # /N(3|8|9)/
390
+ # NXOS image file is: bootflash:///nxos.7.0.3.I3.1.bin
391
+
392
+ pattern = /(?:system|NXOS) image file is:\s+(.*)$/
393
+ assert_output_check(command: 'show version',
394
+ pattern: pattern,
384
395
  check: node.system,
385
396
  msg: 'Error, System Image does not match')
386
397
  end