cisco_node_utils 1.10.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/CHANGELOG.md +25 -0
- data/lib/cisco_node_utils/bgp.rb +1 -1
- data/lib/cisco_node_utils/cisco_cmn_utils.rb +11 -3
- data/lib/cisco_node_utils/client/nxapi/client.rb +40 -6
- data/lib/cisco_node_utils/cmd_ref/acl.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/banner.yaml +5 -1
- data/lib/cisco_node_utils/cmd_ref/feature.yaml +8 -1
- data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/interface_service_vni.yaml +5 -0
- data/lib/cisco_node_utils/cmd_ref/inventory.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/ospf.yaml +7 -0
- data/lib/cisco_node_utils/cmd_ref/route_map.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/vtp.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +30 -0
- data/lib/cisco_node_utils/cmd_ref/vxlan_vtep_vni.yaml +9 -2
- data/lib/cisco_node_utils/command_reference.rb +2 -2
- data/lib/cisco_node_utils/dhcp_relay_global.rb +1 -5
- data/lib/cisco_node_utils/feature.rb +30 -4
- data/lib/cisco_node_utils/interface.rb +3 -3
- data/lib/cisco_node_utils/interface_service_vni.rb +1 -1
- data/lib/cisco_node_utils/node.rb +11 -22
- data/lib/cisco_node_utils/node_util.rb +1 -1
- data/lib/cisco_node_utils/radius_global.rb +3 -3
- data/lib/cisco_node_utils/radius_server.rb +1 -2
- data/lib/cisco_node_utils/route_map.rb +1 -1
- data/lib/cisco_node_utils/router_ospf_vrf.rb +49 -5
- data/lib/cisco_node_utils/tacacs_global.rb +1 -2
- data/lib/cisco_node_utils/tacacs_server.rb +1 -2
- data/lib/cisco_node_utils/tacacs_server_host.rb +1 -2
- data/lib/cisco_node_utils/version.rb +1 -1
- data/lib/cisco_node_utils/vlan.rb +1 -1
- data/lib/cisco_node_utils/vxlan_vtep.rb +89 -4
- data/lib/cisco_node_utils/vxlan_vtep_vni.rb +32 -1
- data/spec/schema.yaml +2 -0
- data/tests/basetest.rb +40 -4
- data/tests/ciscotest.rb +15 -5
- data/tests/cmd_config.yaml +0 -2
- data/tests/test_acl.rb +1 -1
- data/tests/test_bgp_af.rb +6 -0
- data/tests/test_feature.rb +30 -4
- data/tests/test_interface.rb +5 -7
- data/tests/test_interface_ospf.rb +5 -1
- data/tests/test_interface_private_vlan.rb +18 -1
- data/tests/test_interface_svi.rb +1 -1
- data/tests/test_interface_switchport.rb +4 -7
- data/tests/test_node_ext.rb +1 -1
- data/tests/test_nxapi.rb +18 -8
- data/tests/test_radius_global.rb +3 -2
- data/tests/test_route_map.rb +2 -4
- data/tests/test_router_bgp.rb +10 -14
- data/tests/test_router_ospf_vrf.rb +61 -0
- data/tests/test_snmpserver.rb +1 -1
- data/tests/test_tacacs_global.rb +4 -2
- data/tests/test_upgrade.rb +1 -1
- data/tests/test_vrf.rb +2 -0
- data/tests/test_vrf_af.rb +2 -0
- data/tests/test_vtp.rb +6 -4
- data/tests/test_vxlan_vtep.rb +93 -1
- data/tests/test_vxlan_vtep_vni.rb +35 -1
- data/tests/yum_package.yaml +5 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8500c855a9675c3c3ab5e581f06be1f67fb8074e
|
4
|
+
data.tar.gz: 0abf3dc4d719fa5282db36717571113f9ffdb617
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ed3776cba64a9cbd4276a0c8034222a9d761f76f4a8b226e2af50fe8d1b1ac0c30d8cb698d1de1132e90435e7c20f6d05ea63216a379bb4da1913e5a6ee72b9
|
7
|
+
data.tar.gz: fc0a131d57d06626abdc777023b5a9637d15591997e8d88d05671f95a2efa8893b82c899fc4dc54e4f4407feac61befe7ba574a0c7438f3fe691cd1063605f60
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,30 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
+
## [v2.0.0]
|
5
|
+
|
6
|
+
### New Cisco Resources
|
7
|
+
|
8
|
+
### Added
|
9
|
+
* Extend nxapi client for https support
|
10
|
+
* `use_ssl` will be true when `transport` is `https`
|
11
|
+
* now makes use of `port` for custom nxapi ports
|
12
|
+
* Extend router_ospf_vrf with attribute:
|
13
|
+
* `redistribute`
|
14
|
+
* `reset_instance` method to node. Allows a single instance of nodeutils to reset the environment cache.
|
15
|
+
* Extend vxlan_vtep_vni with attribute:
|
16
|
+
* `suppress_arp_disable`
|
17
|
+
* Extend vxlan_vtep with attributes:
|
18
|
+
* `global_suppress_arp`
|
19
|
+
* `global_ingress_replication_bgp`
|
20
|
+
* `global_mcast_group_l2`
|
21
|
+
* `global_mcast_group_l3`
|
22
|
+
|
23
|
+
### Removed
|
24
|
+
* Removed cache in `node_util.node`, which gave every inheriting class it's own cache.
|
25
|
+
|
26
|
+
### Changed
|
27
|
+
|
4
28
|
## [v1.10.0]
|
5
29
|
|
6
30
|
### New Cisco Resources
|
@@ -587,6 +611,7 @@ Cisco::Environment.add_env('default', env)
|
|
587
611
|
[git-flow]: https://github.com/petervanderdoes/gitflow-avh
|
588
612
|
[SimpleCov]: https://github.com/colszowka/simplecov
|
589
613
|
|
614
|
+
[v2.0.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.10.0...v2.0.0
|
590
615
|
[v1.10.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.9.0...v1.10.0
|
591
616
|
[v1.9.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.8.0...v1.9.0
|
592
617
|
[v1.8.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.7.0...v1.8.0
|
data/lib/cisco_node_utils/bgp.rb
CHANGED
@@ -827,7 +827,7 @@ module Cisco
|
|
827
827
|
# explicit values when removing the rd command. These restrictions are
|
828
828
|
# not not needed in I3 and newer images.
|
829
829
|
Feature.nv_overlay_evpn_enable if
|
830
|
-
Utils.nexus_i2_image || node.product_id[/
|
830
|
+
Utils.nexus_i2_image || node.product_id[/N[567]/]
|
831
831
|
|
832
832
|
if rd == default_route_distinguisher
|
833
833
|
return if route_distinguisher.empty?
|
@@ -113,6 +113,14 @@ module Cisco
|
|
113
113
|
return true if Platform.chassis['pid'][ver_regexp]
|
114
114
|
end
|
115
115
|
|
116
|
+
def self.fretta?
|
117
|
+
require_relative 'platform'
|
118
|
+
Platform.slots.each do |_x, row|
|
119
|
+
return true if row['pid'][/-R/]
|
120
|
+
end
|
121
|
+
false
|
122
|
+
end
|
123
|
+
|
116
124
|
# Helper utility method for ip/prefix format networks.
|
117
125
|
# For ip/prefix format '1.1.1.1/24' or '2000:123:38::34/64',
|
118
126
|
# we need to mask the address using the prefix length so that they
|
@@ -362,9 +370,9 @@ module Cisco
|
|
362
370
|
end # merge_range
|
363
371
|
|
364
372
|
def self.add_quotes(value)
|
365
|
-
return value if image_version?(/7.3/)
|
366
|
-
value = "
|
367
|
-
value.start_with?('"') && value.end_with?('"')
|
373
|
+
return value if image_version?(/7.3.[0-1]/) || value.nil?
|
374
|
+
value = "'#{value}'" unless
|
375
|
+
value.start_with?('"', "'") && value.end_with?('"', "'")
|
368
376
|
value
|
369
377
|
end # add_quotes
|
370
378
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# November 2014, Glenn F. Matthews
|
4
4
|
#
|
5
|
-
# Copyright (c) 2014-
|
5
|
+
# Copyright (c) 2014-2019 Cisco and/or its affiliates.
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
8
|
# you may not use this file except in compliance with the License.
|
@@ -60,7 +60,11 @@ class Cisco::Client::NXAPI < Cisco::Client
|
|
60
60
|
else
|
61
61
|
# Remote connection. This is primarily expected
|
62
62
|
# when running e.g. from a Unix server as part of Minitest.
|
63
|
-
@
|
63
|
+
@transport = kwargs[:transport] || 'http'
|
64
|
+
@verify_mode = kwargs[:verify_mode] || 'none'
|
65
|
+
@port.nil? ? @port = '' : @port = ":#{@port}"
|
66
|
+
uri = URI.parse("#{@transport}://#{@host}#{@port}")
|
67
|
+
@http = Net::HTTP.new(uri.host, uri.port)
|
64
68
|
end
|
65
69
|
# The default read time out is 60 seconds, which may be too short for
|
66
70
|
# scaled configuration to apply. Change it to 300 seconds, which is
|
@@ -205,14 +209,18 @@ class Cisco::Client::NXAPI < Cisco::Client
|
|
205
209
|
request = build_http_request(type, command)
|
206
210
|
|
207
211
|
# send the request and get the response
|
208
|
-
debug("Sending
|
212
|
+
debug("Sending #{@transport} request to NX-API at #{@http.address}:\n" \
|
209
213
|
"#{request.to_hash}\n#{request.body}")
|
210
214
|
read_timeout_check(request)
|
211
215
|
tries = 2
|
212
216
|
begin
|
213
|
-
|
214
|
-
|
215
|
-
|
217
|
+
if @transport == 'https'
|
218
|
+
debug('Setting use_ssl to true')
|
219
|
+
@http.use_ssl = true
|
220
|
+
@http.verify_mode = handle_verify_mode(@verify_mode)
|
221
|
+
else
|
222
|
+
@http.use_ssl = false
|
223
|
+
end
|
216
224
|
response = @http.request(request)
|
217
225
|
rescue Errno::ECONNREFUSED, Errno::ECONNRESET
|
218
226
|
emsg = 'Connection refused or reset. Is the NX-API feature enabled?'
|
@@ -268,6 +276,32 @@ class Cisco::Client::NXAPI < Cisco::Client
|
|
268
276
|
end
|
269
277
|
private :build_http_request
|
270
278
|
|
279
|
+
# Returns the OpenSSL verify mode based on the verify_mode arguments
|
280
|
+
#
|
281
|
+
# @raise if verify_mode param is not `peer`, `client-once`, `fail-no-peer`
|
282
|
+
# or `none`
|
283
|
+
#
|
284
|
+
# @param String verify mode to use
|
285
|
+
#
|
286
|
+
# @return OpenSSL::SSL verification mode
|
287
|
+
def handle_verify_mode(verify_mode)
|
288
|
+
case verify_mode
|
289
|
+
when 'peer'
|
290
|
+
OpenSSL::SSL::VERIFY_PEER
|
291
|
+
when 'client-once'
|
292
|
+
OpenSSL::SSL::VERIFY_CLIENT_ONCE
|
293
|
+
when 'fail-no-peer'
|
294
|
+
OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
295
|
+
when 'none'
|
296
|
+
OpenSSL::SSL::VERIFY_NONE
|
297
|
+
else
|
298
|
+
fail "#{verify_mode} is not a valid mode, " \
|
299
|
+
'valid modes are: "none", "peer", ' \
|
300
|
+
'"client-once", "fail-no-peer"'
|
301
|
+
end
|
302
|
+
end
|
303
|
+
private :handle_verify_mode
|
304
|
+
|
271
305
|
def handle_http_response(response)
|
272
306
|
debug("HTTP Response: #{response.message}\n#{response.body}")
|
273
307
|
case response
|
@@ -1,7 +1,11 @@
|
|
1
1
|
# banner
|
2
2
|
---
|
3
3
|
motd:
|
4
|
-
|
4
|
+
N5k: &N6000
|
5
|
+
default_value: "Nexus 6000 Switch\n"
|
6
|
+
N6k: *N6000
|
7
|
+
else:
|
8
|
+
default_value: "User Access Verification\n"
|
5
9
|
get_command: 'show banner motd'
|
6
10
|
get_value: '/^.*$/m'
|
7
11
|
set_value: '<state> banner motd <motd>'
|
@@ -31,8 +31,14 @@ fabric_forwarding:
|
|
31
31
|
get_value: '/^feature fabric forwarding$/'
|
32
32
|
set_value: "feature fabric forwarding"
|
33
33
|
|
34
|
+
fabricpath:
|
35
|
+
_exclude: [N3k, N3k-F, N9k-F, N9k]
|
36
|
+
get_command: "show feature-set"
|
37
|
+
get_value: '/^fabricpath[\s\d]+(\w+)/'
|
38
|
+
set_value: "<state> feature-set fabricpath"
|
39
|
+
|
34
40
|
fex:
|
35
|
-
_exclude: [C3064, C3132, N5k, N6k, N3k-F, N9k-F]
|
41
|
+
_exclude: [C3048, C3064, C3132, N5k, N6k, N3k-F, N9k-F]
|
36
42
|
get_command: "show feature-set"
|
37
43
|
get_value: '/^fex[\s\d]+(\w+)/'
|
38
44
|
set_value: "<state> feature-set fex"
|
@@ -113,6 +119,7 @@ vni:
|
|
113
119
|
set_value: 'feature vn-segment-vlan-based'
|
114
120
|
|
115
121
|
vtp:
|
122
|
+
_exclude: [N3k-F, N9k-F]
|
116
123
|
kind: boolean
|
117
124
|
get_value: '/^feature vtp$/'
|
118
125
|
set_value: "<state> feature vtp"
|
@@ -21,7 +21,7 @@ bfd:
|
|
21
21
|
# no config at all so need to grab the optional
|
22
22
|
# match to get the whole config for checking
|
23
23
|
# the mode
|
24
|
-
get_value: '/^\s*ip ospf bfd *(?:\S
|
24
|
+
get_value: '/^\s*ip ospf bfd *(?:\S*)$/'
|
25
25
|
set_value: '%s ip ospf bfd %s'
|
26
26
|
default_value: ~
|
27
27
|
|
@@ -39,6 +39,13 @@ process_initialized:
|
|
39
39
|
get_command: "show ip ospf stat"
|
40
40
|
get_value: '/^No SAP is registered/' # Ospf is not initialized when seen
|
41
41
|
|
42
|
+
redistribute:
|
43
|
+
# no support yet for redistribute maximum-prefix
|
44
|
+
multiple: true
|
45
|
+
get_value: '/^redistribute (\S+ ?\S+?) route-map (\S+)$/'
|
46
|
+
set_value: '<state> redistribute <protocol> route-map <route_map>'
|
47
|
+
default_value: []
|
48
|
+
|
42
49
|
router:
|
43
50
|
multiple: true
|
44
51
|
get_command: "show running ospf"
|
@@ -361,7 +361,7 @@ set_distance_local:
|
|
361
361
|
|
362
362
|
# there is more than one space before delete on some platforms
|
363
363
|
set_extcomm_list:
|
364
|
-
get_value: '/^set extcomm-list (\S+)
|
364
|
+
get_value: '/^set extcomm-list (\S+)\s+delete$/'
|
365
365
|
set_value: "<state> set extcomm-list <list> delete"
|
366
366
|
default_value: false
|
367
367
|
|
@@ -12,6 +12,36 @@ all_interfaces:
|
|
12
12
|
get_context: ~
|
13
13
|
get_value: '/^interface (.*)$/'
|
14
14
|
|
15
|
+
global_ingress_replication_bgp:
|
16
|
+
_exclude: [N3k-F, N5k, N6k, N7k, N9k-F]
|
17
|
+
os_version: 'N9k:9.2'
|
18
|
+
kind: boolean
|
19
|
+
get_value: '/^global ingress-replication protocol bgp$/'
|
20
|
+
set_value: '<state> global ingress-replication protocol bgp'
|
21
|
+
default_value: false
|
22
|
+
|
23
|
+
global_mcast_group_l2:
|
24
|
+
_exclude: [N3k-F, N5k, N6k, N7k]
|
25
|
+
os_version: 'N9k, N9k-F:9.2'
|
26
|
+
get_value: '/^global mcast-group (\S+) L2$/'
|
27
|
+
set_value: '<state> global mcast-group <ip> L2'
|
28
|
+
default_value: ~
|
29
|
+
|
30
|
+
global_mcast_group_l3:
|
31
|
+
_exclude: [N3k-F, N5k, N6k, N7k, N9k-F]
|
32
|
+
os_version: 'N9k:9.2'
|
33
|
+
get_value: '/^global mcast-group (\S+) L3$/'
|
34
|
+
set_value: '<state> global mcast-group <ip> L3'
|
35
|
+
default_value: ~
|
36
|
+
|
37
|
+
global_suppress_arp:
|
38
|
+
_exclude: [N3k-F, N5k, N6k, N7k]
|
39
|
+
os_version: 'N9k, N9k-F:9.2'
|
40
|
+
kind: boolean
|
41
|
+
get_value: '/^global suppress-arp$/'
|
42
|
+
set_value: '<state> global suppress-arp'
|
43
|
+
default_value: false
|
44
|
+
|
15
45
|
host_reachability:
|
16
46
|
get_value: '/^host-reachability protocol (\S+)/'
|
17
47
|
set_value: '<state> host-reachability protocol <proto>'
|
@@ -16,7 +16,7 @@ all_vnis:
|
|
16
16
|
get_value: '/^member vni (\d+|\d+-\d+) ?(associate-vrf)?$/'
|
17
17
|
|
18
18
|
ingress_replication:
|
19
|
-
_exclude: [N5k, N6k, N7k]
|
19
|
+
_exclude: [N3k-F, N5k, N6k, N7k, N9k-F]
|
20
20
|
kind: string
|
21
21
|
get_value: '/^ingress-replication protocol (\S+)$/'
|
22
22
|
set_value: '<state> ingress-replication protocol <protocol>'
|
@@ -35,7 +35,7 @@ multisite_ingress_replication:
|
|
35
35
|
default_value: false
|
36
36
|
|
37
37
|
peer_list:
|
38
|
-
_exclude: [N5k, N6k, N7k]
|
38
|
+
_exclude: [N3k-F, N5k, N6k, N7k, N9k-F]
|
39
39
|
multiple:
|
40
40
|
get_context:
|
41
41
|
- '/^interface <name>$/i'
|
@@ -55,6 +55,13 @@ suppress_arp:
|
|
55
55
|
set_value: '<state> suppress-arp'
|
56
56
|
default_value: false
|
57
57
|
|
58
|
+
suppress_arp_disable:
|
59
|
+
_exclude: [N3k-F, N5k, N6k, N7k]
|
60
|
+
os_version: 'N9k, N9k-F:9.2'
|
61
|
+
get_value: '/^suppress-arp disable$/'
|
62
|
+
set_value: '<state> suppress-arp disable'
|
63
|
+
default_value: ~
|
64
|
+
|
58
65
|
suppress_uuc:
|
59
66
|
_exclude: [N3k-F, N9k-F, N9k]
|
60
67
|
os_version: 'N7k:8.1.1'
|
@@ -437,8 +437,8 @@ module Cisco
|
|
437
437
|
puts "DEBUG: #{text}" if @@debug
|
438
438
|
end
|
439
439
|
|
440
|
-
KNOWN_PLATFORMS = %w(C3064 C3132 C3172 N35 N3k N3k-F N5k N6k N7k N9k
|
441
|
-
XRv9k)
|
440
|
+
KNOWN_PLATFORMS = %w(C3048 C3064 C3132 C3172 N35 N3k N3k-F N5k N6k N7k N9k
|
441
|
+
N9k-F XRv9k)
|
442
442
|
|
443
443
|
def self.platform_to_filter(platform)
|
444
444
|
if KNOWN_PLATFORMS.include?(platform)
|
@@ -172,7 +172,6 @@ module Cisco
|
|
172
172
|
|
173
173
|
def ipv4_src_intf
|
174
174
|
intf = config_get('dhcp_relay_global', 'ipv4_src_intf')
|
175
|
-
# Normalize by downcasing and removing white space
|
176
175
|
intf = intf.downcase.delete(' ') if intf
|
177
176
|
intf
|
178
177
|
end
|
@@ -207,10 +206,7 @@ module Cisco
|
|
207
206
|
def ipv4_sub_option_circuit_id_string
|
208
207
|
str = config_get('dhcp_relay_global', 'ipv4_sub_option_circuit_id_string')
|
209
208
|
# Normalize by removing white space and add quotes
|
210
|
-
if str
|
211
|
-
str.strip!
|
212
|
-
str = Utils.add_quotes(str)
|
213
|
-
end
|
209
|
+
str.strip! if str.kind_of?(String)
|
214
210
|
str
|
215
211
|
end
|
216
212
|
|
@@ -80,6 +80,27 @@ module Cisco
|
|
80
80
|
config_get('feature', 'fabric')
|
81
81
|
end
|
82
82
|
|
83
|
+
# ---------------------------
|
84
|
+
def self.fabricpath_enable
|
85
|
+
# install feature-set and enable it
|
86
|
+
return if fabricpath_enabled?
|
87
|
+
config_set('feature', 'fabricpath', state: 'install') unless
|
88
|
+
fabricpath_installed?
|
89
|
+
config_set('feature', 'fabricpath', state: '')
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.fabricpath_enabled?
|
93
|
+
config_get('feature', 'fabricpath') =~ /^enabled/
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.fabricpath_installed?
|
97
|
+
config_get('feature', 'fabricpath') !~ /^uninstalled/
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.fabricpath_supported?
|
101
|
+
config_get('feature', 'fabricpath')
|
102
|
+
end
|
103
|
+
|
83
104
|
# ---------------------------
|
84
105
|
def self.fabric_forwarding_enable
|
85
106
|
return if fabric_forwarding_enabled?
|
@@ -183,7 +204,8 @@ module Cisco
|
|
183
204
|
def self.nv_overlay_enable
|
184
205
|
# Note: vdc platforms restrict this feature to F3 or newer linecards
|
185
206
|
return if nv_overlay_enabled?
|
186
|
-
config_set('feature', 'nv_overlay', state: '')
|
207
|
+
result = config_set('feature', 'nv_overlay', state: '')
|
208
|
+
cli_error_check(result)
|
187
209
|
sleep 1
|
188
210
|
end
|
189
211
|
|
@@ -311,14 +333,18 @@ module Cisco
|
|
311
333
|
# instead just displays a STDOUT error message; thus NXAPI does not detect
|
312
334
|
# the failure and we must catch it by inspecting the "body" hash entry
|
313
335
|
# returned by NXAPI. This cli behavior is unlikely to change soon.
|
336
|
+
patterns = [
|
337
|
+
'Hardware is not capable of supporting',
|
338
|
+
'is unsupported on this node',
|
339
|
+
'Feature NOT supported on this Platform',
|
340
|
+
]
|
314
341
|
fail result[2]['body'] if
|
315
342
|
result[2].is_a?(Hash) &&
|
316
|
-
|
343
|
+
result[2]['body'].to_s[Regexp.union(patterns)]
|
317
344
|
|
318
345
|
# Some test environments get result as a string instead of a hash
|
319
346
|
fail result if
|
320
|
-
result.is_a?(String) &&
|
321
|
-
/Hardware is not capable of supporting/.match(result)
|
347
|
+
result.is_a?(String) && result[Regexp.union(patterns)]
|
322
348
|
end
|
323
349
|
|
324
350
|
# ---------------------------
|