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
@@ -34,17 +34,6 @@ class TestCmdRef < Minitest::Test
34
34
  @input_file.close!
35
35
  end
36
36
 
37
- # Extend standard Minitest error handling to report UnsupportedError as skip
38
- def capture_exceptions
39
- super do
40
- begin
41
- yield
42
- rescue Cisco::UnsupportedError => e
43
- skip(e.to_s)
44
- end
45
- end
46
- end
47
-
48
37
  def load_file(**args)
49
38
  CommandReference.new(**args, :files => [@input_file.path])
50
39
  end
@@ -57,11 +46,28 @@ class TestCmdRef < Minitest::Test
57
46
  def test_data_sanity
58
47
  # Make sure the actual YAML in our library loads for various platforms
59
48
  CommandReference.new
60
- CommandReference.new(platform: :nexus, cli: true)
61
- CommandReference.new(platform: :nexus, product: 'N9K-C9396PX', cli: true)
62
- CommandReference.new(platform: :nexus, product: 'N7K-C7010', cli: true)
63
- CommandReference.new(platform: :nexus, product: 'N3K-C3064PQ-10GE',
64
- cli: true)
49
+
50
+ CommandReference.new(platform: :nexus,
51
+ data_formats: [:nxapi_structured, :cli])
52
+
53
+ CommandReference.new(platform: :nexus,
54
+ product: 'N9K-C9396PX',
55
+ data_formats: [:nxapi_structured, :cli])
56
+
57
+ CommandReference.new(platform: :nexus,
58
+ product: 'N7K-C7010',
59
+ data_formats: [:nxapi_structured, :cli])
60
+
61
+ CommandReference.new(platform: :nexus,
62
+ product: 'N3K-C3064PQ-10GE',
63
+ data_formats: [:nxapi_structured, :cli])
64
+
65
+ CommandReference.new(platform: :ios_xr,
66
+ data_formats: [:cli])
67
+
68
+ CommandReference.new(platform: :ios_xr,
69
+ product: 'R-IOSXRV9000-CH',
70
+ data_formats: [:cli])
65
71
  end
66
72
 
67
73
  def test_load_empty_file
@@ -107,7 +113,7 @@ name:
107
113
  name:
108
114
  default_value: false
109
115
  name:
110
- config_get: 'show feature'")
116
+ get_command: 'show feature'")
111
117
  assert_raises(RuntimeError) { load_file }
112
118
  end
113
119
 
@@ -122,7 +128,7 @@ name:
122
128
  def test_load_unsupported_key
123
129
  write("
124
130
  name:
125
- config_get: 'show feature'
131
+ get_command: 'show feature'
126
132
  what_is_this: \"I don't even\"")
127
133
  assert_raises(RuntimeError) { load_file }
128
134
  end
@@ -137,86 +143,145 @@ name_a:
137
143
  end
138
144
 
139
145
  def type_check(obj, cls)
140
- assert(obj.is_a?(cls), "#{obj} should be #{cls} but is #{obj.class}")
146
+ assert(obj.is_a?(cls), "'#{obj}' type should be #{cls} but is #{obj.class}")
141
147
  end
142
148
 
143
149
  def test_load_types
144
150
  write(%q(
145
151
  name:
146
152
  default_value: true
147
- config_get: show hello
148
- config_get_token: '/hello world/'
149
- config_set: [ \"hello\", \"world\" ]
150
- test_config_get_regex: '/hello world/'
151
- test_config_result:
152
- false: RuntimeError
153
- 32: "Long VLAN name knob is not enabled"
154
- nil: ~
153
+ get_command: show hello
154
+ get_context: ['/hello/i']
155
+ get_value: '/world/'
156
+ set_context: [ "hello", "world" ]
157
+ set_value:
158
+ - "hello"
159
+ - "world"
155
160
  ))
156
161
  reference = load_file
157
162
  ref = reference.lookup('test', 'name')
158
163
  type_check(ref.default_value, TrueClass)
159
- type_check(ref.config_get, String)
160
- type_check(ref.config_get_token, Array)
161
- type_check(ref.config_get_token[0], Regexp)
162
- type_check(ref.config_set, Array)
163
- type_check(ref.test_config_get_regex, Regexp)
164
- assert_raises(IndexError) { ref.test_config_get }
165
- type_check(ref.test_config_result(false), RuntimeError.class)
166
- type_check(ref.test_config_result(32), String)
167
- type_check(ref.test_config_result('nil'), NilClass)
164
+ type_check(ref.get_command, String)
165
+ type_check(ref.get_context, Array)
166
+ type_check(ref.get_context[0], String)
167
+ type_check(ref.get_value, String)
168
+ type_check(ref.set_context, Array)
169
+ type_check(ref.set_context[0], String)
170
+ type_check(ref.set_value, Array)
171
+ type_check(ref.set_value[0], String)
172
+ assert_raises(IndexError) { ref.context }
168
173
 
169
174
  assert(ref.default_value?)
170
- assert(ref.config_get?)
171
- assert(ref.config_get_token?)
172
- assert(ref.config_set?)
175
+ assert(ref.get_command?)
176
+ assert(ref.get_context?)
177
+ assert(ref.get_value?)
178
+ assert(ref.getter?)
179
+ assert(ref.set_context?)
180
+ assert(ref.set_value?)
181
+ assert(ref.setter?)
173
182
  end
174
183
 
175
184
  def write_variants
176
185
  write("
177
186
  name:
178
187
  default_value: 'generic'
179
- cli_nexus:
188
+ nexus:
180
189
  default_value: 'NXAPI base'
181
- /N7K/:
190
+ C3064:
191
+ default_value: 'NXAPI C3064'
192
+ C3132:
193
+ default_value: 'NXAPI C3132'
194
+ C3172:
195
+ default_value: 'NXAPI C3172'
196
+ N7k:
182
197
  default_value: ~
183
- /N9K/:
198
+ N9k:
184
199
  default_value: 'NXAPI N9K'
200
+ ios_xr:
201
+ XRv9k:
202
+ default_value: ~
203
+ else:
204
+ default_value: 'gRPC base'
185
205
  ")
186
206
  end
187
207
 
188
208
  def test_load_generic
189
209
  write_variants
210
+ # Neither NXAPI nor gRPC
190
211
  reference = load_file
191
212
  assert_equal('generic', reference.lookup('test', 'name').default_value)
192
213
  end
193
214
 
194
215
  def test_load_n9k
195
216
  write_variants
196
- reference = load_file(platform: :nexus, product: 'N9K-C9396PX', cli: true)
217
+ reference = load_file(platform: :nexus,
218
+ product: 'N9K-C9396PX',
219
+ data_formats: [:nxapi_structured, :cli])
197
220
  assert_equal('NXAPI N9K', reference.lookup('test', 'name').default_value)
198
221
  end
199
222
 
200
223
  def test_load_n7k
201
224
  write_variants
202
- reference = load_file(platform: :nexus, product: 'N7K-C7010', cli: true)
225
+ reference = load_file(platform: :nexus,
226
+ product: 'N7K-C7010',
227
+ data_formats: [:nxapi_structured, :cli])
203
228
  assert_equal(nil, reference.lookup('test', 'name').default_value)
204
229
  end
205
230
 
206
- def test_load_n3k_3064
231
+ def test_load_n3k
207
232
  write_variants
208
- reference = load_file(platform: :nexus, product: 'N3K-C3064PQ-10GE',
209
- cli: true)
233
+ reference = load_file(platform: :nexus,
234
+ product: 'N3K',
235
+ data_formats: [:nxapi_structured, :cli])
210
236
  assert_equal('NXAPI base', reference.lookup('test', 'name').default_value)
211
237
  end
212
238
 
239
+ def test_load_n3k_3064
240
+ write_variants
241
+ reference = load_file(platform: :nexus,
242
+ product: 'N3K-C3064PQ-10GE',
243
+ data_formats: [:nxapi_structured, :cli])
244
+ assert_equal('NXAPI C3064', reference.lookup('test', 'name').default_value)
245
+ end
246
+
247
+ def test_load_n3k_3132
248
+ write_variants
249
+ reference = load_file(platform: :nexus,
250
+ product: 'N3K-C3132Q-40GE',
251
+ data_formats: [:nxapi_structured, :cli])
252
+ assert_equal('NXAPI C3132', reference.lookup('test', 'name').default_value)
253
+ end
254
+
255
+ def test_load_n3k_3172
256
+ write_variants
257
+ reference = load_file(platform: :nexus,
258
+ product: 'N3K-C3172PQ-10GE',
259
+ data_formats: [:nxapi_structured, :cli])
260
+ assert_equal('NXAPI C3172', reference.lookup('test', 'name').default_value)
261
+ end
262
+
263
+ def test_load_ios_xr_xrv9k
264
+ write_variants
265
+ reference = load_file(platform: :ios_xr,
266
+ product: 'R-IOSXRV9000-CH',
267
+ data_formats: [:cli])
268
+ assert_nil(reference.lookup('test', 'name').default_value)
269
+ end
270
+
271
+ def test_load_ios_xr_generic
272
+ write_variants
273
+ reference = load_file(platform: :ios_xr,
274
+ data_formats: [:cli])
275
+ assert_equal('gRPC base', reference.lookup('test', 'name').default_value)
276
+ end
277
+
213
278
  def write_exclusions
214
279
  write("
215
280
  _exclude:
216
- - /N9K/
281
+ - N9k
217
282
 
218
283
  name:
219
- _exclude: [/C30../, /C31../]
284
+ _exclude: [N3k]
220
285
  default_value: hello
221
286
 
222
287
  rank:
@@ -232,16 +297,20 @@ rank:
232
297
  # default_value is nil for an unsupported property
233
298
  assert(ref.default_value?, 'default_value? returned false')
234
299
  assert_nil(ref.default_value)
235
- refute(ref.config_get?)
236
- assert_raises(Cisco::UnsupportedError) { ref.config_get }
300
+ refute(ref.getter?)
301
+ assert_raises(Cisco::UnsupportedError) { ref.getter }
302
+ refute(ref.setter?)
303
+ assert_raises(Cisco::UnsupportedError) { ref.setter }
237
304
 
238
305
  # Because the whole file is excluded, we don't know which
239
306
  # attributes are 'valid' - so any attribute name is permitted:
240
307
  ref = reference.lookup('test', 'foobar')
241
308
  assert(ref.default_value?)
242
309
  assert_nil(ref.default_value)
243
- refute(ref.config_get?)
244
- assert_raises(Cisco::UnsupportedError) { ref.config_get }
310
+ refute(ref.getter?)
311
+ assert_raises(Cisco::UnsupportedError) { ref.getter }
312
+ refute(ref.setter?)
313
+ assert_raises(Cisco::UnsupportedError) { ref.setter }
245
314
  end
246
315
 
247
316
  def test_exclude_whole_item
@@ -252,8 +321,10 @@ rank:
252
321
  ref = reference.lookup('test', 'name')
253
322
  assert(ref.default_value?)
254
323
  assert_nil(ref.default_value)
255
- refute(ref.config_get?)
256
- assert_raises(Cisco::UnsupportedError) { ref.config_get }
324
+ refute(ref.getter?)
325
+ assert_raises(Cisco::UnsupportedError) { ref.getter }
326
+ refute(ref.setter?)
327
+ assert_raises(Cisco::UnsupportedError) { ref.setter }
257
328
  end
258
329
 
259
330
  def test_exclude_no_exclusion
@@ -264,12 +335,13 @@ rank:
264
335
  end
265
336
 
266
337
  def test_exclude_implicit
338
+ # TODO: something is hinky with this test.
267
339
  write("
268
340
  name:
269
- cli_nexus:
341
+ cli:
270
342
  default_value: 1
271
343
  ")
272
- reference = load_file(platform: 'nexus', cli: false)
344
+ reference = load_file(platform: 'nexus', data_formats: [])
273
345
  ref = reference.lookup('test', 'name')
274
346
  assert(ref.default_value?)
275
347
  assert_nil(ref.default_value)
@@ -285,27 +357,31 @@ name:
285
357
  assert(ref.default_only?)
286
358
  assert(ref.default_value?)
287
359
  assert_equal('x', ref.default_value)
288
- refute(ref.config_set?)
289
- assert_raises(Cisco::UnsupportedError) { ref.config_set }
360
+ refute(ref.getter?)
361
+ assert_raises(Cisco::UnsupportedError) { ref.getter }
362
+ refute(ref.setter?)
363
+ assert_raises(Cisco::UnsupportedError) { ref.setter }
290
364
  end
291
365
 
292
366
  def test_default_only_cleanup
293
367
  write("
294
368
  name:
295
369
  default_only: 'x'
296
- config_set: 'foo'
370
+ set_value: 'foo'
297
371
  ")
298
372
  reference = load_file
299
373
  ref = reference.lookup('test', 'name')
300
374
  assert(ref.default_only?)
301
375
  assert(ref.default_value?)
302
376
  assert_equal('x', ref.default_value)
303
- refute(ref.config_set?)
304
- assert_raises(Cisco::UnsupportedError) { ref.config_set }
377
+ refute(ref.set_value?)
378
+ assert_raises(Cisco::UnsupportedError) { ref.set_value }
379
+ refute(ref.setter?)
380
+ assert_raises(Cisco::UnsupportedError) { ref.setter }
305
381
 
306
382
  write("
307
383
  name2:
308
- config_set: 'foo'
384
+ set_value: 'foo'
309
385
  default_only: 'x'
310
386
  ")
311
387
  reference = load_file
@@ -313,17 +389,19 @@ name2:
313
389
  assert(ref.default_only?)
314
390
  assert(ref.default_value?)
315
391
  assert_equal('x', ref.default_value)
316
- refute(ref.config_set?)
317
- assert_raises(Cisco::UnsupportedError) { ref.config_set }
392
+ refute(ref.set_value?)
393
+ assert_raises(Cisco::UnsupportedError) { ref.set_value }
394
+ refute(ref.setter?)
395
+ assert_raises(Cisco::UnsupportedError) { ref.setter }
318
396
  end
319
397
 
320
398
  def test_default_only_default_value
321
399
  write("
322
400
  name:
323
401
  kind: int
324
- cli_nexus:
402
+ nexus:
325
403
  default_value: 10
326
- config_set: 'hello'
404
+ set_value: 'hello'
327
405
  default_only: 0
328
406
  ")
329
407
  reference = load_file
@@ -331,61 +409,261 @@ name:
331
409
  assert(ref.default_only?)
332
410
  assert(ref.default_value?)
333
411
  assert_equal(0, ref.default_value)
334
- refute(ref.config_set?)
335
- assert_raises(Cisco::UnsupportedError) { ref.config_set }
412
+ refute(ref.set_value?)
413
+ assert_raises(Cisco::UnsupportedError) { ref.set_value }
414
+ refute(ref.setter?)
415
+ assert_raises(Cisco::UnsupportedError) { ref.setter }
336
416
 
337
- reference = load_file(cli: true, platform: 'nexus')
417
+ reference = load_file(data_formats: [:nxapi_structured, :cli],
418
+ platform: 'nexus')
338
419
  ref = reference.lookup('test', 'name')
339
420
  refute(ref.default_only?)
340
421
  assert(ref.default_value?)
341
422
  assert_equal(10, ref.default_value)
342
- assert(ref.config_set?)
343
- assert_raises(IndexError) { ref.config_get }
423
+ assert(ref.set_value?)
424
+ assert(ref.setter?)
425
+ assert_raises(IndexError) { ref.get_value }
344
426
  end
345
427
 
346
- def test_config_get_token_hash_substitution
428
+ def test_getter_hash_substitution
347
429
  write(%q(
348
430
  name:
349
- config_get_token:
431
+ get_context:
350
432
  ['/^router ospf <name>$/',
351
- '/^vrf <vrf>$/',
352
- '/^router-id (\S+)$/']
433
+ '(?)/^vrf <vrf>$/']
434
+ get_value: '/^router-id (\S+)$/'
353
435
  test2:
354
- config_get_token:
355
- ['abc <val1> def',
356
- 'xyz <val2>']
436
+ get_context: ['(?)abc <val1> def']
437
+ get_value: 'xyz <val2>'
438
+ test3:
439
+ get_context: ['foo']
440
+ # no get_value
441
+ test4:
442
+ get_value: 'xyz <val1> <val2>'
357
443
  ))
358
444
  reference = load_file
359
445
  ref = reference.lookup('test', 'name')
360
- token = ref.config_get_token(name: 'red')
361
- assert_equal([/^router ospf red$/, /^router-id (\S+)$/],
362
- token)
363
- token = ref.config_get_token(name: 'blue', vrf: 'green')
364
- assert_equal([/^router ospf blue$/, /^vrf green$/, /^router-id (\S+)$/],
365
- token)
366
- ref = reference.lookup('test', 'test2')
367
- token = ref.config_get_token(val1: '1', val2: '2')
368
- assert_equal(['abc 1 def', 'xyz 2'], token)
369
- token = ref.config_get_token(val1: '1', extra_val: 'asdf')
370
- assert_equal(['abc 1 def'], token)
371
- token = ref.config_get_token(val2: '2')
372
- assert_equal(['xyz 2'], token)
373
- assert_raises(ArgumentError) { token = ref.config_get_token }
374
- assert_raises(ArgumentError) { token = ref.config_get_token(extra: 'x') }
375
- end
446
+ # vrf context is flagged as optional
447
+ getter = ref.getter(name: 'red')
448
+ assert_equal({
449
+ command: nil,
450
+ context: ['/^router ospf red$/'],
451
+ value: '/^router-id (\S+)$/',
452
+ data_format: :cli,
453
+ }, getter)
454
+
455
+ getter = ref.getter(name: 'blue', vrf: 'green')
456
+ assert_equal({
457
+ command: nil,
458
+ context: ['/^router ospf blue$/', '/^vrf green$/'],
459
+ value: '/^router-id (\S+)$/',
460
+ data_format: :cli,
461
+ }, getter)
462
+
463
+ # ospf name is not flagged as optional
464
+ assert_raises(ArgumentError) { ref.getter(vrf: 'green') }
376
465
 
377
- def test_config_get_token_printf_substitution
466
+ ref = reference.lookup('test', 'test2')
467
+ getter = ref.getter(val1: '1', val2: '2')
468
+ assert_equal({
469
+ command: nil,
470
+ context: ['abc 1 def'],
471
+ value: 'xyz 2',
472
+ data_format: :cli,
473
+ }, getter)
474
+
475
+ # value params are mandatory
476
+ assert_raises(ArgumentError) { ref.getter(val1: '1', extra_val: 'asdf') }
477
+
478
+ # context params are optional only if flagged!
479
+ getter = ref.getter(val2: '2')
480
+ assert_equal({
481
+ command: nil,
482
+ context: [],
483
+ value: 'xyz 2',
484
+ data_format: :cli,
485
+ }, getter)
486
+
487
+ e = assert_raises(ArgumentError) { ref.getter }
488
+ assert_equal("No value specified for 'val2' in 'xyz <val2>'", e.message)
489
+
490
+ e = assert_raises(ArgumentError) { ref.getter(extra: 'x') }
491
+ assert_equal("No value specified for 'val2' in 'xyz <val2>'", e.message)
492
+
493
+ e = assert_raises(ArgumentError) { ref.getter('x') }
494
+ assert_match(/requires keyword args/, e.message)
495
+
496
+ # No get_value and no get_command means no getter
497
+ ref = reference.lookup('test', 'test3')
498
+ refute(ref.getter?)
499
+ assert_raises(UnsupportedError) { ref.getter }
500
+ assert_raises(UnsupportedError) { ref.getter(val1: '1') }
501
+ assert_raises(UnsupportedError) { ref.getter('x') }
502
+
503
+ # Multiple keys in a single parameter
504
+ ref = reference.lookup('test', 'test4')
505
+ getter = ref.getter(val1: 1, val2: 2.2)
506
+ assert_equal({
507
+ command: nil,
508
+ context: [],
509
+ value: 'xyz 1 2.2',
510
+ data_format: :cli,
511
+ }, getter)
512
+
513
+ e = assert_raises(ArgumentError) { ref.getter }
514
+ assert_match(/No value specified for 'val1'/, e.message)
515
+ e = assert_raises(ArgumentError) { ref.getter(val1: 1) }
516
+ assert_equal("No value specified for 'val2' in 'xyz 1 <val2>'", e.message)
517
+ e = assert_raises(ArgumentError) { ref.getter(val2: 2.2) }
518
+ assert_equal("No value specified for 'val1' in 'xyz <val1> 2.2'", e.message)
519
+ end
520
+
521
+ def test_getter_printf_substitution
378
522
  write("
379
523
  name:
380
- config_get_token: ['/^interface %s$/i', '/^description (.*)/']
524
+ get_context: ['/^interface %s$/i']
525
+ get_value: '/^description (.*)/'
526
+ test3:
527
+ get_context: ['/^foo %s$/']
528
+ # no get_value
381
529
  ")
382
530
  reference = load_file
383
531
  ref = reference.lookup('test', 'name')
384
- token = ref.config_get_token('Ethernet1/1')
385
- assert_equal([%r{^interface Ethernet1/1$}i, /^description (.*)/],
386
- token)
532
+ getter = ref.getter('Ethernet1/1')
533
+ assert_equal({
534
+ command: nil,
535
+ context: ['/^interface Ethernet1/1$/i'],
536
+ value: '/^description (.*)/',
537
+ data_format: :cli,
538
+ }, getter)
387
539
  # Negative tests - wrong # of args
388
- assert_raises(ArgumentError) { ref.config_get_token }
389
- assert_raises(ArgumentError) { ref.config_get_token('eth1/1', 'foo') }
540
+ e = assert_raises(ArgumentError) { ref.getter }
541
+ assert_equal('wrong number of arguments (0 for 1)', e.message)
542
+
543
+ e = assert_raises(ArgumentError) { ref.getter('eth1/1', 'foo') }
544
+ assert_equal('wrong number of arguments (2 for 1)', e.message)
545
+
546
+ # Wrong kind of args
547
+ e = assert_raises(ArgumentError) { ref.getter(name: 'eth1/1', val: 'foo') }
548
+ assert_match(/requires positional args/, e.message)
549
+
550
+ ref = reference.lookup('test', 'test3')
551
+ refute(ref.getter?)
552
+ assert_raises(UnsupportedError) { ref.getter }
553
+ assert_raises(UnsupportedError) { ref.getter('1') }
554
+ assert_raises(UnsupportedError) { ref.getter(foo: '1') }
555
+ end
556
+
557
+ RAW_1 = {
558
+ 'name' => {
559
+ '_exclude' => ['N3k'],
560
+ 'default_value' => 'generic',
561
+ 'nexus' => {
562
+ 'default_value' => 'NXAPI base',
563
+ 'N7k' => { 'default_value' => nil },
564
+ 'N9k' => { 'default_value' => 'NXAPI N9K' },
565
+ },
566
+ 'ios_xr' => {
567
+ 'XRv9k' => { 'default_value' => nil },
568
+ 'else' => { 'default_value' => 'gRPC base' },
569
+ },
570
+ }
571
+ }
572
+
573
+ FILTERED_1_NEXUS = {
574
+ 'name' => {
575
+ 'default_value' => 'generic',
576
+ 'nexus' => { 'default_value' => 'NXAPI base' },
577
+ }
578
+ }
579
+
580
+ FILTERED_1_NEXUS_N7K = {
581
+ 'name' => {
582
+ 'default_value' => 'generic',
583
+ 'nexus' => {
584
+ 'default_value' => 'NXAPI base',
585
+ 'N7k' => { 'default_value' => nil },
586
+ },
587
+ }
588
+ }
589
+
590
+ FILTERED_1_NEXUS_N3K = {
591
+ 'name' => {}
592
+ }
593
+
594
+ RAW_2 = {
595
+ '_template' => {
596
+ 'ios_xr' => {
597
+ 'cli' => { 'get_command' => 'show inventory' },
598
+ 'set_value' => 'show inventory',
599
+ },
600
+ 'nexus' => {
601
+ 'nxapi_structured' => { get_command: 'show inventory' },
602
+ 'set_value' => 'show inventory | no-more',
603
+ },
604
+ }
605
+ }
606
+
607
+ FILTERED_2_IOS_XR = {
608
+ '_template' => {
609
+ 'ios_xr' => {
610
+ 'set_value' => 'show inventory'
611
+ }
612
+ }
613
+ }
614
+
615
+ FILTERED_2_IOS_XR_CLI = {
616
+ '_template' => {
617
+ 'ios_xr' => {
618
+ 'cli' => { 'get_command' => 'show inventory' },
619
+ 'set_value' => 'show inventory',
620
+ }
621
+ }
622
+ }
623
+
624
+ def test_filter_hash
625
+ filtered = CommandReference.filter_hash(RAW_1)
626
+ assert_equal({ 'name' => { 'default_value' => 'generic' } }, filtered)
627
+
628
+ filtered = CommandReference.filter_hash(RAW_1,
629
+ platform: :nexus)
630
+ assert_equal(FILTERED_1_NEXUS, filtered)
631
+
632
+ filtered = CommandReference.filter_hash(RAW_1,
633
+ platform: :nexus,
634
+ product_id: 'N7K-C7010')
635
+ assert_equal(FILTERED_1_NEXUS_N7K, filtered)
636
+
637
+ filtered = CommandReference.filter_hash(RAW_1,
638
+ platform: :nexus,
639
+ product_id: 'N3K-C3172PQ')
640
+ assert_equal(FILTERED_1_NEXUS_N3K, filtered)
641
+
642
+ filtered = CommandReference.filter_hash(RAW_2)
643
+ assert_equal({ '_template' => {} }, filtered)
644
+
645
+ filtered = CommandReference.filter_hash(RAW_2,
646
+ platform: :ios_xr)
647
+ assert_equal(FILTERED_2_IOS_XR, filtered)
648
+
649
+ filtered = CommandReference.filter_hash(RAW_2,
650
+ platform: :ios_xr,
651
+ data_formats: [:cli])
652
+ assert_equal(FILTERED_2_IOS_XR_CLI, filtered)
653
+ end
654
+
655
+ def test_hash_merge_no_template
656
+ merged = CommandReference.hash_merge(FILTERED_1_NEXUS)
657
+ assert_equal({ 'default_value' => 'NXAPI base' }, merged)
658
+
659
+ merged = CommandReference.hash_merge(FILTERED_1_NEXUS_N7K)
660
+ assert_equal({ 'default_value' => nil }, merged)
661
+
662
+ merged = CommandReference.hash_merge(FILTERED_2_IOS_XR)
663
+ assert_equal({ 'set_value' => 'show inventory' }, merged)
664
+
665
+ merged = CommandReference.hash_merge(FILTERED_2_IOS_XR_CLI)
666
+ assert_equal({ 'set_value' => 'show inventory',
667
+ 'get_command' => 'show inventory' }, merged)
390
668
  end
391
669
  end