cisco_node_utils_mgx 2.1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (357) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +96 -0
  5. data/.travis.yml +17 -0
  6. data/CHANGELOG.md +676 -0
  7. data/CONTRIBUTING.md +43 -0
  8. data/Gemfile +10 -0
  9. data/LICENSE +201 -0
  10. data/README.md +246 -0
  11. data/Rakefile +44 -0
  12. data/SUPPORT.md +3 -0
  13. data/bin/.rubocop.yml +18 -0
  14. data/bin/check_metric_limits.rb +109 -0
  15. data/bin/git/hooks/commit-msg/enforce_style +89 -0
  16. data/bin/git/hooks/hook_lib +115 -0
  17. data/bin/git/hooks/hooks-wrapper +38 -0
  18. data/bin/git/hooks/post-flow-hotfix-start/update-version +24 -0
  19. data/bin/git/hooks/post-flow-release-finish/update-version +29 -0
  20. data/bin/git/hooks/post-flow-release-start/update-version +19 -0
  21. data/bin/git/hooks/post-merge/update-hooks +6 -0
  22. data/bin/git/hooks/post-rewrite/update-hooks +6 -0
  23. data/bin/git/hooks/pre-commit/check_unstaged_changes +18 -0
  24. data/bin/git/hooks/pre-commit/rubocop +25 -0
  25. data/bin/git/hooks/pre-commit/validate-diffs +45 -0
  26. data/bin/git/hooks/pre-commit/validate-yaml +18 -0
  27. data/bin/git/hooks/pre-push/check-changelog +24 -0
  28. data/bin/git/hooks/pre-push/rubocop +7 -0
  29. data/bin/git/update-hooks +123 -0
  30. data/bin/show_running_yang.rb +233 -0
  31. data/cisco_node_utils.gemspec +41 -0
  32. data/docs/README-develop-best-practices.md +521 -0
  33. data/docs/README-develop-node-utils-APIs.md +570 -0
  34. data/docs/README-maintainers.md +77 -0
  35. data/docs/README-test-execution.md +57 -0
  36. data/docs/README-utilities.md +14 -0
  37. data/docs/agent_files.png +0 -0
  38. data/docs/cisco_node_utils.yaml.example +36 -0
  39. data/docs/template-router.rb +123 -0
  40. data/docs/template-test_router.rb +104 -0
  41. data/ext/mkrf_conf.rb +63 -0
  42. data/lib/.rubocop.yml +18 -0
  43. data/lib/cisco_node_utils/aaa_authentication_login.rb +95 -0
  44. data/lib/cisco_node_utils/aaa_authentication_login_service.rb +138 -0
  45. data/lib/cisco_node_utils/aaa_authorization_service.rb +156 -0
  46. data/lib/cisco_node_utils/ace.rb +467 -0
  47. data/lib/cisco_node_utils/acl.rb +101 -0
  48. data/lib/cisco_node_utils/banner.rb +63 -0
  49. data/lib/cisco_node_utils/bfd_global.rb +305 -0
  50. data/lib/cisco_node_utils/bgp.rb +988 -0
  51. data/lib/cisco_node_utils/bgp_af.rb +545 -0
  52. data/lib/cisco_node_utils/bgp_af_aggr_addr.rb +207 -0
  53. data/lib/cisco_node_utils/bgp_neighbor.rb +527 -0
  54. data/lib/cisco_node_utils/bgp_neighbor_af.rb +780 -0
  55. data/lib/cisco_node_utils/bridge_domain.rb +178 -0
  56. data/lib/cisco_node_utils/bridge_domain_vni.rb +206 -0
  57. data/lib/cisco_node_utils/cisco_cmn_utils.rb +444 -0
  58. data/lib/cisco_node_utils/client/client.rb +238 -0
  59. data/lib/cisco_node_utils/client/grpc/client.rb +395 -0
  60. data/lib/cisco_node_utils/client/grpc/ems.proto +148 -0
  61. data/lib/cisco_node_utils/client/grpc/ems.rb +111 -0
  62. data/lib/cisco_node_utils/client/grpc/ems_services.rb +49 -0
  63. data/lib/cisco_node_utils/client/grpc.rb +33 -0
  64. data/lib/cisco_node_utils/client/nxapi/client.rb +368 -0
  65. data/lib/cisco_node_utils/client/nxapi.rb +31 -0
  66. data/lib/cisco_node_utils/client/utils.rb +180 -0
  67. data/lib/cisco_node_utils/client.rb +35 -0
  68. data/lib/cisco_node_utils/cmd_ref/README_YAML.md +590 -0
  69. data/lib/cisco_node_utils/cmd_ref/aaa_auth_login_service.yaml +25 -0
  70. data/lib/cisco_node_utils/cmd_ref/aaa_authentication_login.yaml +38 -0
  71. data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +40 -0
  72. data/lib/cisco_node_utils/cmd_ref/acl.yaml +48 -0
  73. data/lib/cisco_node_utils/cmd_ref/banner.yaml +11 -0
  74. data/lib/cisco_node_utils/cmd_ref/bfd_global.yaml +117 -0
  75. data/lib/cisco_node_utils/cmd_ref/bgp.yaml +383 -0
  76. data/lib/cisco_node_utils/cmd_ref/bgp_af.yaml +223 -0
  77. data/lib/cisco_node_utils/cmd_ref/bgp_af_aa.yaml +38 -0
  78. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor.yaml +174 -0
  79. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor_af.yaml +236 -0
  80. data/lib/cisco_node_utils/cmd_ref/bridge_domain.yaml +49 -0
  81. data/lib/cisco_node_utils/cmd_ref/bridge_domain_vni.yaml +33 -0
  82. data/lib/cisco_node_utils/cmd_ref/dhcp_relay_global.yaml +128 -0
  83. data/lib/cisco_node_utils/cmd_ref/dnsclient.yaml +55 -0
  84. data/lib/cisco_node_utils/cmd_ref/encapsulation.yaml +25 -0
  85. data/lib/cisco_node_utils/cmd_ref/evpn_multicast.yaml +12 -0
  86. data/lib/cisco_node_utils/cmd_ref/evpn_multisite.yaml +18 -0
  87. data/lib/cisco_node_utils/cmd_ref/evpn_stormcontrol.yaml +18 -0
  88. data/lib/cisco_node_utils/cmd_ref/evpn_vni.yaml +48 -0
  89. data/lib/cisco_node_utils/cmd_ref/fabricpath.yaml +183 -0
  90. data/lib/cisco_node_utils/cmd_ref/fabricpath_topology.yaml +40 -0
  91. data/lib/cisco_node_utils/cmd_ref/feature.yaml +126 -0
  92. data/lib/cisco_node_utils/cmd_ref/hostname.yaml +8 -0
  93. data/lib/cisco_node_utils/cmd_ref/hsrp_global.yaml +25 -0
  94. data/lib/cisco_node_utils/cmd_ref/images.yaml +8 -0
  95. data/lib/cisco_node_utils/cmd_ref/interface.yaml +781 -0
  96. data/lib/cisco_node_utils/cmd_ref/interface_channel_group.yaml +45 -0
  97. data/lib/cisco_node_utils/cmd_ref/interface_evpn_multisite.yaml +17 -0
  98. data/lib/cisco_node_utils/cmd_ref/interface_hsrp_group.yaml +120 -0
  99. data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +112 -0
  100. data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +87 -0
  101. data/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml +42 -0
  102. data/lib/cisco_node_utils/cmd_ref/inventory.yaml +45 -0
  103. data/lib/cisco_node_utils/cmd_ref/ip_multicast.yaml +22 -0
  104. data/lib/cisco_node_utils/cmd_ref/itd_device_group.yaml +83 -0
  105. data/lib/cisco_node_utils/cmd_ref/itd_service.yaml +119 -0
  106. data/lib/cisco_node_utils/cmd_ref/memory.yaml +24 -0
  107. data/lib/cisco_node_utils/cmd_ref/ntp_auth_key.yaml +10 -0
  108. data/lib/cisco_node_utils/cmd_ref/ntp_config.yaml +27 -0
  109. data/lib/cisco_node_utils/cmd_ref/ntp_server.yaml +34 -0
  110. data/lib/cisco_node_utils/cmd_ref/object_group.yaml +32 -0
  111. data/lib/cisco_node_utils/cmd_ref/ospf.yaml +91 -0
  112. data/lib/cisco_node_utils/cmd_ref/ospf_area.yaml +91 -0
  113. data/lib/cisco_node_utils/cmd_ref/ospf_area_vlink.yaml +88 -0
  114. data/lib/cisco_node_utils/cmd_ref/overlay_global.yaml +37 -0
  115. data/lib/cisco_node_utils/cmd_ref/pim.yaml +43 -0
  116. data/lib/cisco_node_utils/cmd_ref/portchannel_global.yaml +86 -0
  117. data/lib/cisco_node_utils/cmd_ref/radius_global.yaml +37 -0
  118. data/lib/cisco_node_utils/cmd_ref/radius_server.yaml +100 -0
  119. data/lib/cisco_node_utils/cmd_ref/radius_server_group.yaml +19 -0
  120. data/lib/cisco_node_utils/cmd_ref/route_map.yaml +601 -0
  121. data/lib/cisco_node_utils/cmd_ref/show_system.yaml +9 -0
  122. data/lib/cisco_node_utils/cmd_ref/show_version.yaml +84 -0
  123. data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +81 -0
  124. data/lib/cisco_node_utils/cmd_ref/snmp_group.yaml +9 -0
  125. data/lib/cisco_node_utils/cmd_ref/snmp_notification_receiver.yaml +74 -0
  126. data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +91 -0
  127. data/lib/cisco_node_utils/cmd_ref/snmp_user.yaml +57 -0
  128. data/lib/cisco_node_utils/cmd_ref/snmpnotification.yaml +23 -0
  129. data/lib/cisco_node_utils/cmd_ref/span_session.yaml +65 -0
  130. data/lib/cisco_node_utils/cmd_ref/stp_global.yaml +235 -0
  131. data/lib/cisco_node_utils/cmd_ref/syslog_facility.yaml +10 -0
  132. data/lib/cisco_node_utils/cmd_ref/syslog_server.yaml +34 -0
  133. data/lib/cisco_node_utils/cmd_ref/syslog_settings.yaml +45 -0
  134. data/lib/cisco_node_utils/cmd_ref/system.yaml +7 -0
  135. data/lib/cisco_node_utils/cmd_ref/tacacs_global.yaml +37 -0
  136. data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +63 -0
  137. data/lib/cisco_node_utils/cmd_ref/tacacs_server_group.yaml +45 -0
  138. data/lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml +64 -0
  139. data/lib/cisco_node_utils/cmd_ref/upgrade.yaml +38 -0
  140. data/lib/cisco_node_utils/cmd_ref/vdc.yaml +52 -0
  141. data/lib/cisco_node_utils/cmd_ref/virtual_service.yaml +8 -0
  142. data/lib/cisco_node_utils/cmd_ref/vlan.yaml +106 -0
  143. data/lib/cisco_node_utils/cmd_ref/vpc.yaml +233 -0
  144. data/lib/cisco_node_utils/cmd_ref/vrf.yaml +86 -0
  145. data/lib/cisco_node_utils/cmd_ref/vrf_af.yaml +139 -0
  146. data/lib/cisco_node_utils/cmd_ref/vtp.yaml +32 -0
  147. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +114 -0
  148. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml +71 -0
  149. data/lib/cisco_node_utils/cmd_ref/yang.yaml +7 -0
  150. data/lib/cisco_node_utils/cmd_ref/yum.yaml +68 -0
  151. data/lib/cisco_node_utils/command_reference.rb +724 -0
  152. data/lib/cisco_node_utils/configparser_lib.rb +195 -0
  153. data/lib/cisco_node_utils/constants.rb +40 -0
  154. data/lib/cisco_node_utils/dhcp_relay_global.rb +302 -0
  155. data/lib/cisco_node_utils/dns_domain.rb +93 -0
  156. data/lib/cisco_node_utils/domain_name.rb +82 -0
  157. data/lib/cisco_node_utils/encapsulation.rb +112 -0
  158. data/lib/cisco_node_utils/environment.rb +110 -0
  159. data/lib/cisco_node_utils/evpn_multicast.rb +66 -0
  160. data/lib/cisco_node_utils/evpn_multisite.rb +96 -0
  161. data/lib/cisco_node_utils/evpn_stormcontrol.rb +84 -0
  162. data/lib/cisco_node_utils/evpn_vni.rb +159 -0
  163. data/lib/cisco_node_utils/exceptions.rb +140 -0
  164. data/lib/cisco_node_utils/fabricpath_global.rb +405 -0
  165. data/lib/cisco_node_utils/fabricpath_topology.rb +137 -0
  166. data/lib/cisco_node_utils/feature.rb +377 -0
  167. data/lib/cisco_node_utils/hostname.rb +62 -0
  168. data/lib/cisco_node_utils/hsrp_global.rb +97 -0
  169. data/lib/cisco_node_utils/interface.rb +2128 -0
  170. data/lib/cisco_node_utils/interface_channel_group.rb +142 -0
  171. data/lib/cisco_node_utils/interface_evpn_multisite.rb +72 -0
  172. data/lib/cisco_node_utils/interface_hsrp_group.rb +557 -0
  173. data/lib/cisco_node_utils/interface_ospf.rb +378 -0
  174. data/lib/cisco_node_utils/interface_portchannel.rb +180 -0
  175. data/lib/cisco_node_utils/interface_service_vni.rb +132 -0
  176. data/lib/cisco_node_utils/ip_multicast.rb +90 -0
  177. data/lib/cisco_node_utils/itd_device_group.rb +228 -0
  178. data/lib/cisco_node_utils/itd_device_group_node.rb +144 -0
  179. data/lib/cisco_node_utils/itd_service.rb +511 -0
  180. data/lib/cisco_node_utils/logger.rb +78 -0
  181. data/lib/cisco_node_utils/name_server.rb +64 -0
  182. data/lib/cisco_node_utils/node.rb +443 -0
  183. data/lib/cisco_node_utils/node_util.rb +111 -0
  184. data/lib/cisco_node_utils/ntp_auth_key.rb +67 -0
  185. data/lib/cisco_node_utils/ntp_config.rb +83 -0
  186. data/lib/cisco_node_utils/ntp_server.rb +86 -0
  187. data/lib/cisco_node_utils/object_group.rb +75 -0
  188. data/lib/cisco_node_utils/object_group_entry.rb +143 -0
  189. data/lib/cisco_node_utils/overlay_global.rb +142 -0
  190. data/lib/cisco_node_utils/pim.rb +131 -0
  191. data/lib/cisco_node_utils/pim_group_list.rb +109 -0
  192. data/lib/cisco_node_utils/pim_rp_address.rb +103 -0
  193. data/lib/cisco_node_utils/platform.rb +217 -0
  194. data/lib/cisco_node_utils/portchannel_global.rb +347 -0
  195. data/lib/cisco_node_utils/radius_global.rb +165 -0
  196. data/lib/cisco_node_utils/radius_server.rb +421 -0
  197. data/lib/cisco_node_utils/radius_server_group.rb +117 -0
  198. data/lib/cisco_node_utils/route_map.rb +2540 -0
  199. data/lib/cisco_node_utils/router_ospf.rb +77 -0
  200. data/lib/cisco_node_utils/router_ospf_area.rb +416 -0
  201. data/lib/cisco_node_utils/router_ospf_area_vlink.rb +313 -0
  202. data/lib/cisco_node_utils/router_ospf_vrf.rb +342 -0
  203. data/lib/cisco_node_utils/snmp_notification_receiver.rb +176 -0
  204. data/lib/cisco_node_utils/snmpcommunity.rb +109 -0
  205. data/lib/cisco_node_utils/snmpgroup.rb +54 -0
  206. data/lib/cisco_node_utils/snmpnotification.rb +57 -0
  207. data/lib/cisco_node_utils/snmpserver.rb +132 -0
  208. data/lib/cisco_node_utils/snmpuser.rb +403 -0
  209. data/lib/cisco_node_utils/span_session.rb +149 -0
  210. data/lib/cisco_node_utils/stp_global.rb +676 -0
  211. data/lib/cisco_node_utils/syslog_facility.rb +64 -0
  212. data/lib/cisco_node_utils/syslog_server.rb +146 -0
  213. data/lib/cisco_node_utils/syslog_settings.rb +174 -0
  214. data/lib/cisco_node_utils/tacacs_global.rb +137 -0
  215. data/lib/cisco_node_utils/tacacs_server.rb +173 -0
  216. data/lib/cisco_node_utils/tacacs_server_group.rb +149 -0
  217. data/lib/cisco_node_utils/tacacs_server_host.rb +216 -0
  218. data/lib/cisco_node_utils/upgrade.rb +122 -0
  219. data/lib/cisco_node_utils/vdc.rb +118 -0
  220. data/lib/cisco_node_utils/version.rb +21 -0
  221. data/lib/cisco_node_utils/vlan.rb +301 -0
  222. data/lib/cisco_node_utils/vpc.rb +466 -0
  223. data/lib/cisco_node_utils/vrf.rb +192 -0
  224. data/lib/cisco_node_utils/vrf_af.rb +327 -0
  225. data/lib/cisco_node_utils/vtp.rb +125 -0
  226. data/lib/cisco_node_utils/vxlan_vtep.rb +286 -0
  227. data/lib/cisco_node_utils/vxlan_vtep_vni.rb +331 -0
  228. data/lib/cisco_node_utils/yang.rb +160 -0
  229. data/lib/cisco_node_utils/yum.rb +213 -0
  230. data/lib/cisco_node_utils.rb +21 -0
  231. data/lib/minitest/environment_plugin.rb +31 -0
  232. data/lib/minitest/log_level_plugin.rb +41 -0
  233. data/spec/client_spec.rb +7 -0
  234. data/spec/environment_spec.rb +384 -0
  235. data/spec/grpc_client_spec.rb +23 -0
  236. data/spec/isolate/all_clients_spec.rb +9 -0
  237. data/spec/isolate/grpc_only_spec.rb +16 -0
  238. data/spec/isolate/no_clients_spec.rb +26 -0
  239. data/spec/isolate/nxapi_only_spec.rb +16 -0
  240. data/spec/nxapi_client_spec.rb +42 -0
  241. data/spec/schema.yaml +82 -0
  242. data/spec/shared_examples_for_clients.rb +14 -0
  243. data/spec/spec_helper.rb +91 -0
  244. data/spec/whitespace_spec.rb +10 -0
  245. data/spec/yaml_spec.rb +42 -0
  246. data/tests/.rubocop.yml +18 -0
  247. data/tests/CSCuxdublin-1.0.0-7.0.3.I3.1.lib32_n9000.rpm +0 -0
  248. data/tests/basetest.rb +243 -0
  249. data/tests/ciscotest.rb +577 -0
  250. data/tests/cmd_config.yaml +75 -0
  251. data/tests/cmd_config_invalid.yaml +16 -0
  252. data/tests/n9000_sample-1.0.0-7.0.3.x86_64.rpm +0 -0
  253. data/tests/noop.rb +7 -0
  254. data/tests/platform_info.rb +63 -0
  255. data/tests/tacacs_server.yaml.example +6 -0
  256. data/tests/test_aaa_authentication_login.rb +243 -0
  257. data/tests/test_aaa_authentication_login_service.rb +761 -0
  258. data/tests/test_aaa_authorization_service.rb +874 -0
  259. data/tests/test_ace.rb +304 -0
  260. data/tests/test_acl.rb +185 -0
  261. data/tests/test_banner.rb +85 -0
  262. data/tests/test_bfd_global.rb +272 -0
  263. data/tests/test_bgp_af.rb +875 -0
  264. data/tests/test_bgp_af_aa.rb +108 -0
  265. data/tests/test_bgp_neighbor.rb +596 -0
  266. data/tests/test_bgp_neighbor_af.rb +781 -0
  267. data/tests/test_bridge_domain.rb +198 -0
  268. data/tests/test_bridge_domain_vni.rb +109 -0
  269. data/tests/test_client_utils.rb +111 -0
  270. data/tests/test_cmn_utils.rb +76 -0
  271. data/tests/test_command_config.rb +206 -0
  272. data/tests/test_command_reference.rb +669 -0
  273. data/tests/test_dhcp_relay_global.rb +286 -0
  274. data/tests/test_dns_domain.rb +123 -0
  275. data/tests/test_domain_name.rb +96 -0
  276. data/tests/test_encapsulation.rb +75 -0
  277. data/tests/test_evpn_multicast.rb +65 -0
  278. data/tests/test_evpn_multisite.rb +70 -0
  279. data/tests/test_evpn_stormcontrol.rb +56 -0
  280. data/tests/test_evpn_vni.rb +131 -0
  281. data/tests/test_fabricpath_global.rb +246 -0
  282. data/tests/test_fabricpath_topology.rb +77 -0
  283. data/tests/test_feature.rb +272 -0
  284. data/tests/test_grpc.rb +166 -0
  285. data/tests/test_hostname.rb +64 -0
  286. data/tests/test_hsrp_global.rb +79 -0
  287. data/tests/test_interface.rb +1958 -0
  288. data/tests/test_interface_bdi.rb +80 -0
  289. data/tests/test_interface_channel_group.rb +131 -0
  290. data/tests/test_interface_evpn_multisite.rb +94 -0
  291. data/tests/test_interface_hsrp.rb +134 -0
  292. data/tests/test_interface_hsrp_group.rb +570 -0
  293. data/tests/test_interface_ospf.rb +820 -0
  294. data/tests/test_interface_portchannel.rb +135 -0
  295. data/tests/test_interface_private_vlan.rb +365 -0
  296. data/tests/test_interface_service_vni.rb +203 -0
  297. data/tests/test_interface_svi.rb +210 -0
  298. data/tests/test_interface_switchport.rb +468 -0
  299. data/tests/test_ip_multicast.rb +80 -0
  300. data/tests/test_itd_device_group.rb +145 -0
  301. data/tests/test_itd_device_group_node.rb +199 -0
  302. data/tests/test_itd_service.rb +314 -0
  303. data/tests/test_logger.rb +43 -0
  304. data/tests/test_name_server.rb +94 -0
  305. data/tests/test_node.rb +50 -0
  306. data/tests/test_node_ext.rb +406 -0
  307. data/tests/test_node_util.rb +119 -0
  308. data/tests/test_ntp_auth_key.rb +77 -0
  309. data/tests/test_ntp_config.rb +100 -0
  310. data/tests/test_ntp_server.rb +146 -0
  311. data/tests/test_nxapi.rb +236 -0
  312. data/tests/test_object_group.rb +122 -0
  313. data/tests/test_overlay_global.rb +108 -0
  314. data/tests/test_pim.rb +203 -0
  315. data/tests/test_pim_group_list.rb +147 -0
  316. data/tests/test_pim_rp_address.rb +155 -0
  317. data/tests/test_platform.rb +254 -0
  318. data/tests/test_portchannel_global.rb +322 -0
  319. data/tests/test_radius_global.rb +108 -0
  320. data/tests/test_radius_server.rb +377 -0
  321. data/tests/test_radius_server_group.rb +151 -0
  322. data/tests/test_route_map.rb +1479 -0
  323. data/tests/test_router_bgp.rb +1325 -0
  324. data/tests/test_router_ospf.rb +56 -0
  325. data/tests/test_router_ospf_area.rb +433 -0
  326. data/tests/test_router_ospf_area_vlink.rb +298 -0
  327. data/tests/test_router_ospf_vrf.rb +690 -0
  328. data/tests/test_snmp_notification_receiver.rb +169 -0
  329. data/tests/test_snmpcommunity.rb +422 -0
  330. data/tests/test_snmpgroup.rb +71 -0
  331. data/tests/test_snmpnotification.rb +91 -0
  332. data/tests/test_snmpserver.rb +251 -0
  333. data/tests/test_snmpuser.rb +666 -0
  334. data/tests/test_span_session.rb +155 -0
  335. data/tests/test_stp_global.rb +575 -0
  336. data/tests/test_syslog_facility.rb +80 -0
  337. data/tests/test_syslog_server.rb +119 -0
  338. data/tests/test_syslog_settings.rb +123 -0
  339. data/tests/test_tacacs_global.rb +109 -0
  340. data/tests/test_tacacs_server.rb +436 -0
  341. data/tests/test_tacacs_server_group.rb +434 -0
  342. data/tests/test_tacacs_server_host.rb +427 -0
  343. data/tests/test_upgrade.rb +105 -0
  344. data/tests/test_vdc.rb +64 -0
  345. data/tests/test_vlan.rb +386 -0
  346. data/tests/test_vlan_private.rb +656 -0
  347. data/tests/test_vpc.rb +548 -0
  348. data/tests/test_vrf.rb +248 -0
  349. data/tests/test_vrf_af.rb +288 -0
  350. data/tests/test_vtp.rb +278 -0
  351. data/tests/test_vxlan_vtep.rb +327 -0
  352. data/tests/test_vxlan_vtep_vni.rb +326 -0
  353. data/tests/test_yang.rb +369 -0
  354. data/tests/test_yum.rb +109 -0
  355. data/tests/upgrade_info.yaml.example +3 -0
  356. data/tests/yum_package.yaml +94 -0
  357. metadata +534 -0
@@ -0,0 +1,521 @@
1
+ # Develoment Best Practices for cisco_node_utils APIs.
2
+
3
+ * [Overview](#overview)
4
+ * [YAML Development Best Practices](#ydbp)
5
+ * [Common Object Development Best Practices](#odbp)
6
+ * [MiniTest Development Best Practices](#mdbp)
7
+
8
+ ## <a name="overview">Overview</a>
9
+
10
+ This document is intended to assist in developing cisco_node_utils API's that are consistent with current best practices.
11
+
12
+
13
+ ## <a name="ydbp">YAML Development Best Practices</a>
14
+
15
+ * [Y1](#yaml1): One feature per YAML file
16
+ * [Y2](#yaml2): All attribute entries must be kept in alphabetical order.
17
+ * [Y3](#yaml3): Use *regexp* anchors where needed for CLI `get_context` and `get_value` entries.
18
+ * [Y4](#yaml4): Avoid nested optional matches.
19
+ * [Y5](#yaml5): Use the `_template` feature when getting/setting the same property value at multiple levels.
20
+ * [Y6](#yaml6): When possible include a `default_value` that represents the system default value.
21
+ * [Y7](#yaml7): When possible, use the same `get_command` for all properties and document any anomalies.
22
+ * [Y8](#yaml8): Use Key-value wildcards instead of Printf-style wildcards.
23
+ * [Y9](#yaml9): Selection of `show` commands for `get_command`.
24
+ * [Y10](#yaml10): Use `true` and `false` for boolean values.
25
+ * [Y11](#yaml11): Use YAML anchors and aliases to avoid redundant entries.
26
+ * [Y12](#yaml12): Use `_exclude` to return `nil` for unsupported properties.
27
+
28
+ ## <a name="odbp">Common Object Development Best Practices</a>
29
+
30
+ * [CO1](#co1): Features that can be configured under the global and non-global vrfs need to account for this in the object design.
31
+ * [CO2](#co2): Make use of the equality operator allowing proper `instance1 == instance2` checks in the minitests.
32
+ * [CO3](#co3): Use `''` rather than `nil` to represent "property is absent entirely"
33
+ * [CO4](#co4): Make sure all new properties have a `getter`, `setter` and `default_getter` method.
34
+ * [CO5](#co5): Use singleton-like design for resources that cannot have multiple instances.
35
+ * [CO6](#co6): Implement a meaningful `to_s` method
36
+
37
+ ## <a name="mdbp">MiniTest Development Best Practices</a>
38
+
39
+ * [MT1](#mt1): Ensure that **all new API's** have minitest coverage.
40
+ * [MT2](#mt2): Use appropriate `assert_foo` and `refute_foo` statements rather than `assert_equal`.
41
+ * [MT3](#mt3): Do not hardcode interface names.
42
+ * [MT4](#mt4): Make use of the `config` helper method for device configuration instead of `@device.cmd`.
43
+ * [MT5](#mt5): Make use of the `assert_show_match` and `refute_show_match` helper methods to validate expected outcomes in the CLI instead of `@device.cmd("show...")`.
44
+ * [MT6](#mt6): Unsupported properties must include negative test cases.
45
+
46
+
47
+ ## YAML Best Practices:
48
+
49
+ ### <a name="yaml1">Y1: One feature per YAML file
50
+
51
+ Each YAML file should define a single 'feature' (a closely related set of configuration properties). Don't create "one YAML file to rule them all".
52
+
53
+ ### <a name="yaml2">Y2: All attribute entries must be kept in alphabetical order.
54
+
55
+ All attribute entries in a given YAML file must be kept in alphabetical order. As YAML permits duplicate entries (in which case the last entry overrides any earlier entries), keeping a consistent order helps to prevent accidentally introducing such duplication.
56
+
57
+ This rule is enforced by the `Cisco::CommandReference` class itself - it will raise an exception if it detects any out-of-order entries.
58
+
59
+ ### <a name="yaml3">Y3: Use *regexp* anchors where needed for CLI `get_context` and `get_value` entries.
60
+
61
+ By default, CLI clients assume that `get_context` and `get_value` are to be treated as Regexps, and implicitly add regexp anchors and case-insensitivity (i.e., a `get_value` of `'router bgp 100'` becomes the regexp `/^router bgp 100$/i`). If you want to explicitly specify a regexp (perhaps because the default behavior does not meet your needs for a specific property), be sure to add the `^` and `$` anchors to ensure you match the correct feature information in the `show` output and do not unexpectedly match similar but undesired CLI strings.
62
+
63
+ ```yaml
64
+ # syslog_settings.yaml
65
+ timestamp:
66
+ get_command: "show running-config all | include '^logging timestamp'"
67
+ get_value: 'logging timestamp (.*)'
68
+ # this is equivalent to:
69
+ # get_value: '/^logging timestamp (.*)$/'
70
+ set_value: '<state> logging timestamp <units>'
71
+ default_value: 'seconds'
72
+ ```
73
+
74
+ ### <a name="yaml4">Y4: Avoid nested optional matches.
75
+
76
+ Regexps containing optional match strings inside other match strings become
77
+ complex to work with and difficult to maintain.
78
+
79
+ One case where this may crop up is in trying to match both affirmative and
80
+ negative variants of a config command:
81
+
82
+ ```yaml
83
+ get_context: ['interface <name>']
84
+ get_value: '((no )?switchport)'
85
+
86
+ get_value: '(no)? ?ip tacacs source-interface ?(\S+)?'
87
+ ```
88
+
89
+ Instead, match the affirmative form of a command and treat its absence as
90
+ confirmation of the negative form:
91
+
92
+ ```yaml
93
+ get_context: ['interface <name>']
94
+ get_value: 'switchport'
95
+
96
+ get_value: 'tacacs-server source-interface (\S+)'
97
+ ```
98
+
99
+ ### <a name="yaml5">Y5: Use the `_template` feature when getting/setting the same property value at multiple levels.
100
+
101
+ Using the template below, `auto_cost` and `default_metric` can be set under `router ospf foo` and `router ospf foo; vrf blue`.
102
+
103
+ ```yaml
104
+ # ospf.yaml
105
+ _template:
106
+ get_command: "show running ospf all"
107
+ context:
108
+ - 'router ospf <name>'
109
+ - '(?)vrf <vrf>'
110
+
111
+ auto_cost:
112
+ get_value: 'auto-cost reference-bandwidth (\d+)\s*(\S+)?'
113
+ set_value: "auto-cost reference-bandwidth <cost> <type>"
114
+ default_value: [40, "Gbps"]
115
+
116
+ default_metric:
117
+ get_value: 'default-metric (\d+)?'
118
+ set_value: "<state> default-metric <metric>"
119
+ default_value: 0
120
+ ```
121
+
122
+ ### <a name="yaml6">Y6: When possible include a `default_value` that represents the system default value.
123
+
124
+ Please make sure to specify a `default_value` and document properties that don't have a system default. System defaults may differ between cisco platforms making it important to define for lookup in the cisco_node_utils common object methods.
125
+
126
+
127
+ Default value for `message_digest_alg_type` is `md5`
128
+
129
+ ```yaml
130
+ message_digest_alg_type:
131
+ get_command: 'show running interface all'
132
+ get_context: 'interface <name>'
133
+ get_value: '/^\s*ip ospf message-digest-key \d+ (\S+)/'
134
+ default_value: 'md5'
135
+ ```
136
+
137
+ **NOTE1: Use strings rather then symbols when applicable**.
138
+
139
+ If the `default_value` differs between cisco platforms, use per-API or per-platform keys in the YAML as needed. For example, if the default value on all platforms except the N9k is `md5` then you might do something like this:
140
+
141
+ ```yaml
142
+ message_digest_alg_type:
143
+ get_command: 'show running interface all'
144
+ get_context: 'interface <name>'
145
+ get_value: '/^\s*ip ospf message-digest-key \d+ (\S+)/'
146
+ N9k:
147
+ default_value: 'sha2'
148
+ else:
149
+ default_value: 'md5'
150
+ ```
151
+
152
+ See [README_YAML](../lib/cisco_node_utils/cmd_ref/README_YAML.md) for more details about this advanced feature.
153
+
154
+ ### <a name="yaml7">Y7: When possible, use the same `get_command` for all properties and document any anomalies.
155
+
156
+ All properties below use the `show run tacacs all` command except `directed_request` which is documented.
157
+
158
+ ```yaml
159
+ # tacacs_server.yaml
160
+ _template:
161
+ get_command: "show run tacacs all"
162
+
163
+ deadtime:
164
+ get_value: '/^tacacs-server deadtime\s+(\d+)/'
165
+ set_value: "<state> tacacs-server deadtime <time>"
166
+ default_value: 0
167
+
168
+ directed_request:
169
+ # oddly, directed request must be retrieved from aaa output
170
+ get_command: "show running aaa all"
171
+ get_value: '/(?:no)?\s*tacacs-server directed-request/'
172
+ set_value: "<state> tacacs-server directed-request"
173
+ default_value: false
174
+
175
+ encryption_type:
176
+ get_value: '/^tacacs-server key (\d+)\s+(\S+)/'
177
+ default_value: 0
178
+
179
+ encryption_password:
180
+ get_value: '/^tacacs-server key (\d+)\s+(\S+)/'
181
+ default_value: ""
182
+ ```
183
+
184
+ ### <a name="yaml8">Y8: Use Key-value wildcards instead of Printf-style wildcards.
185
+
186
+ Key-value wildcards are moderately more complex to implement than Printf-style wildcards but they are more readable in the Ruby code and are flexible enough to handle significant platform differences in CLI. Key-value wildcards are therefore the recommended approach for new development.
187
+
188
+ **Key-value wildcards**
189
+
190
+ ```yaml
191
+ get_value: "<state> log-adjacency-changes <type>"
192
+ ```
193
+
194
+ This following approach is quick to implement and concise, but less flexible - in particular it cannot handle a case where different platforms take parameters in a different order - and less readable in the ruby code.
195
+
196
+ **Printf-style wildcards**
197
+
198
+ ```yaml
199
+ get_value: "%s log-adjacency-changes %s"
200
+ ```
201
+
202
+ ### <a name="yaml9">Y9: Selection of `show` commands for `get_command`.
203
+
204
+ The following commands should be preferred over `show [feature]` commands since not all `show [feature]` commands behave in the same manner across cisco platforms.
205
+
206
+ * `show running [feature] all` if available.
207
+ * `show running all` if `show running [feature] all` is *not* available.
208
+
209
+ ### <a name="yaml10">Y10: Use `true` and `false` for boolean values.
210
+
211
+ YAML allows various synonyms for `true` and `false` such as `yes` and `no`, but for consistency and readability (especially to users more familiar with Ruby than with YAML), we recommend using `true` and `false` rather than any of their synonyms.
212
+
213
+ ### <a name="yaml11">Y11: Use YAML anchors and aliases to avoid redundant entries.
214
+
215
+ Use the standard YAML functionality of [node anchors](http://www.yaml.org/spec/1.2/spec.html#id2785586) and [node aliases](http://www.yaml.org/spec/1.2/spec.html#id2786196) to avoid redundant entries. In other words, instead of:
216
+
217
+ ```yaml
218
+ vn_segment_vlan_based:
219
+ # MT-lite only
220
+ N3k:
221
+ kind: boolean
222
+ config_get: 'show running section feature'
223
+ config_get_token: '/^feature vn-segment-vlan-based$/'
224
+ config_set: 'feature vn-segment-vlan-based'
225
+ default_value: false
226
+ N9k:
227
+ # same as N3k
228
+ kind: boolean
229
+ config_get: 'show running section feature'
230
+ config_get_token: '/^feature vn-segment-vlan-based$/'
231
+ config_set: 'feature vn-segment-vlan-based'
232
+ default_value: false
233
+ ```
234
+
235
+ instead you can do:
236
+
237
+ ```yaml
238
+ vn_segment_vlan_based:
239
+ # MT-lite only
240
+ N3k: &vn_segment_vlan_based_mt_lite
241
+ kind: boolean
242
+ config_get: 'show running section feature'
243
+ config_get_token: '/^feature vn-segment-vlan-based$/'
244
+ config_set: 'feature vn-segment-vlan-based'
245
+ default_value: false
246
+ N9k: *vn_segment_vlan_based_mt_lite
247
+ ```
248
+
249
+ ### <a name="yaml12">Y12: Use `_exclude` to return `nil` for unsupported properties.
250
+
251
+ Some properties are only applicable to specific platforms. Rather than using `default_only` to specify an 'unconfigured' default like `''` or `false`, it is more accurate to return `nil` for a property that is not applicable at all. By returning `nil`, the property will not even appear in commands like `puppet resource`, which is the desired outcome.
252
+
253
+ Rather than specifying `default_only: nil`, the most straightforward and self-evident way to mark a property as unsupported is to use the `_exclude: [my_platform]` YAML tag. See [README_YAML.md](../lib/cisco_node_utils/cmd_ref/README_YAML.md#_exclude) for more details about the `_exclude` tag.
254
+
255
+ ## Common Object Best Practices:
256
+
257
+ ### <a name="co1">CO1: Features that can be configured under the global and non-global vrfs need to account for this in the object design.
258
+
259
+ Many cisco features can be configured under the default or global vrf and also under *n* number of non-default vrfs.
260
+
261
+ The following `initialize` and `self.vrfs` methods account for configuration under `default` and `non-default vrfs`.
262
+
263
+ ```ruby
264
+ def initialize(router, name, instantiate=true)
265
+ fail TypeError if router.nil?
266
+ fail TypeError if name.nil?
267
+ fail ArgumentError unless router.length > 0
268
+ fail ArgumentError unless name.length > 0
269
+ @router = router
270
+ @name = name
271
+ @parent = {}
272
+ if @name == 'default'
273
+ @get_args = @set_args = { name: @router }
274
+ else
275
+ @get_args = @set_args = { name: @router, vrf: @name }
276
+ end
277
+
278
+ create if instantiate
279
+ end
280
+
281
+ # Create a hash of all router ospf vrf instances
282
+ def self.vrfs
283
+ hash_final = {}
284
+ RouterOspf.routers.each do |instance|
285
+ name = instance[0]
286
+ vrf_ids = config_get('ospf', 'vrf', name: name)
287
+ hash_tmp = { name =>
288
+ { 'default' => RouterOspfVrf.new(name, 'default', false) } }
289
+ unless vrf_ids.nil?
290
+ vrf_ids.each do |vrf|
291
+ hash_tmp[name][vrf] = RouterOspfVrf.new(name, vrf, false)
292
+ end
293
+ end
294
+ hash_final.merge!(hash_tmp)
295
+ end
296
+ hash_final
297
+ end
298
+ ```
299
+
300
+ ### <a name="co2">CO2: Make use of the equality operator allowing proper `instance1 == instance2` checks in the minitests.
301
+
302
+ Having this logic defined in the common object lets the minitest easily check the specific instances.
303
+
304
+ The built-in equality operator `==` returns true only if they are the same instance object. The `==` method below is used to override the built-in equality operator and return true even if they are different objects referring to the same configuration on the node.
305
+
306
+ ```ruby
307
+ def ==(other)
308
+ (name == other.name) && (vrf == other.vrf)
309
+ end
310
+ ```
311
+
312
+ Example Usage:
313
+
314
+ ```ruby
315
+ def test_dnsdomain_create_destroy_multiple
316
+ id1 = 'aoeu.com'
317
+ id2 = 'asdf.com'
318
+ refute_includes(Cisco::DnsDomain.dnsdomains, id1)
319
+ refute_includes(Cisco::DnsDomain.dnsdomains, id2)
320
+
321
+ ns1 = Cisco::DnsDomain.new(id1)
322
+ ns2 = Cisco::DnsDomain.new(id2)
323
+ assert_includes(Cisco::DnsDomain.dnsdomains, id1)
324
+ assert_includes(Cisco::DnsDomain.dnsdomains, id2)
325
+ assert_equal(Cisco::DnsDomain.dnsdomains[id1], ns1)
326
+ assert_equal(Cisco::DnsDomain.dnsdomains[id2], ns2)
327
+
328
+ ns1.destroy
329
+ refute_includes(Cisco::DnsDomain.dnsdomains, id1)
330
+ assert_includes(Cisco::DnsDomain.dnsdomains, id2)
331
+ ns2.destroy
332
+ refute_includes(Cisco::DnsDomain.dnsdomains, id2)
333
+ end
334
+ ```
335
+ ### <a name="co3">CO3: Use `''` rather than `nil` to represent "property is absent entirely"
336
+
337
+ Our convention is to let `''` represent 'not configured at all' rather than `nil`. For example, `interface.rb`:
338
+
339
+ ```ruby
340
+ def vrf
341
+ vrf = config_get('interface', 'vrf', @name)
342
+ return '' if vrf.nil?
343
+ vrf.shift.strip
344
+ end
345
+
346
+ def vrf=(vrf)
347
+ fail TypeError unless vrf.is_a?(String)
348
+ if vrf.empty?
349
+ config_set('interface', 'vrf', @name, 'no', '')
350
+ else
351
+ config_set('interface', 'vrf', @name, '', vrf)
352
+ end
353
+ ```
354
+
355
+ However, if a property has a default value (it is never truly 'removed'), then we should do this instead:
356
+
357
+ ```ruby
358
+ def access_vlan
359
+ vlan = config_get('interface', 'access_vlan', @name)
360
+ return default_access_vlan if vlan.nil?
361
+ vlan.shift.to_i
362
+ end
363
+
364
+ def access_vlan=(vlan)
365
+ config_set('interface', 'access_vlan', @name, vlan)
366
+ ```
367
+
368
+ ### <a name="co4">CO4: Make sure all new properties have a `getter`, `setter` and `default_getter` method.
369
+
370
+ In order to have a complete set of api's for each property it is important that all properties have a `getter`, `setter` and `default_getter` method.
371
+
372
+ This can be seen in the following `router_id` property.
373
+
374
+ ```ruby
375
+ # Getter Method
376
+ def router_id
377
+ match = config_get('ospf', 'router_id', @get_args)
378
+ match.nil? ? default_router_id : match.first
379
+ end
380
+
381
+ # Setter Method
382
+ def router_id=(router_id)
383
+ if router_id == default_router_id
384
+ @set_args[:state] = 'no'
385
+ @set_args[:router_id] = ''
386
+ else
387
+ @set_args[:state] = ''
388
+ @set_args[:router_id] = router_id
389
+ end
390
+
391
+ config_set('ospf', 'router_id', @set_args)
392
+ delete_set_args_keys([:state, :router_id])
393
+ end
394
+
395
+ # Default Getter Method
396
+ def default_router_id
397
+ config_get_default('ospf', 'router_id')
398
+ end
399
+ ```
400
+
401
+ ### <a name="co5">CO5: Use singleton-like design for resources that cannot have multiple instances.
402
+
403
+ See [TacacsServer](../lib/cisco_node_utils/tacacs_server.rb) and [SnmpServer](../lib/cisco_node_utils/snmpserver.rb) for examples.
404
+
405
+ ### <a name="co6">CO6: Implement a meaningful `to_s` method
406
+
407
+ Request errors generated by a `NodeUtil` subclass calling `config_get` or `config_set` will automatically prepend the output of the class's `to_s` method. The default output of this method is not especially helpful as it just identifies the class name:
408
+
409
+ ```
410
+ Cisco::CliError: [#<Cisco::Bgp:0x007f1b3b7af5a0>] The command 'foobar shutdown' was rejected with error:
411
+ ...
412
+ ```
413
+
414
+ But by implementing the `to_s` method:
415
+
416
+ ```ruby
417
+ module Cisco
418
+ # RouterBgp - node utility class for BGP general config management
419
+ class RouterBgp < NodeUtil
420
+ attr_reader :asnum, :vrf
421
+ ...
422
+ def to_s
423
+ "BGP #{asnum} VRF '#{vrf}'"
424
+ end
425
+ ```
426
+
427
+ The error output can now clearly identify the instance that failed:
428
+
429
+ ```
430
+ Cisco::CliError: [BGP 100 VRF 'red'] The command 'foobar shutdown' was rejected with error:
431
+ ...
432
+ ```
433
+
434
+ ## MiniTest Best Practices:
435
+
436
+ ### <a name="mt1">MT1: Ensure that *all new API's* have minitest coverage.
437
+
438
+ Running minitest will automatically produce code coverage results using the [SimpleCov](http://www.rubydoc.info/gems/simplecov) Gem:
439
+
440
+ ```
441
+ test_interface:
442
+ 39 runs, 316 assertions, 0 failures, 0 errors, 2 skips
443
+ Coverage report generated for MiniTest to cisco-network-node-utils/coverage. 602 / 814 LOC (73.96%) covered.
444
+ ```
445
+
446
+ If you are adding new APIs, after running the tests, you should inspect the coverage results (open `coverage/index.html` with a web browser) to ensure that your new APIs are being exercised appropriately by your new tests.
447
+
448
+ ### <a name="mt2">MT2: Use appropriate `assert_foo` and `refute_foo` statements rather than `assert_equal`.
449
+
450
+
451
+ Minitest has a bunch of different test methods that are more specific than assert_equal. See [test methods](http://docs.ruby-lang.org/en/2.1.0/MiniTest/Assertions.html) for a complete list, but here are some general guidelines:
452
+
453
+ | Instead of ... | Use ... |
454
+ | ------------------------------|:-----------------:|
455
+ | assert_equal(true, foo.bar?) | assert(foo.bar?) |
456
+ | assert_equal(false, foo.bar?) | refute(foo.bar?) |
457
+ | assert_equal(true, foo.nil?) | assert_nil(foo) |
458
+ | assert_equal(false, foo.nil?) | refute_nil(foo) |
459
+ | assert_equal(true, foo.empty?)| assert_empty(foo) |
460
+
461
+ The more specific assertions also produce more helpful failure messages if something is wrong.
462
+
463
+ ### <a name="mt3">MT3: Do not hardcode interface names.
464
+
465
+ Rather then hardcode an interface name that may or may not exist, instead use the `interfaces[]` array.
466
+
467
+ ```ruby
468
+ def create_interface(ifname=interfaces[0])
469
+ @default_show_command = show_cmd(ifname)
470
+ Interface.new(ifname)
471
+ end
472
+ ```
473
+
474
+ If additional interfaces are needed array index `1` and `2` may be used.
475
+
476
+ ### <a name="mt4">MT4: Make use of the `config` helper method for device configuration instead of `@device.cmd`.
477
+
478
+ For conveninence the `config` helper method has been provided for device configuration within the minitests.
479
+
480
+ ```ruby
481
+ config('no feature ospf')
482
+ ```
483
+
484
+ ```ruby
485
+ config('feature ospf'; 'router ospf green')
486
+ ```
487
+
488
+ ### <a name="mt5">MT5: Make use of the `assert_show_match` and `refute_show_match` helper methods to validate expected outcomes in the CLI instead of `@device.cmd("show...")`.
489
+
490
+ We have a very common pattern in minitest where we execute some show command over the telnet connection, match it against some regexp pattern, and succeed or fail based on the result. Helper methods `assert_show_match` and `refute_show_match` support this pattern.
491
+
492
+ ```ruby
493
+ assert_show_match(command: 'show run all | no-more',
494
+ pattern: /interface port-channel 1/,
495
+ msg: 'port-channel is not present but it should be')
496
+ ```
497
+
498
+ If your `command` and/or `pattern` are the same throughout a test case or throughout a test suite, you can set the test case instance variables `@default_show_command` and/or `@default_output_pattern` which serve as defaults for these parameters:
499
+
500
+ ```ruby
501
+ @default_show_command = 'show run interface all | include "interface" | no-more'
502
+ assert_output_match(pattern: /interface port-channel 10/)
503
+ refute_output_match(pattern: /interface port-channel 11/)
504
+ refute_output_match(pattern: /interface port-channel 12/)
505
+ assert_output_match(pattern: /interface port-channel 13/)
506
+ ```
507
+
508
+ ### <a name="mt6">MT6: Unsupported properties must include negative test cases.
509
+
510
+ Some properties are only applicable to a particular platform and are unsupported on other platforms. To ensure that this lack of support is properly validated, at least one of the test cases for this property should include tests of the getter and default methods and a negative test for the setter method. If you followed [Y11](#yaml11), this means checking that the getter and default methods return `nil` and the setter method raises a `Cisco::UnsupportedError`:
511
+
512
+ ```ruby
513
+ def test_foo_bar
514
+ if platform == :platform_not_supporting_bar
515
+ assert_nil(foo.bar)
516
+ assert_nil(foo.default_bar)
517
+ assert_raises(Cisco::UnsupportedError) { foo.bar = baz }
518
+ else
519
+ # tests for foo.bar on a platform that supports this
520
+ ...
521
+ ```