cisco_node_utils 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +66 -0
  4. data/Gemfile +1 -0
  5. data/README.md +44 -43
  6. data/bin/.rubocop.yml +18 -0
  7. data/bin/show_running_yang.rb +233 -0
  8. data/cisco_node_utils.gemspec +1 -1
  9. data/docs/README-maintainers.md +1 -0
  10. data/docs/README-utilities.md +14 -0
  11. data/lib/.rubocop.yml +1 -1
  12. data/lib/cisco_node_utils/aaa_authentication_login_service.rb +8 -3
  13. data/lib/cisco_node_utils/aaa_authorization_service.rb +6 -0
  14. data/lib/cisco_node_utils/bfd_global.rb +300 -0
  15. data/lib/cisco_node_utils/bgp.rb +6 -4
  16. data/lib/cisco_node_utils/bgp_af.rb +2 -0
  17. data/lib/cisco_node_utils/bgp_neighbor.rb +14 -0
  18. data/lib/cisco_node_utils/bgp_neighbor_af.rb +4 -1
  19. data/lib/cisco_node_utils/cisco_cmn_utils.rb +126 -0
  20. data/lib/cisco_node_utils/client/client.rb +6 -2
  21. data/lib/cisco_node_utils/client/grpc/client.rb +120 -36
  22. data/lib/cisco_node_utils/client/nxapi/client.rb +6 -2
  23. data/lib/cisco_node_utils/cmd_ref/DEPRECATED.yaml +118 -0
  24. data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +14 -0
  25. data/lib/cisco_node_utils/cmd_ref/bfd_global.yaml +117 -0
  26. data/lib/cisco_node_utils/cmd_ref/bgp.yaml +7 -7
  27. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor.yaml +7 -0
  28. data/lib/cisco_node_utils/cmd_ref/dhcp_relay_global.yaml +125 -0
  29. data/lib/cisco_node_utils/cmd_ref/feature.yaml +10 -0
  30. data/lib/cisco_node_utils/cmd_ref/interface.yaml +141 -49
  31. data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +44 -0
  32. data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +6 -0
  33. data/lib/cisco_node_utils/cmd_ref/ospf.yaml +6 -0
  34. data/lib/cisco_node_utils/cmd_ref/ospf_area.yaml +91 -0
  35. data/lib/cisco_node_utils/cmd_ref/ospf_area_vlink.yaml +88 -0
  36. data/lib/cisco_node_utils/cmd_ref/overlay_global.yaml +0 -3
  37. data/lib/cisco_node_utils/cmd_ref/show_version.yaml +3 -3
  38. data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +39 -15
  39. data/lib/cisco_node_utils/cmd_ref/snmp_notification_receiver.yaml +43 -21
  40. data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +48 -19
  41. data/lib/cisco_node_utils/cmd_ref/snmp_user.yaml +0 -0
  42. data/lib/cisco_node_utils/cmd_ref/tacacs_global.yaml +30 -0
  43. data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +18 -6
  44. data/lib/cisco_node_utils/cmd_ref/vdc.yaml +4 -0
  45. data/lib/cisco_node_utils/cmd_ref/virtual_service.yaml +1 -0
  46. data/lib/cisco_node_utils/cmd_ref/vlan.yaml +23 -10
  47. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +8 -2
  48. data/lib/cisco_node_utils/cmd_ref/yang.yaml +7 -0
  49. data/lib/cisco_node_utils/cmd_ref/yum.yaml +10 -1
  50. data/lib/cisco_node_utils/constants.rb +8 -1
  51. data/lib/cisco_node_utils/dhcp_relay_global.rb +302 -0
  52. data/lib/cisco_node_utils/exceptions.rb +29 -0
  53. data/lib/cisco_node_utils/feature.rb +28 -0
  54. data/lib/cisco_node_utils/interface.rb +493 -402
  55. data/lib/cisco_node_utils/interface_DEPRECATED.rb +513 -0
  56. data/lib/cisco_node_utils/interface_ospf.rb +126 -0
  57. data/lib/cisco_node_utils/interface_portchannel.rb +16 -0
  58. data/lib/cisco_node_utils/logger.rb +3 -0
  59. data/lib/cisco_node_utils/node.rb +29 -1
  60. data/lib/cisco_node_utils/overlay_global.rb +1 -12
  61. data/lib/cisco_node_utils/pim.rb +1 -0
  62. data/lib/cisco_node_utils/pim_group_list.rb +1 -0
  63. data/lib/cisco_node_utils/pim_rp_address.rb +1 -0
  64. data/lib/cisco_node_utils/platform.rb +9 -2
  65. data/lib/cisco_node_utils/router_ospf.rb +1 -1
  66. data/lib/cisco_node_utils/router_ospf_area.rb +416 -0
  67. data/lib/cisco_node_utils/router_ospf_area_vlink.rb +313 -0
  68. data/lib/cisco_node_utils/router_ospf_vrf.rb +17 -0
  69. data/lib/cisco_node_utils/snmp_notification_receiver.rb +27 -9
  70. data/lib/cisco_node_utils/snmpcommunity.rb +34 -8
  71. data/lib/cisco_node_utils/snmpserver.rb +4 -4
  72. data/lib/cisco_node_utils/snmpuser.rb +0 -0
  73. data/lib/cisco_node_utils/tacacs_global.rb +102 -0
  74. data/lib/cisco_node_utils/tacacs_server.rb +8 -7
  75. data/lib/cisco_node_utils/vdc.rb +25 -7
  76. data/lib/cisco_node_utils/version.rb +1 -1
  77. data/lib/cisco_node_utils/vlan.rb +30 -56
  78. data/lib/cisco_node_utils/vlan_DEPRECATED.rb +108 -0
  79. data/lib/cisco_node_utils/yang.rb +160 -0
  80. data/lib/cisco_node_utils/yum.rb +25 -32
  81. data/tests/.rubocop.yml +3 -0
  82. data/tests/ciscotest.rb +136 -19
  83. data/tests/cmd_config_invalid.yaml +1 -1
  84. data/tests/noop.rb +7 -0
  85. data/tests/tacacs_server.yaml.example +6 -0
  86. data/tests/test_aaa_authentication_login.rb +24 -1
  87. data/tests/test_aaa_authentication_login_service.rb +9 -16
  88. data/tests/test_aaa_authorization_service.rb +111 -84
  89. data/tests/test_bfd_global.rb +278 -0
  90. data/tests/test_bgp_neighbor.rb +20 -0
  91. data/tests/test_bridge_domain_vni.rb +2 -9
  92. data/tests/test_cmn_utils.rb +76 -0
  93. data/tests/test_dhcp_relay_global.rb +284 -0
  94. data/tests/test_dns_domain.rb +4 -4
  95. data/tests/test_domain_name.rb +2 -2
  96. data/tests/test_encapsulation.rb +2 -4
  97. data/tests/test_evpn_vni.rb +14 -7
  98. data/tests/test_fabricpath_global.rb +12 -13
  99. data/tests/test_feature.rb +35 -17
  100. data/tests/test_interface.rb +352 -127
  101. data/tests/test_interface_bdi.rb +2 -2
  102. data/tests/test_interface_channel_group.rb +1 -1
  103. data/tests/test_interface_ospf.rb +153 -23
  104. data/tests/test_interface_portchannel.rb +15 -6
  105. data/tests/test_interface_private_vlan.rb +200 -576
  106. data/tests/test_interface_svi.rb +5 -52
  107. data/tests/test_interface_switchport.rb +80 -240
  108. data/tests/test_itd_device_group.rb +2 -2
  109. data/tests/test_itd_device_group_node.rb +2 -2
  110. data/tests/test_itd_service.rb +1 -1
  111. data/tests/test_name_server.rb +3 -3
  112. data/tests/test_node_ext.rb +15 -17
  113. data/tests/test_ntp_config.rb +1 -1
  114. data/tests/test_ntp_server.rb +3 -3
  115. data/tests/test_nxapi.rb +1 -0
  116. data/tests/test_overlay_global.rb +15 -19
  117. data/tests/test_pim.rb +5 -5
  118. data/tests/test_pim_group_list.rb +1 -37
  119. data/tests/test_pim_rp_address.rb +1 -1
  120. data/tests/test_platform.rb +9 -11
  121. data/tests/test_portchannel_global.rb +43 -3
  122. data/tests/test_radius_server.rb +1 -1
  123. data/tests/test_radius_server_group.rb +1 -1
  124. data/tests/test_router_bgp.rb +17 -30
  125. data/tests/test_router_ospf_area.rb +433 -0
  126. data/tests/test_router_ospf_area_vlink.rb +298 -0
  127. data/tests/test_router_ospf_vrf.rb +17 -0
  128. data/tests/test_snmp_notification_receiver.rb +11 -11
  129. data/tests/test_snmpcommunity.rb +177 -69
  130. data/tests/test_snmpgroup.rb +7 -7
  131. data/tests/test_snmpserver.rb +164 -253
  132. data/tests/test_snmpuser.rb +73 -69
  133. data/tests/test_stp_global.rb +15 -15
  134. data/tests/test_syslog_settings.rb +1 -1
  135. data/tests/test_tacacs_global.rb +80 -0
  136. data/tests/test_tacacs_server.rb +129 -51
  137. data/tests/test_tacacs_server_group.rb +3 -29
  138. data/tests/test_tacacs_server_host.rb +24 -27
  139. data/tests/test_vlan.rb +57 -59
  140. data/tests/test_vlan_private.rb +271 -284
  141. data/tests/test_vpc.rb +10 -4
  142. data/tests/test_vrf.rb +2 -0
  143. data/tests/test_vrf_af.rb +2 -5
  144. data/tests/test_vtp.rb +5 -2
  145. data/tests/test_vxlan_vtep.rb +20 -44
  146. data/tests/test_vxlan_vtep_vni.rb +23 -16
  147. data/tests/test_yang.rb +369 -0
  148. data/tests/test_yum.rb +34 -42
  149. data/tests/yum_package.yaml +35 -0
  150. metadata +31 -4
  151. data/tests/test_vlan_mt_full.rb +0 -85
@@ -99,7 +99,10 @@ module Cisco
99
99
  # rubocop:enable Style/AccessorMethodNamefor
100
100
 
101
101
  def create
102
- Feature.bgp_enable if platform == :nexus
102
+ if platform == :nexus
103
+ Feature.bgp_enable
104
+ Feature.nv_overlay_evpn_enable if @safi[/evpn/]
105
+ end
103
106
  set_args_keys(state: '')
104
107
  config_set('bgp_neighbor', 'af', @set_args)
105
108
  end
@@ -224,5 +224,131 @@ module Cisco
224
224
  end
225
225
  lranges.to_s.gsub('..', '-').delete('[').delete(']').delete(' ')
226
226
  end
227
+
228
+ # normalize_range_array
229
+ #
230
+ # Given a list of ranges, merge any overlapping ranges and sort them.
231
+ #
232
+ # Note: The ranges are converted to ruby ranges for easy merging,
233
+ # then converted back to a cli-syntax range.
234
+ #
235
+ # Accepts an array or string:
236
+ # ["2-5", "9", "4-6"] -or- '2-5, 9, 4-6' -or- ["2-5, 9, 4-6"]
237
+ # Returns a merged and ordered range as an array or string:
238
+ # ["2-6", "9"] -or- '2-6,9'
239
+ #
240
+ def self.normalize_range_array(range, fmt=:array)
241
+ return range if range.nil? || range.empty?
242
+ range = range.clone
243
+
244
+ # Handle string within an array: ["2-5, 9, 4-6"] to '2-5, 9, 4-6'
245
+ range = range.shift if range.is_a?(Array) && range.length == 1
246
+
247
+ # Handle string only: '2-5, 9, 4-6' to ["2-5", "9", "4-6"]
248
+ range = range.split(',') if range.is_a?(String)
249
+
250
+ # Convert to ruby-syntax ranges
251
+ range = dash_range_to_ruby_range(range)
252
+
253
+ # Sort & Merge
254
+ merged = merge_range(range)
255
+
256
+ # Convert back to cli dash-syntax
257
+ merged_array = ruby_range_to_dash_range(merged)
258
+
259
+ return merged_array.join(',') if fmt == :string
260
+ merged_array
261
+ end
262
+
263
+ # Convert a cli-dash-syntax range to ruby-range. This is useful for
264
+ # preparing inputs to merge_range().
265
+ #
266
+ # Inputs an array or string of dash-syntax ranges -> returns an array
267
+ # of ruby ranges.
268
+ #
269
+ # Accepts an array or string: ["2-5", "9", "4-6"] or '2-5, 9, 4-6'
270
+ # Returns an array of ranges: [2..5, 9..9, 4..6]
271
+ #
272
+ def self.dash_range_to_ruby_range(range)
273
+ range = range.split(',') if range.is_a?(String)
274
+ range.map! do |rng|
275
+ if rng[/-/]
276
+ # '2-5' -> 2..5
277
+ rng.split('-').inject { |a, e| a.to_i..e.to_i }
278
+ else
279
+ # '9' -> 9..9
280
+ rng.to_i..rng.to_i
281
+ end
282
+ end
283
+ range
284
+ end
285
+
286
+ # Convert a ruby-range to cli-dash-syntax.
287
+ #
288
+ # Inputs an array of ruby ranges -> returns an array or string of
289
+ # dash-syntax ranges.
290
+ #
291
+ # when (:array) [2..6, 9..9] -> ['2-6', '9']
292
+ #
293
+ # when (:string) [2..6, 9..9] -> '2-6, 9'
294
+ #
295
+ def self.ruby_range_to_dash_range(range, type=:array)
296
+ fail unless range.is_a?(Array)
297
+ range.map! do |r|
298
+ if r.first == r.last
299
+ # 9..9 -> '9'
300
+ r.first.to_s
301
+ else
302
+ # 2..6 -> '2-6'
303
+ r.first.to_s + '-' + r.last.to_s
304
+ end
305
+ end
306
+ return range.join(', ') if type == :string
307
+ range
308
+ end
309
+
310
+ # Convert a dash-range set into individual elements.
311
+ # This is useful for preparing inputs to delta_add_remove().
312
+ #
313
+ # Inputs an array or string of dash-ranges:
314
+ # ["2-5", "9", "4-6"] or '2-5, 9, 4-6' or ['2-5, 9, 4-6']
315
+ # Returns an array of range elements:
316
+ # ["2", "3", "4", "5", "6", "9"]
317
+ #
318
+ def self.dash_range_to_elements(range)
319
+ return [] if range.nil?
320
+ range = range.shift if range.is_a?(Array) && range.length == 1
321
+ range = range.split(',') if range.is_a?(String)
322
+
323
+ final = []
324
+ range = dash_range_to_ruby_range(range)
325
+ range.each do |rng|
326
+ # 2..5 maps to ["2", "3", "4", "5"]
327
+ final << rng.map(&:to_s)
328
+ end
329
+ final.flatten.uniq.sort
330
+ end
331
+
332
+ # Merge overlapping ranges.
333
+ #
334
+ # Inputs an array of ruby ranges: [2..5, 9..9, 4..6]
335
+ # Returns an array of merged ruby ranges: [2..6, 9..9]
336
+ #
337
+ def self.merge_range(range)
338
+ # sort to lowest range 'first' values:
339
+ # [2..5, 9..9, 4..6] -> [2..5, 4..6, 9..9]
340
+ range = range.sort_by(&:first)
341
+
342
+ *merged = range.shift
343
+ range.each do |r|
344
+ lastr = merged[-1]
345
+ if lastr.last >= r.first - 1
346
+ merged[-1] = lastr.first..[r.last, lastr.last].max
347
+ else
348
+ merged.push(r)
349
+ end
350
+ end
351
+ merged
352
+ end # merge_range
227
353
  end # class Utils
228
354
  end # module Cisco
@@ -167,9 +167,11 @@ class Cisco::Client
167
167
  # @param data_format one of Cisco::DATA_FORMATS. Default is :cli
168
168
  # @param context [String, Array<String>] Context for the configuration
169
169
  # @param values [String, Array<String>] Actual configuration to set
170
+ # @param kwargs data-format-specific args
170
171
  def set(data_format: :cli,
171
172
  context: nil,
172
- values: nil)
173
+ values: nil,
174
+ **_kwargs)
173
175
  # subclasses will generally want to call Client.munge_to_array()
174
176
  # on context and/or values before calling super()
175
177
  fail Cisco::RequestNotSupported unless self.supports?(data_format)
@@ -195,11 +197,13 @@ class Cisco::Client
195
197
  # @param command [String] the get command to execute
196
198
  # @param context [String, Array<String>] Context to refine/filter the results
197
199
  # @param value [String, Regexp] Specific key or regexp to look up
200
+ # @param kwargs data-format-specific args
198
201
  # @return [String, Hash, nil] The state found, or nil if not found.
199
202
  def get(data_format: :cli,
200
203
  command: nil,
201
204
  context: nil,
202
- value: nil)
205
+ value: nil,
206
+ **_kwargs)
203
207
  # subclasses will generally want to call Client.munge_to_array()
204
208
  # on context and/or value before calling super()
205
209
  fail Cisco::RequestNotSupported unless self.supports?(data_format)
@@ -17,6 +17,7 @@
17
17
  # limitations under the License.
18
18
 
19
19
  require_relative '../client'
20
+ require_relative '../../constants'
20
21
  Cisco::Client.silence_warnings do
21
22
  require 'grpc'
22
23
  end
@@ -37,7 +38,7 @@ class Cisco::Client::GRPC < Cisco::Client
37
38
  kwargs[:host] ||= '127.0.0.1'
38
39
  kwargs[:port] ||= 57_400
39
40
  # rubocop:disable Style/HashSyntax
40
- super(data_formats: [:cli],
41
+ super(data_formats: [:cli, :yang_json],
41
42
  platform: :ios_xr,
42
43
  **kwargs)
43
44
  # rubocop:enable Style/HashSyntax
@@ -85,47 +86,64 @@ class Cisco::Client::GRPC < Cisco::Client
85
86
  # @param data_format one of Cisco::DATA_FORMATS. Default is :cli
86
87
  # @param context [Array<String>] Zero or more configuration commands used
87
88
  # to enter the desired CLI sub-mode
88
- # @param values [Array<String>] One or more commands to enter within the
89
- # CLI sub-mode.
89
+ # @param values [Array<String>] One or more commands to execute /
90
+ # config strings to send
91
+ # @param kwargs data-format-specific args
90
92
  def set(data_format: :cli,
91
93
  context: nil,
92
- values: nil)
94
+ values: nil,
95
+ **kwargs)
93
96
  context = munge_to_array(context)
94
97
  values = munge_to_array(values)
95
98
  super
96
- # IOS XR lets us concatenate submode commands together.
97
- # This makes it possible to guarantee we are in the correct context:
98
- # context: ['foo', 'bar'], values: ['baz', 'bat']
99
- # ---> values: ['foo bar baz', 'foo bar bat']
100
- # However, there's a special case for 'no' commands:
101
- # context: ['foo', 'bar'], values: ['no baz']
102
- # ---> values: ['no foo bar baz'] ---- the 'no' goes at the start
103
- context = context.join(' ')
104
- unless context.empty?
105
- values.map! do |cmd|
106
- match = cmd[/^\s*no\s+(.*)/, 1]
107
- if match
108
- cmd = "no #{context} #{match}"
109
- else
110
- cmd = "#{context} #{cmd}"
99
+ if data_format == :yang_json
100
+ mode = kwargs[:mode] || :merge_config
101
+ fail ArgumentError unless Cisco::YANG_SET_MODE.include? mode
102
+ values.each do |yang|
103
+ yang_req(@config, mode.to_s, ConfigArgs.new(yangjson: yang))
104
+ end
105
+ else
106
+ # IOS XR lets us concatenate submode commands together.
107
+ # This makes it possible to guarantee we are in the correct context:
108
+ # context: ['foo', 'bar'], values: ['baz', 'bat']
109
+ # ---> values: ['foo bar baz', 'foo bar bat']
110
+ # However, there's a special case for 'no' commands:
111
+ # context: ['foo', 'bar'], values: ['no baz']
112
+ # ---> values: ['no foo bar baz'] ---- the 'no' goes at the start
113
+ context = context.join(' ')
114
+ unless context.empty?
115
+ values.map! do |cmd|
116
+ match = cmd[/^\s*no\s+(.*)/, 1]
117
+ if match
118
+ cmd = "no #{context} #{match}"
119
+ else
120
+ cmd = "#{context} #{cmd}"
121
+ end
122
+ cmd
111
123
  end
112
- cmd
113
124
  end
125
+ # CliConfigArgs wants a newline-separated string of commands
126
+ args = CliConfigArgs.new(cli: values.join("\n"))
127
+ req(@config, 'cli_config', args)
114
128
  end
115
- # CliConfigArgs wants a newline-separated string of commands
116
- args = CliConfigArgs.new(cli: values.join("\n"))
117
- req(@config, 'cli_config', args)
118
129
  end
119
130
 
120
131
  def get(data_format: :cli,
121
132
  command: nil,
122
133
  context: nil,
123
- value: nil)
134
+ value: nil,
135
+ **kwargs)
124
136
  super
125
137
  fail ArgumentError if command.nil?
126
- args = ShowCmdArgs.new(cli: command)
127
- output = req(@exec, 'show_cmd_text_output', args)
128
- self.class.filter_cli(cli_output: output, context: context, value: value)
138
+
139
+ if data_format == :yang_json
140
+ mode = kwargs[:mode] || :get_config
141
+ yang_req(@config, mode, ConfigGetArgs.new(yangpathjson: command))
142
+ else
143
+ args = ShowCmdArgs.new(cli: command)
144
+ output = req(@exec, 'show_cmd_text_output', args)
145
+ self.class.filter_cli(cli_output: output, context: context, value: value)
146
+ end
129
147
  end
130
148
 
131
149
  def req(stub, type, args)
@@ -170,6 +188,51 @@ class Cisco::Client::GRPC < Cisco::Client
170
188
  end
171
189
  end
172
190
 
191
+ # Send a YANG request via gRPC
192
+ def yang_req(stub, type, args)
193
+ debug "Sending '#{type}' request:"
194
+ if args.is_a?(ConfigGetArgs)
195
+ debug " with yangpathjson: #{args.yangpathjson}"
196
+ elsif args.is_a?(ConfigArgs)
197
+ debug " with yangjson: #{args.yangjson}"
198
+ end
199
+
200
+ output = Cisco::Client.silence_warnings do
201
+ response = stub.send(type, args,
202
+ timeout: @timeout,
203
+ username: @username,
204
+ password: @password)
205
+ # gRPC server may split the response into multiples
206
+ response = response.is_a?(Enumerator) ? response.to_a : [response]
207
+ debug "Got responses: #{response.map(&:class).join(', ')}"
208
+ debug "response: #{response}"
209
+ # Check for errors first
210
+ handle_errors(args, response.select { |r| !r.errors.empty? })
211
+
212
+ # If we got here, no errors occurred
213
+ handle_response(args, response)
214
+ end
215
+ return output
216
+
217
+ rescue ::GRPC::BadStatus => e
218
+ warn "gRPC error '#{e.code}' during '#{type}' request: "
219
+ if args.is_a?(ConfigGetArgs)
220
+ debug " with yangpathjson: #{args.yangpathjson}"
221
+ elsif args.is_a?(ConfigArgs)
222
+ debug " with yangjson: #{args.yangjson}"
223
+ end
224
+
225
+ warn " '#{e.details}'"
226
+ case e.code
227
+ when ::GRPC::Core::StatusCodes::UNAVAILABLE
228
+ raise Cisco::ConnectionRefused, "Connection refused: #{e.details}"
229
+ when ::GRPC::Core::StatusCodes::UNAUTHENTICATED
230
+ raise Cisco::AuthenticationFailed, e.details
231
+ else
232
+ raise Cisco::ClientError, e.details
233
+ end
234
+ end
235
+
173
236
  def handle_response(args, replies)
174
237
  klass = replies[0].class
175
238
  unless replies.all? { |r| r.class == klass }
@@ -189,6 +252,15 @@ class Cisco::Client::GRPC < Cisco::Client
189
252
  when /CliConfigReply/
190
253
  # nothing to process
191
254
  output = ''
255
+ when /ConfigGetReply/
256
+ replies.each { |r| debug " yangjson:\n#{r.yangjson}" }
257
+ output = replies.map(&:yangjson).join('')
258
+ when /GetOperReply/
259
+ replies.each { |r| debug " yangjson:\n#{r.yangjson}" }
260
+ output = replies.map(&:yangjson).join('')
261
+ when /ConfigReply/
262
+ # nothing to process
263
+ output = ''
192
264
  else
193
265
  fail Cisco::ClientError, "unsupported reply class #{klass}"
194
266
  end
@@ -242,6 +314,11 @@ class Cisco::Client::GRPC < Cisco::Client
242
314
  def handle_text_error(args, msg)
243
315
  if /^Disallowed commands:/ =~ msg
244
316
  fail Cisco::RequestNotSupported, msg
317
+ elsif args.is_a?(ConfigGetArgs) || args.is_a?(ConfigArgs)
318
+ fail Cisco::YangError.new( # rubocop:disable Style/RaiseArgs
319
+ rejected_input: args.yangpathjson,
320
+ error: msg,
321
+ )
245
322
  else
246
323
  fail Cisco::CliError.new( # rubocop:disable Style/RaiseArgs
247
324
  rejected_input: args.cli,
@@ -277,7 +354,8 @@ class Cisco::Client::GRPC < Cisco::Client
277
354
  msg = msg['error'] unless msg.is_a?(Array)
278
355
  msg.each do |m|
279
356
  type = m['error-type']
280
- message = m['error-message']
357
+ message = m['error-message'] || m['error-tag']
358
+ message += ': ' + m['error-path'] if m['error-path']
281
359
  if type == 'protocol' && message == 'Failed authentication'
282
360
  fail Cisco::AuthenticationFailed, message
283
361
  elsif type == 'application'
@@ -293,16 +371,22 @@ class Cisco::Client::GRPC < Cisco::Client
293
371
  # foo
294
372
  # bar
295
373
  #
296
- match = /\n\n(.*)\n\n\Z/m.match(message)
297
- if match.nil?
298
- rejected = '(unknown, see error message)'
374
+ if m['error-path']
375
+ fail Cisco::YangError.new( # rubocop:disable Style/RaiseArgs
376
+ message
377
+ )
299
378
  else
300
- rejected = match[1].split("\n")
379
+ match = /\n\n(.*)\n\n\Z/m.match(message)
380
+ if match.nil?
381
+ rejected = '(unknown, see error message)'
382
+ else
383
+ rejected = match[1].split("\n")
384
+ end
385
+ fail Cisco::CliError.new( # rubocop:disable Style/RaiseArgs
386
+ rejected_input: rejected,
387
+ clierror: message,
388
+ )
301
389
  end
302
- fail Cisco::CliError.new( # rubocop:disable Style/RaiseArgs
303
- rejected_input: rejected,
304
- clierror: message,
305
- )
306
390
  else
307
391
  fail Cisco::ClientError, message
308
392
  end
@@ -105,9 +105,11 @@ class Cisco::Client::NXAPI < Cisco::Client
105
105
  # used to enter the desired CLI sub-mode
106
106
  # @param values [String, Array<String>] One or more commands
107
107
  # to enter within the CLI sub-mode.
108
+ # @param kwargs data-format-specific args
108
109
  def set(data_format: :cli,
109
110
  context: nil,
110
- values: nil)
111
+ values: nil,
112
+ **_kwargs)
111
113
  # we don't currently support nxapi_structured for configuration
112
114
  fail Cisco::RequestNotSupported if data_format == :nxapi_structured
113
115
  context = munge_to_array(context)
@@ -130,11 +132,13 @@ class Cisco::Client::NXAPI < Cisco::Client
130
132
  # @param command [String] the show command to execute
131
133
  # @param context [String, Array<String>] Context to refine the results
132
134
  # @param value [String] Specific key to look up
135
+ # @param kwargs data-format-specific args
133
136
  # @return [String, Hash]
134
137
  def get(data_format: :cli,
135
138
  command: nil,
136
139
  context: nil,
137
- value: nil)
140
+ value: nil,
141
+ **_kwargs)
138
142
  context = munge_to_array(context)
139
143
  super
140
144
  if data_format == :cli
@@ -0,0 +1,118 @@
1
+ # DEPRECATED
2
+ #
3
+ ###############################################################################
4
+ # WARNING. DO NOT USE ANY OF THE YAML TAGS IN THIS FILE.
5
+ # These yaml tags are deprecated and will be removed in future releases.
6
+ ###############################################################################
7
+ ---
8
+ _template:
9
+ context: ["interface <name>"]
10
+ nexus:
11
+ get_command: "show running interface all"
12
+
13
+ private_vlan_any:
14
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'pvlan_any'
15
+ multiple:
16
+ get_value: '/switchport private-vlan/'
17
+
18
+ private_vlan_association:
19
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'pvlan_association'
20
+ _exclude: [N8k]
21
+ multiple: true
22
+ get_command: "show vlan private-vlan"
23
+ get_context: ~
24
+ get_value: '/^<id>\s+(\d+)/'
25
+ set_context: ['vlan <vlan>']
26
+ set_value: "<state> private-vlan association <vlans> ; end"
27
+ default_value: []
28
+
29
+ private_vlan_mapping:
30
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'pvlan_mapping'
31
+ _exclude: [ios_xr, N8k]
32
+ multiple: true
33
+ get_value: '/^private-vlan mapping (.*)$/'
34
+ set_value: "<state> private-vlan mapping <vlans>"
35
+ default_value: []
36
+
37
+ private_vlan_type:
38
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'pvlan_type'
39
+ _exclude: [N8k]
40
+ kind: string
41
+ get_command: 'show vlan private-vlan type'
42
+ get_context: ~
43
+ get_value: '/^<id>\s+(\S+)/'
44
+ set_context: ['vlan <vlan>']
45
+ set_value: "<state> private-vlan <type> ; end"
46
+ default_value: ""
47
+
48
+ switchport_mode_private_vlan_host:
49
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'switchport_pvlan_host'
50
+ _exclude: [ios_xr, N8k]
51
+ get_value: '/^switchport mode private-vlan (.*)$/'
52
+ set_value: "<state> switchport mode private-vlan <mode>"
53
+ default_value: :disabled
54
+
55
+ switchport_mode_private_vlan_host_association:
56
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'switchport_pvlan_host_association'
57
+ _exclude: [ios_xr, N8k]
58
+ multiple: true
59
+ get_value: '/^switchport private-vlan host-association (.*)$/'
60
+ set_value: "<state> switchport private-vlan host-association <vlan_pr> <vlan_sec>"
61
+ default_value: []
62
+
63
+ switchport_mode_private_vlan_host_promiscous:
64
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'switchport_pvlan_promiscuous'
65
+ _exclude: [ios_xr, N8k]
66
+ multiple: true
67
+ get_value: '/^switchport private-vlan mapping (\d+.*)$/'
68
+ set_value: "<state> switchport private-vlan mapping <vlan_pr> <vlans>"
69
+ default_value: []
70
+
71
+ switchport_mode_private_vlan_trunk_promiscuous:
72
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'switchport_pvlan_trunk_promiscuous'
73
+ _exclude: [ios_xr, N3k, N8k]
74
+ kind: boolean
75
+ get_value: '/^switchport mode private-vlan trunk promiscuous$/'
76
+ set_value: "<state> switchport mode private-vlan trunk promiscuous"
77
+ default_value: false
78
+
79
+ switchport_mode_private_vlan_trunk_secondary:
80
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'switchport_pvlan_trunk_secondary'
81
+ _exclude: [ios_xr, N3k, N8k]
82
+ kind: boolean
83
+ get_value: '/^switchport mode private-vlan trunk secondary$/'
84
+ set_value: "<state> switchport mode private-vlan trunk secondary"
85
+ default_value: false
86
+
87
+ switchport_private_vlan_association_trunk:
88
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'switchport_pvlan_trunk_association'
89
+ _exclude: [ios_xr, N3k, N8k]
90
+ multiple: true
91
+ #get_value: '/^switchport private-vlan association trunk (.*) (.*)$/'
92
+ get_value: '/^switchport private-vlan association trunk (.*)$/'
93
+ set_value: "<state> switchport private-vlan association trunk <vlan_pr> <vlan>"
94
+ default_value: []
95
+
96
+ switchport_private_vlan_mapping_trunk:
97
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'switchport_pvlan_mapping_trunk'
98
+ _exclude: [ios_xr, N3k, N8k]
99
+ multiple: true
100
+ get_value: '/^switchport private-vlan mapping trunk (.*)$/'
101
+ set_value: "<state> switchport private-vlan mapping trunk <vlan_pr> <vlans>"
102
+ default_value: []
103
+
104
+ switchport_private_vlan_trunk_allowed_vlan:
105
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'switchport_pvlan_trunk_allowed_vlan'
106
+ _exclude: [ios_xr, N8k]
107
+ multiple: true
108
+ get_value: '/^switchport private-vlan trunk allowed vlan (.*)$/'
109
+ set_value: "<state> switchport private-vlan trunk allowed vlan <oper> <vlans>"
110
+ default_value: []
111
+
112
+ switchport_private_vlan_trunk_native_vlan:
113
+ # DEPRECATED (REMOVING WITH RELEASE 2.0.0). USE 'switchport_pvlan_trunk_native_vlan'
114
+ _exclude: [ios_xr, N8k]
115
+ kind: int
116
+ get_value: '/^switchport private-vlan trunk native vlan (.*)$/'
117
+ set_value: "<state> switchport private-vlan trunk native vlan <vlan>"
118
+ default_value: 1