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
data/tests/test_ace.rb CHANGED
@@ -18,143 +18,214 @@ require_relative '../lib/cisco_node_utils/ace'
18
18
 
19
19
  # TestAce - Minitest for Ace node utility class
20
20
  class TestAce < CiscoTestCase
21
+ @skip_unless_supported = 'acl'
22
+ @@pre_clean_needed = true # rubocop:disable Style/ClassVars
23
+
21
24
  def setup
22
- # setup runs at the beginning of each test
23
25
  super
24
- @acl_name_v4 = 'test-foo-v4-1'
25
- @acl_name_v6 = 'test-foo-v6-1'
26
- @seqno = 10
27
- no_access_list_foo
26
+ remove_all_acls if @@pre_clean_needed
27
+ @@pre_clean_needed = false # rubocop:disable Style/ClassVars
28
28
  end
29
29
 
30
30
  def teardown
31
- # teardown runs at the end of each test
32
- no_access_list_foo
33
31
  super
32
+ remove_all_acls
34
33
  end
35
34
 
36
- def no_access_list_foo
37
- # Remove the test ACLs
38
- %w(ipv4 ipv6).each do |afi|
39
- acl_name = afi[/ipv6/] ? @acl_name_v6 : @acl_name_v4
40
- config('no ' + Acl.afi_cli(afi) + ' access-list ' + acl_name)
35
+ def remove_all_acls
36
+ Acl.acls.each do |_afis, acls|
37
+ acls.values.each(&:destroy)
41
38
  end
42
39
  end
43
40
 
44
- # TESTS
45
- def test_create_destroy_ace_one
46
- attr_v4_1 = {
41
+ # Helper to create an ACE and return the obj. The test_hash contains
42
+ # only the minimum properties which can be added to or overwritten as
43
+ # required for each test.
44
+ def ace_helper(afi, props=nil)
45
+ test_hash = {
47
46
  action: 'permit',
48
47
  proto: 'tcp',
49
- src_addr: '7.8.9.6 2.3.4.5',
50
- src_port: 'eq 40',
51
- dst_addr: '1.2.3.4/32',
52
- dst_port: 'neq 20',
48
+ src_addr: 'any',
49
+ dst_addr: 'any',
53
50
  }
51
+ test_hash.merge!(props) unless props.nil?
54
52
 
55
- attr_v4_2 = {
56
- action: 'deny',
57
- proto: 'udp',
58
- src_addr: '7.8.9.6/32',
59
- src_port: 'eq 41',
60
- dst_addr: 'host 1.2.3.4',
61
- dst_port: 'neq 20',
62
- }
53
+ a = Ace.new(afi, afi, 10)
54
+ begin
55
+ a.ace_set(test_hash)
56
+ a
57
+ end
58
+ rescue CliError => e
59
+ skip('This property is not supported on this platform') if
60
+ e.message[/(Invalid parameter detected|Invalid command)/]
61
+ flunk(e.message)
62
+ end
63
63
 
64
- attr_v4_3 = {
65
- remark: 'ipv4 remark'
66
- }
64
+ # TESTS
65
+ def test_remark
66
+ %w(ipv4 ipv6).each do |afi|
67
+ a = ace_helper(afi, remark: afi)
68
+ assert_equal(afi, a.remark)
69
+ end
70
+ end
67
71
 
68
- attr_v6_1 = {
69
- action: 'permit',
70
- proto: '6',
71
- src_addr: 'addrgroup fi',
72
- src_port: '',
73
- dst_addr: '1::7/32',
74
- dst_port: '',
75
- }
72
+ def test_action
73
+ %w(ipv4 ipv6).each do |afi|
74
+ %w(permit deny).each do |val|
75
+ a = ace_helper(afi, action: val)
76
+ assert_equal(val, a.action)
77
+ end
78
+ end
79
+ end
76
80
 
77
- attr_v6_2 = {
78
- action: 'permit',
79
- proto: 'udp',
80
- src_addr: '1::8/56',
81
- src_port: 'eq 41',
82
- dst_addr: 'any',
83
- dst_port: '',
84
- }
81
+ def test_proto
82
+ %w(ipv4 ipv6).each do |afi|
83
+ # Sampling of proto's
84
+ %w(ip tcp udp).each do |val|
85
+ val = 'ipv6' if val[/ip/] && afi[/ipv6/]
86
+ a = ace_helper(afi, proto: val)
87
+ assert_equal(val, a.proto)
88
+ end
89
+ end
90
+ end
85
91
 
86
- attr_v6_3 = {
87
- remark: 'ipv6 remark'
88
- }
92
+ def test_addrs
93
+ val = '10.1.1.1/32'
94
+ a = ace_helper('ipv4', src_addr: val, dst_addr: val)
95
+ assert_equal(val, a.src_addr)
96
+ assert_equal(val, a.dst_addr)
97
+
98
+ val = '10.1.1.1 0.0.0.0'
99
+ exp = '10.1.1.1/32'
100
+ # This syntax will transform to 10.1.1.1/32
101
+ a = ace_helper('ipv4', src_addr: val, dst_addr: val)
102
+ assert_equal(exp, a.src_addr)
103
+ assert_equal(exp, a.dst_addr)
104
+
105
+ val = '10.1.1.1 2.3.4.5'
106
+ a = ace_helper('ipv4', src_addr: val, dst_addr: val)
107
+ assert_equal(val, a.src_addr)
108
+ assert_equal(val, a.dst_addr)
109
+
110
+ val = '10:1:1::1/128'
111
+ a = ace_helper('ipv6', src_addr: val, dst_addr: val)
112
+ assert_equal(val, a.src_addr)
113
+ assert_equal(val, a.dst_addr)
89
114
 
90
- props = {
91
- 'ipv4' => [attr_v4_1, attr_v4_2, attr_v4_3],
92
- 'ipv6' => [attr_v6_1, attr_v6_2, attr_v6_3],
93
- }
115
+ %w(ipv4 ipv6).each do |afi|
116
+ val = "addrgroup my_addrgroup_#{afi}"
117
+ a = ace_helper(afi, src_addr: val, dst_addr: val)
118
+ assert_equal(val, a.src_addr)
119
+ assert_equal(val, a.dst_addr)
120
+ end
121
+ end
94
122
 
123
+ def test_ports
95
124
  %w(ipv4 ipv6).each do |afi|
96
- @seqno = 0
97
- props[afi].each do |item|
98
- create_destroy_ace(afi, item)
125
+ ['eq 2', 'neq 2', 'gt 2', 'lt 2',
126
+ 'portgroup my_pg'].each do |val|
127
+ a = ace_helper(afi, src_port: val, dst_port: val)
128
+ assert_equal(val, a.src_port)
129
+ assert_equal(val, a.dst_port)
99
130
  end
100
131
  end
101
132
  end
102
133
 
103
- def create_destroy_ace(afi, entry)
104
- acl_name = @acl_name_v4 if afi[/(ip|ipv4)$/]
105
- acl_name = @acl_name_v6 if afi[/ipv6/]
106
- @seqno += 10
134
+ def test_dscp
135
+ %w(ipv4 ipv6).each do |afi|
136
+ %w(5 60 af11 af12 af13 af21 af22 af23 af31 af32 af33 af41 af42 af43
137
+ cs1 cs2 cs3 cs4 cs5 cs6 cs7 default ef).each do |val|
138
+ a = ace_helper(afi, dscp: val)
139
+ assert_equal(val, a.dscp)
140
+ end
141
+ end
142
+ end
143
+
144
+ def test_tcp_flags
145
+ %w(ipv4 ipv6).each do |afi|
146
+ %w(ack fin urg syn psh rst) + [
147
+ 'ack fin', 'ack psh rst'].each do |val|
148
+ a = ace_helper(afi, tcp_flags: val)
149
+ assert_equal(val, a.tcp_flags)
150
+ end
151
+ end
152
+ end
107
153
 
108
- Acl.new(afi, acl_name)
109
- ace = Ace.new(afi, acl_name, @seqno)
110
- ace.ace_set(entry)
154
+ def test_established
155
+ %w(ipv4 ipv6).each do |afi|
156
+ refute(ace_helper(afi).established)
157
+ a = ace_helper(afi, established: true)
158
+ assert(a.established)
159
+ a = ace_helper(afi, established: false)
160
+ refute(a.established)
161
+ end
162
+ end
111
163
 
112
- afi_cli = Acl.afi_cli(afi)
113
- all_aces = Ace.aces
114
- found = false
115
- all_aces[afi][acl_name].each do |seqno, _inst|
116
- next unless seqno.to_i == @seqno.to_i
117
- found = true
164
+ def test_http_method
165
+ afi = 'ipv4'
166
+ %w(connect delete get head post put trace).each do |val|
167
+ a = ace_helper(afi, http_method: val)
168
+ assert_equal(val, a.http_method)
118
169
  end
170
+ end
119
171
 
120
- @default_show_command =
121
- "show runn aclmgr | sec '#{afi_cli} access-list #{acl_name}'"
122
- assert(found,
123
- "#{afi_cli} acl #{acl_name} seqno #{@seqno} is not configured")
172
+ def test_log
173
+ %w(ipv4 ipv6).each do |afi|
174
+ refute(ace_helper(afi).log)
175
+ a = ace_helper(afi, log: true)
176
+ assert(a.log)
177
+ a = ace_helper(afi, log: false)
178
+ refute(a.log)
179
+ end
180
+ end
124
181
 
125
- if entry.include?(:action)
126
- action = "#{entry[:action]} .*"
127
- else
128
- action = "remark #{entry[:remark]}"
182
+ def test_precedence
183
+ afi = 'ipv4'
184
+ %w(critical flash flash-override immediate internet network
185
+ priority routine).each do |val|
186
+ a = ace_helper(afi, precedence: val)
187
+ assert_equal(val, a.precedence)
129
188
  end
130
- assert_show_match(pattern: /\s+#{@seqno} #{action}$/,
131
- msg: "failed to create ace seqno #{@seqno}")
132
- ace.destroy
133
- refute_show_match(pattern: /\s+#{@seqno} #{entry[:action]} .*$/,
134
- msg: "failed to remove ace seqno #{@seqno}")
135
189
  end
136
190
 
137
- def test_ace_update
138
- action = 'permit'
139
- proto = 'tcp'
140
- src = '1.0.0.0/8'
141
- dst = '3.0.0.0 0.0.0.8'
142
- entry = { action: action, proto: proto, src_addr: src, dst_addr: dst }
191
+ def test_redirect
192
+ afi = 'ipv4'
193
+ val = 'port-channel1,port-channel2'
194
+ a = ace_helper(afi, redirect: val)
195
+ assert_equal(val, a.redirect)
196
+ end
143
197
 
144
- a = Ace.new('ipv4', 'ace_update', 10)
145
- a.ace_set(entry)
198
+ def test_tcp_option_length
199
+ afi = 'ipv4'
200
+ %w(0 16 28).each do |val|
201
+ a = ace_helper(afi, tcp_option_length: val)
202
+ assert_equal(val, a.tcp_option_length)
203
+ end
204
+ end
146
205
 
147
- assert_equal(src, a.src_addr)
148
- assert_equal(dst, a.dst_addr)
206
+ def test_time_range
207
+ val = 'my_range'
208
+ %w(ipv4 ipv6).each do |afi|
209
+ a = ace_helper(afi, time_range: val)
210
+ assert_equal(val, a.time_range)
211
+ end
212
+ end
149
213
 
150
- src = '2.0.0.0/16'
151
- entry = { action: action, proto: proto, src_addr: src, dst_addr: dst }
152
- a.ace_set(entry)
153
- assert_equal(src, a.src_addr)
214
+ def test_packet_length
215
+ val = 'range 80 1000'
216
+ %w(ipv4 ipv6).each do |afi|
217
+ a = ace_helper(afi, packet_length: val)
218
+ assert_equal(val, a.packet_length)
219
+ end
220
+ end
154
221
 
155
- dst = '3.0.0.0 0.0.0.4'
156
- entry = { action: action, proto: proto, src_addr: src, dst_addr: dst }
157
- a.ace_set(entry)
158
- assert_equal(dst, a.dst_addr)
222
+ def test_ttl
223
+ val = '3'
224
+ %w(ipv4 ipv6).each do |afi|
225
+ a = ace_helper(afi, ttl: val)
226
+ skip("This property has a known defect on the platform itself -\n"\
227
+ 'CSCuy47463: access-list ttl does not nvgen') if a.ttl.nil?
228
+ assert_equal(val, a.ttl)
229
+ end
159
230
  end
160
231
  end
data/tests/test_acl.rb CHANGED
@@ -17,6 +17,7 @@ require_relative '../lib/cisco_node_utils/acl'
17
17
 
18
18
  # test client for acl creation and deletion
19
19
  class TestAcl < CiscoTestCase
20
+ @skip_unless_supported = 'acl'
20
21
  def setup
21
22
  # setup runs at the beginning of each test
22
23
  super
@@ -84,7 +85,7 @@ class TestAcl < CiscoTestCase
84
85
  # set to false
85
86
  rtr.stats_per_entry = false
86
87
  refute_show_match(pattern: /statistics per-entry/,
87
- msg: 'failed to disnable stats')
88
+ msg: 'failed to disable stats')
88
89
  refute(rtr.stats_per_entry)
89
90
 
90
91
  # default getter function
@@ -168,6 +169,14 @@ class TestAcl < CiscoTestCase
168
169
  end
169
170
 
170
171
  def test_fragments
172
+ if node.product_id[/N(5|6)/]
173
+ a = Acl.new('ipv4', 'acl_fragments')
174
+ assert_nil(a.fragments)
175
+ assert_nil(a.default_fragments)
176
+ assert_raises(Cisco::UnsupportedError) { a.fragments = 'permit-all' }
177
+ return
178
+ end
179
+
171
180
  %w(ipv4 ipv6).each do |afi|
172
181
  acl_name = afi[/ipv6/] ? @acl_name_v6 : @acl_name_v4
173
182
  fragments(afi, acl_name)
data/tests/test_bgp_af.rb CHANGED
@@ -30,34 +30,234 @@ class TestBgpAF < CiscoTestCase
30
30
  def setup
31
31
  super
32
32
  remove_all_bgps if @@pre_clean_needed
33
+ remove_all_vrfs if @@pre_clean_needed
34
+ if platform == :ios_xr && @@pre_clean_needed
35
+ config_no_warn('no route-policy drop_all')
36
+ end
33
37
  @@pre_clean_needed = false # rubocop:disable Style/ClassVars
34
38
  end
35
39
 
36
40
  def teardown
37
- super
38
41
  remove_all_bgps
42
+ remove_all_vrfs
43
+ config_no_warn('no route-policy drop_all') if platform == :ios_xr
44
+ super
39
45
  end
40
46
 
41
- def get_bgp_af_cfg(asn, vrf, af)
42
- afi, safi = af
43
- string =
44
- @device.cmd("show run bgp all | sec 'bgp #{asn}' | sec 'vrf #{vrf}' | " \
45
- "sec 'address-family #{afi} #{safi}' | no-more")
46
- string
47
- end
48
-
49
- # show bgp ipv4 unicast dampening parameters
50
- # Route Flap Dampening Parameters for VRF default Address family IPv4 Unicast:
51
- # Default values in use:
52
- # Half-life time : 15 mins
53
- # Suppress penalty : 2000
54
- # Reuse penalty : 750
55
- # Max suppress time : 45 mins
56
- # Max suppress penalty : 6000
57
- def get_bgp_af_dampening_params(_asn, vrf, af)
58
- afi = af.first
59
- safi = af.last
60
- @device.cmd("show bgp vrf #{vrf} #{afi} #{safi} dampening parameters")
47
+ # Disabling line length to support wide-format test matrix definition
48
+ # rubocop:disable Metrics/LineLength
49
+
50
+ # Address Families to test:
51
+ T_AFS = [
52
+ # afi safi
53
+ %w(ipv4 unicast),
54
+ %w(ipv6 unicast),
55
+ %w(ipv4 multicast),
56
+ %w(ipv6 multicast),
57
+ %w(l2vpn evpn),
58
+
59
+ # TODO: These are additional address families/modifiers reported by XR, should they be tested also?
60
+ # Looks like most of them are not supported on Nexus...
61
+ #
62
+
63
+ # %w(ipv4 mvpn),
64
+ # %w(ipv6 mvpn),
65
+
66
+ # Not on Nexus:
67
+ # %w(link-state link-state),
68
+ #
69
+ # %w(l2vpn mspw),
70
+ # %w(l2vpn vpls-vpws),
71
+ #
72
+ # %w(ipv4 flowspec),
73
+ # %w(ipv4 mdt),
74
+ # %w(ipv4 rt-filter),
75
+ # %w(ipv4 tunnel),
76
+ #
77
+ # %w(ipv6 flowspec),
78
+ #
79
+ # %w(vpnv4 unicast),
80
+ # %w(vpnv4 multicast),
81
+ # %w(vpnv4 flowspec),
82
+ #
83
+ # %w(vpnv6 unicast),
84
+ # %w(vpnv6 multicast),
85
+ # %w(vpnv6 flowspec),
86
+ ]
87
+
88
+ # ASs to test:
89
+ # TODO: Do we ever need to test more than one AS?
90
+ T_ASNS = ['55']
91
+
92
+ # VRFs to test:
93
+ T_VRFS = %w(default red)
94
+
95
+ # Value-based properties
96
+ T_VALUES = [
97
+ [:default_information_originate, [:toggle]],
98
+ [:client_to_client, [:toggle]],
99
+ [:additional_paths_send, [:toggle]],
100
+ [:additional_paths_receive, [:toggle]],
101
+ [:additional_paths_install, [:toggle]],
102
+ [:advertise_l2vpn_evpn, [:toggle]],
103
+
104
+ [:next_hop_route_map, ['drop_all']],
105
+ [:additional_paths_selection, ['drop_all']],
106
+ [:maximum_paths, [7, 9]],
107
+ [:maximum_paths_ibgp, [7, 9]],
108
+ [:dampen_igp_metric, [555, nil]],
109
+ [:default_metric, [50, false]],
110
+ [:inject_map, [[%w(lax sfo), %w(lax sjc), %w(nyc sfo copy-attributes), %w(sjc nyc copy-attributes)], [%w(nyc sfo copy-attributes), %w(sjc nyc copy-attributes)]]],
111
+ ]
112
+
113
+ # Given the cartesian product of the above parameters, not all tests are supported.
114
+ # Here we record which tests are expected to fail, and what kind of failure is expected.
115
+ # This supports a very simple workflow for adding new tests:
116
+ # - Add new entry into test tables above.
117
+ # - Run tests.
118
+ # - When test fails, add a new 'exception' entry.
119
+ # - Repeat until all tests pass.
120
+ # - Condense entries using :any where possible.
121
+ #
122
+ TEST_EXCEPTIONS = [
123
+ # Test OS VRF AF Expected result
124
+
125
+ # Tests that are successful even though a rule below says otherwise
126
+ [:next_hop_route_map, :nexus, 'default', %w(l2vpn evpn), :success],
127
+
128
+ # XR CLI Errors
129
+ [:additional_paths_send, :ios_xr, :any, :multicast, :CliError],
130
+ [:additional_paths_receive, :ios_xr, :any, :multicast, :CliError],
131
+ [:additional_paths_selection, :ios_xr, :any, :multicast, :CliError],
132
+ [:client_to_client, :ios_xr, :VRF, :any, :CliError],
133
+ [:maximum_paths, :ios_xr, :any, %w(l2vpn evpn), :CliError],
134
+ [:maximum_paths_ibgp, :ios_xr, :any, %w(l2vpn evpn), :CliError],
135
+ [:next_hop_route_map, :ios_xr, :VRF, :any, :CliError],
136
+
137
+ # Nexus Unsupported
138
+
139
+ # Nexus CLI Errors
140
+ [:any, :nexus, 'default', %w(l2vpn evpn), :CliError],
141
+ [:advertise_l2vpn_evpn, :nexus, 'default', :any, :CliError],
142
+ [:advertise_l2vpn_evpn, :nexus, :VRF, :multicast, :CliError],
143
+ [:inject_map, :nexus, :any, :multicast, :CliError],
144
+ ]
145
+
146
+ # rubocop:disable Style/SpaceAroundOperators
147
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
148
+ def check_test_exceptions(test_, os_, vrf_, af_)
149
+ ret = nil
150
+ amb = nil
151
+ TEST_EXCEPTIONS.each do |test, os, vrf, af, expect|
152
+ next unless (test_ == test || test == :any) &&
153
+ (os_ == os || os == :any) &&
154
+ (vrf_ == vrf || vrf == :any ||
155
+ (vrf == :VRF && vrf_ != 'default')) &&
156
+ (af_ == af || af == :any ||
157
+ (af == :unicast && (af_.include? 'unicast')) ||
158
+ (af == :multicast && (af_.include? 'multicast')) ||
159
+ (af == :ipv4 && (af_.include? 'ipv4')) ||
160
+ (af == :ipv6 && (af_.include? 'ipv6')))
161
+ return expect if expect == :success || expect == :skip
162
+
163
+ # Otherwise, make sure there's no ambiguity/overlap in the exceptions.
164
+ if !ret.nil? && ret != expect
165
+ assert('TEST ERROR: Exceptions matrix has ambiguous entries! ' \
166
+ "#{amb} and [#{test}, #{os}, #{vrf}, #{af}]")
167
+ end
168
+ ret = expect
169
+ amb = [test, os, vrf, af, expect]
170
+ end
171
+ # Return the expected test result
172
+ ret.nil? ? :success : ret
173
+ end
174
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
175
+ # rubocop:enable Style/SpaceAroundOperators
176
+
177
+ def properties_matrix(asns, vrfs, afs, values)
178
+ asns.each do |asn|
179
+ config_ios_xr_dependencies(asn)
180
+
181
+ vrfs.each do |vrf|
182
+ afs.each do |af|
183
+ # l2vpn evpn restrictions
184
+ if af == %w(l2vpn evpn)
185
+ next if vrf != 'default' ||
186
+ validate_property_excluded?('feature', 'nv_overlay_evpn')
187
+ end
188
+
189
+ bgp_af = RouterBgpAF.new(asn, vrf, af)
190
+
191
+ values.each do |test, test_values|
192
+ if validate_property_excluded?('bgp_af', test.to_s)
193
+ assert_raises(Cisco::UnsupportedError) { bgp_af.send("#{test}=", nil) }
194
+ next
195
+ end
196
+
197
+ # What result do we expect from this test?
198
+ expect = check_test_exceptions(test, platform, vrf, af)
199
+
200
+ # Gather initial value, default value, and the first test value..
201
+ initial = bgp_af.send(test)
202
+
203
+ # Properties which are unsupported or OFF by default return initial == nil
204
+ if initial.nil?
205
+ default = nil
206
+ first_value = nil
207
+ else
208
+ default = bgp_af.send("default_#{test}")
209
+ first_value = (test_values[0] == :toggle) ? !default : test_values[0]
210
+ end
211
+
212
+ if expect == :skip
213
+ # Do nothing..
214
+
215
+ elsif expect == :CliError
216
+
217
+ # This set of parameters should produce a CLI error
218
+ assert_raises(Cisco::CliError,
219
+ "Assert 'cli error' failed for: "\
220
+ "#{test}=(#{first_value}), #{asn}, #{vrf}, #{af}") do
221
+ bgp_af.send("#{test}=", first_value)
222
+ end
223
+
224
+ else
225
+
226
+ # Check initial value == default value
227
+ # Skip this assertion for properties that use auto_default: false
228
+ assert_equal(default, initial,
229
+ "Initial value failed for: #{test}, #{asn}, #{vrf}, #{af}"
230
+ ) unless initial.nil?
231
+
232
+ # Try all the test values in order
233
+ test_values.each do |test_value|
234
+ test_value = (test_value == :toggle) ? !default : test_value
235
+
236
+ # Try the test value
237
+ bgp_af.send("#{test}=", test_value)
238
+ assert_equal(test_value, bgp_af.send(test),
239
+ "Test value failed for: #{test}, #{asn}, #{vrf}, #{af}")
240
+ end # test_values
241
+
242
+ # Set it back to the default
243
+ unless default.nil?
244
+ bgp_af.send("#{test}=", default)
245
+ assert_equal(default, bgp_af.send(test),
246
+ "Default assignment failed for: #{test}, #{asn}, #{vrf}, #{af}")
247
+ end
248
+ end
249
+
250
+ # Cleanup
251
+ bgp_af.destroy
252
+ end # tests
253
+ end # afs
254
+ end # vrfs
255
+ end # asns
256
+ end
257
+ # rubocop:enable Metrics/LineLength
258
+
259
+ def test_properties_matrix
260
+ properties_matrix(T_ASNS, T_VRFS, T_AFS, T_VALUES)
61
261
  end
62
262
 
63
263
  ##
@@ -77,17 +277,27 @@ class TestBgpAF < CiscoTestCase
77
277
  ## Enable VXLAN and the EVPN
78
278
  ##
79
279
  def test_collection_not_empty
80
- config('feature bgp',
81
- 'router bgp 55',
82
- 'address-family ipv4 unicast',
83
- 'vrf red',
84
- 'address-family ipv4 unicast',
85
- 'vrf blue',
86
- 'address-family ipv6 multicast',
87
- 'vrf orange',
88
- 'address-family ipv4 multicast',
89
- 'vrf black',
90
- 'address-family ipv6 unicast')
280
+ config('feature bgp') if platform == :nexus
281
+
282
+ bgp_afs = []
283
+ %w(default red blue orange black).each do |vrf|
284
+ [%w(ipv4 unicast), %w(ipv6 unicast),
285
+ %w(ipv4 multicast), %w(ipv6 multicast)].each do |af|
286
+ config_ios_xr_dependencies(55, vrf)
287
+ bgp_afs.push(RouterBgpAF.new(55, vrf, af))
288
+ end
289
+ end
290
+
291
+ # config('router bgp 55',
292
+ # 'address-family ipv4 unicast',
293
+ # 'vrf red',
294
+ # 'address-family ipv4 unicast',
295
+ # 'vrf blue',
296
+ # 'address-family ipv6 multicast',
297
+ # 'vrf orange',
298
+ # 'address-family ipv4 multicast',
299
+ # 'vrf black',
300
+ # 'address-family ipv6 unicast')
91
301
 
92
302
  # Construct a hash of routers, vrfs, afs
93
303
  routers = RouterBgpAF.afs
@@ -106,449 +316,73 @@ class TestBgpAF < CiscoTestCase
106
316
  afi = af_key[0]
107
317
  safi = af_key[1]
108
318
  assert(afi.length > 0, 'Error: AFI length is zero')
109
- assert_match(/^ipv[46]/, afi, 'Error: AFI must be ipv4 or ipv6')
319
+ assert_match(/^(ip|vpn)v[46]/, afi,
320
+ 'Error: AFI must be vpnv4, ipv4, vpnv6 or ipv6')
110
321
  assert(safi.length > 0, 'Error: SAFI length is zero')
322
+ assert_match(/^(un|mult)icast/, safi,
323
+ 'Error: AFI must be unicast or multicast')
111
324
  end
112
325
  end
113
326
  end
114
327
  end
115
328
 
116
- ########################################################
117
- # PROPERTIES #
118
- ########################################################
119
-
120
- ##
121
- ## default-information originate
122
- ##
123
- def test_default_information_originate
124
- asn = '55'
125
- vrf = 'red'
126
- af = %w(ipv4 unicast)
127
-
128
- #
129
- # Set and verify
130
- #
131
- bgp_af = RouterBgpAF.new(asn, vrf, af)
132
- bgp_af.default_information_originate = true
133
- assert(bgp_af.default_information_originate,
134
- 'Error: default-information originate not set')
135
-
136
- pattern = /^ *default-information originate$/
137
- af_string = get_bgp_af_cfg(asn, vrf, af)
138
-
139
- assert_match(pattern, af_string,
140
- "Error: 'default_information originate' is not" \
141
- ' configured and should be')
142
-
143
- #
144
- # Unset and verify
145
- #
146
-
147
- # Do a 'no default-information originate'
148
- bgp_af.default_information_originate = false
149
-
150
- pattern = /^ *default-information originate$/
151
- af_string = get_bgp_af_cfg(asn, vrf, af)
152
-
153
- refute_match(pattern, af_string,
154
- "Error: 'default_information originate' " \
155
- 'is configured and should not be')
156
- end
157
-
158
- ##
159
- ## client-to-client reflection
160
- ##
161
- def test_client_to_client
162
- asn = '55'
163
- vrf = 'red'
164
- af = %w(ipv4 unicast)
165
-
166
- bgp_af = RouterBgpAF.new(asn, vrf, af)
167
- #
168
- # Default is 'client-to-client' is configured
169
- #
170
- assert(bgp_af.client_to_client,
171
- "Error: 'client-to-client is not configured but should be")
172
- #
173
- # Unset and verify
174
- #
175
-
176
- # Do a 'no client-to-client reflection'
177
- bgp_af.client_to_client = false
178
- pattern = /^ *no client-to-client reflection$/
179
- af_string = get_bgp_af_cfg(asn, vrf, af)
180
-
181
- assert_match(pattern, af_string,
182
- "Error: 'no client-to-client' is not configured and should be")
183
-
184
- #
185
- # Set and verify
186
- #
187
-
188
- # Do a 'client-to-client reflection'
189
- bgp_af.client_to_client = true
190
- af_string = get_bgp_af_cfg(asn, vrf, af)
191
-
192
- refute_match(pattern, af_string,
193
- "Error: 'no client-to-client' is configured and should not be")
194
- end
195
-
196
- ##
197
- ## next_hop route-map
198
- ##
199
- def test_next_hop_route_map
200
- asn = '55'
201
- vrf = 'red'
202
- af = %w(ipv4 unicast)
203
-
204
- #
205
- # Set and verify
206
- #
207
- bgp_af = RouterBgpAF.new(asn, vrf, af)
208
- bgp_af.next_hop_route_map = 'drop_all'
209
- assert_match(bgp_af.next_hop_route_map, 'drop_all',
210
- 'Error: nexthop route-map not set')
211
- pattern = /^ *nexthop route-map drop_all$/
212
- af_string = get_bgp_af_cfg(asn, vrf, af)
213
-
214
- assert_match(pattern, af_string,
215
- "Error: 'nexthop route-map drop_all' is " \
216
- 'not configured and should be')
217
-
218
- #
219
- # Unset and verify
220
- #
221
-
222
- # Do a 'no nexthop route-map drop_all'
223
- bgp_af.next_hop_route_map = bgp_af.default_next_hop_route_map
224
- af_string = get_bgp_af_cfg(asn, vrf, af)
225
-
226
- refute_match(pattern, af_string,
227
- "Error: 'nexthop route-map drop_all' is " \
228
- 'configured and should not be')
229
- end
230
-
231
- ##
232
- ## additional_paths
233
- ##
234
- def test_additional_paths
235
- asn = '55'
236
- vrf = 'red'
237
- af = %w(ipv4 unicast)
238
-
239
- bgp_af = RouterBgpAF.new(asn, vrf, af)
240
-
241
- pattern_send = 'additional-paths send'
242
- pattern_receive = 'additional-paths receive'
243
- pattern_install = 'additional-paths install backup'
244
-
245
- #
246
- # Default is not configured
247
- #
248
- af_string = get_bgp_af_cfg(asn, vrf, af)
249
-
250
- [pattern_send, pattern_receive, pattern_install].each do |pat|
251
- refute_match(pat, af_string,
252
- "Error: '#{pat}' is configured but should not be")
253
- end
254
-
255
- #
256
- # Test default and getter methods
257
- #
258
- assert_equal(bgp_af.default_additional_paths_send,
259
- bgp_af.additional_paths_send)
260
- assert_equal(bgp_af.default_additional_paths_receive,
261
- bgp_af.additional_paths_receive)
262
- assert_equal(bgp_af.default_additional_paths_install,
263
- bgp_af.additional_paths_install)
264
-
265
- #
266
- # Set and verify
267
- #
268
-
269
- # Do a 'additional-paths send, receive, install'
270
- bgp_af.additional_paths_send = true
271
- bgp_af.additional_paths_receive = true
272
- bgp_af.additional_paths_install = true
273
-
274
- af_string = get_bgp_af_cfg(asn, vrf, af)
275
-
276
- [pattern_send, pattern_receive, pattern_install].each do |pat|
277
- assert_match(pat, af_string,
278
- "Error: '#{pat}' is not configured and should be")
279
- end
280
-
281
- #
282
- # Test getter
283
- #
284
-
285
- assert(bgp_af.additional_paths_send)
286
- assert(bgp_af.additional_paths_receive)
287
- assert(bgp_af.additional_paths_install)
288
-
289
- #
290
- # Unset and verify
291
- #
292
-
293
- # Do a 'no additional-paths send, receive, install'
294
- bgp_af.additional_paths_send = false
295
- bgp_af.additional_paths_receive = false
296
- bgp_af.additional_paths_install = false
297
-
298
- af_string = get_bgp_af_cfg(asn, vrf, af)
299
-
300
- [pattern_send, pattern_receive, pattern_install].each do |pat|
301
- refute_match(pat, af_string,
302
- "Error: '#{pat}' is configured but should not be")
303
- end
304
- end
305
-
306
- ##
307
- ## additional_paths_selection route-map
308
- ##
309
- def test_additional_paths_selection
310
- asn = '55'
311
- vrf = 'red'
312
- af = %w(ipv4 unicast)
313
-
314
- #
315
- # Set and verify
316
- #
317
- bgp_af = RouterBgpAF.new(asn, vrf, af)
318
- bgp_af.additional_paths_selection = 'drop_all'
319
-
320
- assert_equal(bgp_af.additional_paths_selection, 'drop_all',
321
- 'Error: additional-paths selection route-map not set')
322
-
323
- af_string = get_bgp_af_cfg(asn, vrf, af)
324
- pattern = /^ *additional-paths selection route-map drop_all$/
325
-
326
- assert_match(pattern, af_string,
327
- "Error: 'additional-paths selection route-map drop_all' is " \
328
- 'not configured and should be')
329
-
330
- #
331
- # Test getter
332
- #
333
- pattern = /^ *drop_all$/
334
- assert_match(pattern, bgp_af.additional_paths_selection,
335
- "Error: 'route-map drop_all' is not configured and should be")
336
-
337
- #
338
- # Unset and verify
339
- #
329
+ def config_ios_xr_dependencies(asn, vrf='red')
330
+ return unless platform == :ios_xr
331
+ # These dependencies are required on ios xr
340
332
 
341
- # Do a 'no additional-paths selection route-map drop_all'
342
- bgp_af.additional_paths_selection =
343
- bgp_af.default_additional_paths_selection
333
+ # "rd auto" required, otherwise XR reports:
334
+ # 'The RD for the VRF must be present before an
335
+ # address family is activated'
344
336
 
345
- af_string = get_bgp_af_cfg(asn, vrf, af)
337
+ # "bgp router-id" requred, otherwise XR reports:
338
+ # 'BGP router ID must be configured.'
346
339
 
347
- refute_match(pattern, af_string,
348
- "Error: 'additional-paths selection route-map drop_all' is " \
349
- 'configured and should not be')
350
- end
340
+ # "address-family vpnv4 unicast" required, otherwise XR reports:
341
+ # 'The parent address family has not been initialized'
351
342
 
352
- ##
353
- ## advertise_l2vpn_evpn
354
- ##
355
- def advertise_l2vpn_evpn(asn, vrf, af)
356
- bgp_af = RouterBgpAF.new(asn, vrf, af)
357
-
358
- #
359
- # Set and verify
360
- #
361
- val = false
362
- bgp_af.advertise_l2vpn_evpn = val
363
- assert_equal(val, bgp_af.advertise_l2vpn_evpn,
364
- 'Error: advertise l2vpn evpn value does not match set value')
343
+ cfg = ["router bgp #{asn}",
344
+ 'bgp router-id 10.1.1.1',
345
+ 'address-family vpnv4 unicast',
346
+ 'address-family vpnv6 unicast',
347
+ 'address-family vpnv4 multicast',
348
+ 'address-family vpnv6 multicast',
349
+ ]
350
+ cfg << "vrf #{vrf}" << 'rd auto' unless vrf == 'default'
351
+ config(cfg)
365
352
 
366
- val = true
367
- bgp_af.advertise_l2vpn_evpn = val
368
- assert_equal(val, bgp_af.advertise_l2vpn_evpn,
369
- 'Error: advertise l2vpn evpn value does not match set value')
370
-
371
- val = bgp_af.default_advertise_l2vpn_evpn
372
- bgp_af.advertise_l2vpn_evpn = val
373
- assert_equal(val, bgp_af.advertise_l2vpn_evpn,
374
- 'Error: advertise l2vpn evpn value does not match default' \
375
- 'value')
376
- end
353
+ # Needed for testing route-policy commands
354
+ config_no_warn('route-policy drop_all', 'end-policy')
377
355
 
378
- def test_advertise_l2vpn_evpn
379
- afs = [%w(ipv4 unicast), %w(ipv6 unicast)]
380
- afs.each do |af|
381
- advertise_l2vpn_evpn(55, 'red', af)
382
- end
356
+ # TBD: Reduce the number of different route-policies used by this test
357
+ # and move the remaining ones into this method. Then create an
358
+ # unconfig_ios_xr_dependencies to handle the cleanups.
383
359
  end
384
360
 
385
- ##
386
- ## get_dampen_igp_metric
387
- ##
388
- def test_dampen_igp_metric
389
- asn = '44'
390
- vrf = 'green'
391
- af = %w(ipv4 multicast)
392
-
393
- bgp_af = RouterBgpAF.new(asn, vrf, af)
394
-
395
- #
396
- # Verify default value
397
- #
398
- assert_equal(bgp_af.dampen_igp_metric, bgp_af.default_dampen_igp_metric,
399
- "Error: Default 'dampen-igp-metric' value should be " \
400
- "#{bgp_af.default_dampen_igp_metric}")
401
-
402
- #
403
- # Set and verify 'dampen-igp-metric <value>'
404
- #
405
-
406
- # Do a 'dampen-igp-metric 555'
407
- pattern = /^ *dampen-igp-metric 555$/
408
- bgp_af.dampen_igp_metric = 555
409
-
410
- af_string = get_bgp_af_cfg(asn, vrf, af)
411
-
412
- assert_match(pattern, af_string,
413
- "Error: 'dampen-igp-metric 555' is not configured " \
414
- 'and should be')
415
- #
416
- # Test getter
417
- #
418
- assert_equal(bgp_af.dampen_igp_metric, 555,
419
- 'Error: dampen_igp_metric should be 555')
420
-
421
- #
422
- # Set and verify 'no dampen-igp-metric'
423
- #
424
-
425
- # Do a 'no dampen-igp-metric'
426
- pattern = /no dampen-igp-metric$/
427
- bgp_af.dampen_igp_metric = nil
428
-
429
- af_string = get_bgp_af_cfg(asn, vrf, af)
430
-
431
- assert_match(pattern, af_string,
432
- "Error: 'no dampen-igp-metric' is not configured " \
433
- 'and should be')
434
- #
435
- # Test getter
436
- #
437
- assert_equal(bgp_af.dampen_igp_metric, nil,
438
- 'Error: dampen_igp_metric should be nil')
439
-
440
- #
441
- # Set default value explicitly
442
- #
443
- bgp_af.dampen_igp_metric = bgp_af.default_dampen_igp_metric
444
- assert_equal(bgp_af.dampen_igp_metric, bgp_af.default_dampen_igp_metric,
445
- "Error: Default 'dampen-igp-metric' value should be " \
446
- "#{bgp_af.default_dampen_igp_metric}")
447
- end
361
+ ########################################################
362
+ # PROPERTIES #
363
+ ########################################################
448
364
 
449
- ##
450
- ## dampening
451
- ##
452
- # rubocop:disable Metrics/MethodLength
453
365
  def test_dampening
454
366
  asn = '101'
455
-
456
- ############################################
457
- # Set and verify 'dampening' with defaults #
458
- ############################################
459
- vrf = 'orange'
460
367
  af = %w(ipv4 unicast)
368
+ if platform == :nexus
369
+ vrf = 'orange'
370
+ elsif platform == :ios_xr
371
+ vrf = 'default'
372
+ config_ios_xr_dependencies(asn, vrf)
373
+ config_no_warn('route-policy DropAllTraffic', 'end-policy')
374
+ end
461
375
  bgp_af = RouterBgpAF.new(asn, vrf, af)
462
376
 
463
377
  # Test no dampening configured
464
378
  assert_nil(bgp_af.dampening)
465
379
 
466
- pattern = /^ *dampening$/
467
-
468
- bgp_af.dampening = []
469
-
470
- # Check property got set
471
- af_string = get_bgp_af_cfg(asn, vrf, af)
472
-
473
- assert_match(pattern, af_string,
474
- "Error: 'dampening' is not configured and should be")
475
-
476
- # Check properties got set
477
- af_string = get_bgp_af_dampening_params(asn, vrf, af)
478
-
479
- pattern_params1 = 'Half-life time : 15 mins'
480
- pattern_params2 = 'Suppress penalty : 2000'
481
- pattern_params3 = 'Reuse penalty : 750'
482
- pattern_params4 = 'Max suppress time : 45 mins'
483
- pattern_params5 = 'Max suppress penalty : 6000'
484
-
485
- error = ("Error: 'dampening' properties are incorrect")
486
-
487
- assert_match(pattern_params1, af_string, error)
488
- assert_match(pattern_params2, af_string, error)
489
- assert_match(pattern_params3, af_string, error)
490
- assert_match(pattern_params4, af_string, error)
491
- assert_match(pattern_params5, af_string, error)
492
-
493
- # Check getter
494
- assert_empty(bgp_af.dampening, 'Error: dampening is configured and ' \
495
- 'should not be')
496
-
497
- #
498
- # Unset and verify
499
- #
500
- bgp_af.dampening = nil
501
-
502
- af_string = get_bgp_af_cfg(asn, vrf, af)
503
- pattern = /^ *dampening$/
504
-
505
- refute_match(pattern, af_string, "Error: 'dampening' is still configured")
506
-
507
- #
508
- # Test Getters
509
- #
510
- assert_nil(bgp_af.dampening)
511
- assert_nil(bgp_af.dampening_half_time)
512
- assert_nil(bgp_af.dampening_reuse_time)
513
- assert_nil(bgp_af.dampening_suppress_time)
514
- assert_nil(bgp_af.dampening_max_suppress_time)
515
- assert_nil(bgp_af.dampening_routemap)
516
-
517
- bgp_af.destroy
518
-
519
380
  #############################################
520
381
  # Set and verify 'dampening' with overrides #
521
382
  #############################################
522
- vrf = 'green'
523
- af = %w(ipv4 multicast)
524
- bgp_af = RouterBgpAF.new(asn, vrf, af)
525
383
 
526
384
  bgp_af.dampening = %w(1 2 3 4)
527
385
 
528
- # Check property got set
529
- af_string = get_bgp_af_cfg(asn, vrf, af)
530
- pattern = /^ *dampening 1 2 3 4$/
531
-
532
- assert_match(pattern, af_string,
533
- "Error: 'dampening' is not configured and should be")
534
-
535
- # Check properties got set
536
- af_string = get_bgp_af_dampening_params(asn, vrf, af)
537
-
538
- pattern_params1 = 'Half-life time : 1 mins'
539
- pattern_params2 = 'Suppress penalty : 3'
540
- pattern_params3 = 'Reuse penalty : 2'
541
- pattern_params4 = 'Max suppress time : 4 mins'
542
- pattern_params5 = 'Max suppress penalty : 32'
543
-
544
- error = ("Error: 'dampening' properties are incorrect")
545
-
546
- assert_match(pattern_params1, af_string, error)
547
- assert_match(pattern_params2, af_string, error)
548
- assert_match(pattern_params3, af_string, error)
549
- assert_match(pattern_params4, af_string, error)
550
- assert_match(pattern_params5, af_string, error)
551
-
552
386
  # Check getters
553
387
  assert_equal(bgp_af.dampening, %w(1 2 3 4),
554
388
  'Error: dampening getter did not match')
@@ -563,92 +397,28 @@ class TestBgpAF < CiscoTestCase
563
397
  assert_empty(bgp_af.dampening_routemap,
564
398
  'A routemap should not be configured')
565
399
 
566
- #
567
- # Unset and verify
568
- #
569
- bgp_af.dampening = nil
570
-
571
- af_string = get_bgp_af_cfg(asn, vrf, af)
572
- pattern = /^ *dampening$/
573
-
574
- refute_match(pattern, af_string, "Error: 'dampening' is still configured")
575
-
576
400
  #############################################
577
401
  # Set and verify 'dampening' with route-map #
578
402
  #############################################
579
- vrf = 'brown'
580
- af = %w(ipv6 unicast)
581
- bgp_af = RouterBgpAF.new(asn, vrf, af)
582
403
 
583
404
  bgp_af.dampening = 'DropAllTraffic'
584
405
 
585
- pattern = /^ *dampening route-map DropAllTraffic$/
586
-
587
- # Check property got set
588
- af_string = get_bgp_af_cfg(asn, vrf, af)
589
-
590
- assert_match(pattern, af_string,
591
- "Error: 'dampening' is not configured and should be")
592
-
593
- # Check properties got set
594
- af_string = get_bgp_af_dampening_params(asn, vrf, af)
595
- pattern_params = 'Dampening policy configured: DropAllTraffic'
596
-
597
- assert_match(pattern_params, af_string,
598
- 'Error: dampening properties DropAllTraffic is not ' \
599
- 'configured and should be')
600
-
601
406
  # Check getters
602
- assert_equal(bgp_af.dampening, 'DropAllTraffic',
603
- 'Error: dampening getter did not match')
604
- assert_equal(bgp_af.dampening_routemap, 'DropAllTraffic',
605
- 'Error: dampening getter did not match')
606
-
607
- #
608
- # Unset and verify
609
- #
610
- bgp_af.dampening = nil
611
- af_string = get_bgp_af_cfg(asn, vrf, af)
612
- pattern = /^ *dampening$/
613
-
614
- refute_match(pattern, af_string, "Error: 'dampening' is still configured")
407
+ assert_equal('DropAllTraffic', bgp_af.dampening)
408
+ assert_equal('DropAllTraffic', bgp_af.dampening_routemap)
615
409
 
616
410
  #############################################
617
- # Set and verify 'dampening' with default #
411
+ # Set and verify 'dampening' to defaults #
618
412
  #############################################
619
- vrf = 'sangria'
620
- af = %w(ipv4 multicast)
621
- bgp_af = RouterBgpAF.new(asn, vrf, af)
622
413
 
623
414
  bgp_af.dampening = bgp_af.default_dampening
624
415
 
625
- # Check property got set
626
- af_string = get_bgp_af_cfg(asn, vrf, af)
627
-
628
- assert_match(pattern, af_string,
629
- "Error: 'dampening' is not configured and should be")
630
-
631
- # Check properties got set
632
- af_string = get_bgp_af_dampening_params(asn, vrf, af)
633
-
634
- pattern_params1 = 'Half-life time : 15 mins'
635
- pattern_params2 = 'Suppress penalty : 2000'
636
- pattern_params3 = 'Reuse penalty : 750'
637
- pattern_params4 = 'Max suppress time : 45 mins'
638
- pattern_params5 = 'Max suppress penalty : 6000'
639
-
640
- error = ("Error: 'dampening' properties are incorrect")
416
+ # Check getters
641
417
 
642
- assert_match(pattern_params1, af_string, error)
643
- assert_match(pattern_params2, af_string, error)
644
- assert_match(pattern_params3, af_string, error)
645
- assert_match(pattern_params4, af_string, error)
646
- assert_match(pattern_params5, af_string, error)
418
+ assert_equal(bgp_af.default_dampening, bgp_af.dampening)
647
419
 
648
- # Check getters
649
- assert_empty(bgp_af.dampening, 'Error: dampening not configured ' \
650
- 'and should be')
651
- assert_equal(bgp_af.default_dampening_half_time, bgp_af.dampening_half_time,
420
+ assert_equal(bgp_af.default_dampening_half_time,
421
+ bgp_af.dampening_half_time,
652
422
  'Wrong default dampening half_time value configured')
653
423
  assert_equal(bgp_af.default_dampening_reuse_time,
654
424
  bgp_af.dampening_reuse_time,
@@ -663,15 +433,20 @@ class TestBgpAF < CiscoTestCase
663
433
  bgp_af.dampening_routemap,
664
434
  'The default dampening routemap should configured')
665
435
 
666
- #
667
- # Unset and verify
668
- #
436
+ ############################################
437
+ # Turn off 'dampening' #
438
+ ############################################
439
+
669
440
  bgp_af.dampening = nil
670
- af_string = get_bgp_af_cfg(asn, vrf, af)
441
+ assert_nil(bgp_af.dampening)
442
+ assert_nil(bgp_af.dampening_half_time)
443
+ assert_nil(bgp_af.dampening_reuse_time)
444
+ assert_nil(bgp_af.dampening_suppress_time)
445
+ assert_nil(bgp_af.dampening_max_suppress_time)
446
+ assert_nil(bgp_af.dampening_routemap)
671
447
 
672
- refute_match(pattern, af_string, "Error: 'dampening' is still configured")
448
+ bgp_af.destroy
673
449
  end
674
- # rubocop:enable Metrics/AbcSize,Metrics/MethodLength
675
450
 
676
451
  ##
677
452
  ## distance
@@ -681,6 +456,7 @@ class TestBgpAF < CiscoTestCase
681
456
  vrf = 'red'
682
457
  af = %w(ipv4 unicast)
683
458
 
459
+ config_ios_xr_dependencies(asn)
684
460
  bgp_af = RouterBgpAF.new(asn, vrf, af)
685
461
  distance = [{ ebgp: 20, ibgp: 40, local: 60 },
686
462
  { ebgp: bgp_af.default_distance_ebgp,
@@ -705,163 +481,6 @@ class TestBgpAF < CiscoTestCase
705
481
  bgp_af.destroy
706
482
  end
707
483
 
708
- ##
709
- ## default_metric
710
- ##
711
- def default_metric(asn, vrf, af)
712
- bgp_af = RouterBgpAF.new(asn, vrf, af)
713
-
714
- refute(bgp_af.default_default_metric,
715
- 'default value for default default metric should be false')
716
- #
717
- # Set and verify
718
- #
719
- val = 50
720
- bgp_af.default_metric = val
721
- assert_equal(val, bgp_af.default_metric,
722
- 'Error: default metric value does not match set value')
723
-
724
- val = bgp_af.default_default_metric
725
- bgp_af.default_metric = val
726
- assert_equal(val, bgp_af.default_metric,
727
- 'Error: default metric value does not match default' \
728
- 'value')
729
- end
730
-
731
- def test_default_metric
732
- afs = [%w(ipv4 unicast), %w(ipv6 unicast)]
733
- afs.each do |af|
734
- default_metric(55, 'red', af)
735
- end
736
- end
737
-
738
- ##
739
- ## inject_map
740
- ##
741
- def inject_map(asn, vrf, af)
742
- # rubocop:disable Style/WordArray
743
- master = [['lax', 'sfo'],
744
- ['lax', 'sjc'],
745
- ['nyc', 'sfo', 'copy-attributes'],
746
- ['sjc', 'nyc', 'copy-attributes']]
747
- bgp_af = RouterBgpAF.new(asn, vrf, af)
748
-
749
- # Test1: both/import/export when no commands are present. Each target
750
- # option will be tested with and without evpn (6 separate types)
751
- should = master.clone
752
- inject_map_tester(bgp_af, should, 'Test 1')
753
-
754
- # Test 2: remove half of the entries
755
- should = [['lax', 'sfo'], ['nyc', 'sfo', 'copy-attributes']]
756
- # rubocop:enable Style/WordArray
757
- inject_map_tester(bgp_af, should, 'Test 2')
758
-
759
- # Test 3: restore the removed entries
760
- should = master.clone
761
- inject_map_tester(bgp_af, should, 'Test 3')
762
-
763
- # Test 4: 'default'
764
- should = bgp_af.default_inject_map
765
- inject_map_tester(bgp_af, should, 'Test 4')
766
- end
767
-
768
- def inject_map_tester(bgp_af, should, test_id)
769
- bgp_af.send('inject_map=', should)
770
- result = bgp_af.send('inject_map')
771
- assert_equal(should, result,
772
- "#{test_id} : inject_map")
773
- end
774
-
775
- def test_inject_map
776
- afs = [%w(ipv4 unicast), %w(ipv6 unicast)]
777
- afs.each do |af|
778
- inject_map(55, 'red', af)
779
- end
780
- end
781
-
782
- ##
783
- ## maximum_paths
784
- ##
785
- def maximum_paths(asn, vrf, af)
786
- bgp_af = RouterBgpAF.new(asn, vrf, af)
787
-
788
- #
789
- # Set and verify
790
- #
791
- val = 7
792
- bgp_af.maximum_paths = val
793
- assert_equal(bgp_af.maximum_paths, val,
794
- 'Error: maximum paths value not match to set value')
795
-
796
- val = 9
797
- bgp_af.maximum_paths = val
798
- assert_equal(bgp_af.maximum_paths, val,
799
- 'Error: maximum paths value not match to set value')
800
-
801
- val = bgp_af.default_maximum_paths
802
- bgp_af.maximum_paths = val
803
- assert_equal(bgp_af.maximum_paths, val,
804
- 'Error: maximum paths value not match to default value')
805
- end
806
-
807
- def test_maximum_paths
808
- vrfs = %w(default red)
809
- afs = [%w(ipv4 unicast), %w(ipv6 unicast)]
810
- vrfs.each do |vrf|
811
- afs.each do |af|
812
- maximum_paths(55, vrf, af)
813
- end
814
- end
815
- end
816
-
817
- ##
818
- ## maximum_paths_ibgp
819
- ##
820
- def maximum_paths_ibgp(asn, vrf, af)
821
- /ipv4/.match(af) ? af = %w(ipv4 unicast) : af = %w(ipv6 unicast)
822
- bgp_af = RouterBgpAF.new(asn, vrf, af)
823
-
824
- #
825
- # Set and verify
826
- #
827
- val = 7
828
- bgp_af.maximum_paths_ibgp = val
829
- assert_equal(bgp_af.maximum_paths_ibgp, val,
830
- 'Error: maximum paths ibgp value not match to set value')
831
-
832
- val = 9
833
- bgp_af.maximum_paths_ibgp = val
834
- assert_equal(bgp_af.maximum_paths_ibgp, val,
835
- 'Error: maximum paths ibgp value not match to set value')
836
-
837
- val = bgp_af.default_maximum_paths_ibgp
838
- bgp_af.maximum_paths = val
839
- assert_equal(bgp_af.default_maximum_paths_ibgp, val,
840
- 'Error: maximum paths ibgp value not match to default value')
841
- end
842
-
843
- def test_maximum_paths_ibgp
844
- asn = '55'
845
- vrf = 'default'
846
- af = 'ipv4 unicast'
847
- maximum_paths_ibgp(asn, vrf, af)
848
-
849
- asn = '55'
850
- vrf = 'red'
851
- af = 'ipv4 unicast'
852
- maximum_paths_ibgp(asn, vrf, af)
853
-
854
- asn = '55'
855
- vrf = 'default'
856
- af = 'ipv6 unicast'
857
- maximum_paths_ibgp(asn, vrf, af)
858
-
859
- asn = '55'
860
- vrf = 'red'
861
- af = 'ipv6 unicast'
862
- maximum_paths_ibgp(asn, vrf, af)
863
- end
864
-
865
484
  ##
866
485
  ## network
867
486
  ##
@@ -872,13 +491,22 @@ class TestBgpAF < CiscoTestCase
872
491
  vrfs.each do |vrf|
873
492
  afs.each do |af|
874
493
  dbg = sprintf('[VRF %s AF %s]', vrf, af.join('/'))
494
+ config_ios_xr_dependencies(1)
875
495
  af_obj = RouterBgpAF.new(1, vrf, af)
876
496
  network_cmd(af_obj, dbg)
497
+
498
+ af_obj.destroy
877
499
  end
878
500
  end
879
501
  end
880
502
 
881
503
  def network_cmd(af, dbg)
504
+ if platform == :ios_xr
505
+ %w(rtmap1 rtmap2 rtmap3 rtmap5 rtmap6 rtmap7).each do |policy|
506
+ config_no_warn("route-policy #{policy}", 'end-policy')
507
+ end
508
+ end
509
+
882
510
  # Initial 'should' state
883
511
  if /ipv6/.match(dbg)
884
512
  master = [
@@ -926,7 +554,13 @@ class TestBgpAF < CiscoTestCase
926
554
  "#{dbg} Test 3. Restore the removed networks")
927
555
 
928
556
  # Test: Change route-maps on existing networks
929
- should = master.map { |network, rm| [network, "#{rm}_55"] }
557
+ if platform == :ios_xr
558
+ %w(rtmap1_55 rtmap2_55 rtmap3_55 rtmap5_55
559
+ rtmap6_55 rtmap7_55).each do |policy|
560
+ config_no_warn("route-policy #{policy}", 'end-policy')
561
+ end
562
+ end
563
+ should = master.map { |network, rm| [network, rm.nil? ? nil : "#{rm}_55"] }
930
564
  af.networks = should
931
565
  result = af.networks
932
566
  assert_equal(should.sort, result.sort,
@@ -938,6 +572,12 @@ class TestBgpAF < CiscoTestCase
938
572
  result = af.networks
939
573
  assert_equal(should.sort, result.sort,
940
574
  "#{dbg} Test 5. 'Default'")
575
+ return unless platform == :ios_xr
576
+ %w(rtmap1 rtmap2 rtmap3 rtmap5 rtmap6 rtmap7
577
+ rtmap1_55 rtmap2_55 rtmap3_55
578
+ rtmap5_55 rtmap6_55 rtmap7_55).each do |policy|
579
+ config("no route-policy #{policy}")
580
+ end
941
581
  end
942
582
 
943
583
  ##
@@ -950,8 +590,10 @@ class TestBgpAF < CiscoTestCase
950
590
  vrfs.each do |vrf|
951
591
  afs.each do |af|
952
592
  dbg = sprintf('[VRF %s AF %s]', vrf, af.join('/'))
593
+ config_ios_xr_dependencies(1)
953
594
  af = RouterBgpAF.new(1, vrf, af)
954
595
  redistribute_cmd(af, dbg)
596
+ af.destroy
955
597
  end
956
598
  end
957
599
  end
@@ -960,13 +602,22 @@ class TestBgpAF < CiscoTestCase
960
602
  # rubocop:disable Style/WordArray
961
603
  # Initial 'should' state
962
604
  ospf = (dbg.include? 'ipv6') ? 'ospfv3 3' : 'ospf 3'
963
- master = [['direct', 'rm_direct'],
964
- ['lisp', 'rm_lisp'],
965
- ['static', 'rm_static'],
966
- ['eigrp 1', 'rm_eigrp'],
967
- ['isis 2', 'rm_isis'],
968
- [ospf, 'rm_ospf'],
969
- ['rip 4', 'rm_rip']]
605
+ if platform == :nexus
606
+ master = [['direct', 'rm_direct'],
607
+ ['lisp', 'rm_lisp'],
608
+ ['static', 'rm_static'],
609
+ ['eigrp 1', 'rm_eigrp'],
610
+ ['isis 2', 'rm_isis'],
611
+ [ospf, 'rm_ospf'],
612
+ ['rip 4', 'rm_rip']]
613
+ elsif platform == :ios_xr
614
+ config_no_warn('route-policy my_policy', 'end-policy')
615
+ master = [['connected', 'my_policy'],
616
+ ['eigrp 1', 'my_policy'],
617
+ [ospf, 'my_policy'],
618
+ ['static', 'my_policy']]
619
+ master.push(['isis abc', 'my_policy']) if dbg.include? 'default'
620
+ end
970
621
  # rubocop:enable Style/WordArray
971
622
 
972
623
  # Test: Add all protocols w/route-maps when no cmds are present
@@ -991,6 +642,9 @@ class TestBgpAF < CiscoTestCase
991
642
  "#{dbg} Test 3. Restore the removed protocols")
992
643
 
993
644
  # Test: Change route-maps on existing commands
645
+ if platform == :ios_xr
646
+ config_no_warn('route-policy my_policy_2', 'end-policy')
647
+ end
994
648
  should = master.map { |prot_only, rm| [prot_only, "#{rm}_2"] }
995
649
  af.redistribute = should
996
650
  result = af.redistribute
@@ -1003,6 +657,10 @@ class TestBgpAF < CiscoTestCase
1003
657
  result = af.redistribute
1004
658
  assert_equal(should.sort, result.sort,
1005
659
  "#{dbg} Test 5. 'Default'")
660
+ return unless platform == :ios_xr
661
+ %w(my_policy my_policy_2).each do |policy|
662
+ config("no route-policy #{policy}")
663
+ end
1006
664
  end
1007
665
 
1008
666
  ##
@@ -1099,36 +757,36 @@ class TestBgpAF < CiscoTestCase
1099
757
  assert_equal(expected, result, 'Test 5. delta mismatch')
1100
758
  end
1101
759
 
1102
- ##
1103
- ## suppress_inactive
1104
- ##
1105
- def suppress_inactive(asn, vrf, af)
1106
- bgp_af = RouterBgpAF.new(asn, vrf, af)
760
+ def test_respond_to?
761
+ config_ios_xr_dependencies('22')
762
+ bgp_af = RouterBgpAF.new('22', 'red', %w(ipv4 unicast))
1107
763
 
1108
- #
1109
- # Set and verify
1110
- #
1111
- val = false
1112
- bgp_af.suppress_inactive = val
1113
- refute(bgp_af.suppress_inactive,
1114
- 'Error: suppress inactive value does not match set value')
764
+ # Functions that are actually defined in bgp_af.rb
765
+ assert_respond_to(bgp_af, :dampening_max_suppress_time)
766
+ assert_respond_to(bgp_af, :next_hop_route_map=)
767
+ assert_respond_to(bgp_af, :default_additional_paths_selection)
1115
768
 
1116
- val = true
1117
- bgp_af.suppress_inactive = val
1118
- assert(bgp_af.suppress_inactive,
1119
- 'Error: suppress inactive value does not match set value')
1120
-
1121
- val = bgp_af.default_suppress_inactive
1122
- bgp_af.suppress_inactive = val
1123
- refute(bgp_af.suppress_inactive,
1124
- 'Error: suppress inactive value does not match default value')
1125
- end
1126
-
1127
- def test_suppress_inactive
1128
- afs = [%w(ipv4 unicast), %w(ipv6 unicast)]
1129
- afs.each do |af|
1130
- suppress_inactive(55, 'red', af)
769
+ # Functions that are covered by the method_missing magic
770
+ assert_respond_to(bgp_af, :next_hop_route_map)
771
+ assert_respond_to(bgp_af, :additional_paths_selection)
772
+ assert_respond_to(bgp_af, :default_default_information_originate)
773
+ if platform == :ios_xr
774
+ # not supported
775
+ refute_respond_to(bgp_af, :default_information_originate=)
776
+ else
777
+ assert_respond_to(bgp_af, :default_information_originate=)
1131
778
  end
779
+ assert_respond_to(bgp_af, :table_map)
780
+ assert_respond_to(bgp_af, :default_table_map)
781
+
782
+ # Functions that are explicitly excluded from method_missing
783
+ refute_respond_to(bgp_af, :table_map=)
784
+ refute_respond_to(bgp_af, :table_map_filter=)
785
+
786
+ # Functions that shouldn't be covered by method_missing
787
+ refute_respond_to(bgp_af, :default_next_hop_route_map=)
788
+
789
+ bgp_af.destroy
1132
790
  end
1133
791
 
1134
792
  ##
@@ -1142,35 +800,44 @@ class TestBgpAF < CiscoTestCase
1142
800
  #
1143
801
  val = 'sjc'
1144
802
  bgp_af.table_map_set(val)
1145
- assert_equal(val, bgp_af.table_map,
1146
- 'Error: default metric value does not match set value')
803
+ assert_equal(val, bgp_af.table_map)
1147
804
 
1148
805
  val = bgp_af.default_table_map
1149
806
  bgp_af.table_map_set(val)
1150
- assert_equal(val, bgp_af.table_map,
1151
- 'Error: default metric value does not match default' \
1152
- 'value')
807
+ assert_equal(val, bgp_af.table_map)
808
+
809
+ if validate_property_excluded?('bgp_af', 'table_map_filter')
810
+ assert_raises(Cisco::UnsupportedError) do
811
+ bgp_af.table_map_set('sjc', true)
812
+ end
813
+ assert_nil(bgp_af.default_table_map_filter)
814
+ return
815
+ end
1153
816
 
1154
817
  val = false
1155
818
  bgp_af.table_map_set('sjc', val)
1156
- refute(bgp_af.table_map_filter,
1157
- 'Error: suppress inactive value does not match set value')
819
+ refute(bgp_af.table_map_filter)
1158
820
 
1159
821
  val = true
1160
822
  bgp_af.table_map_set('sjc', val)
1161
- assert(bgp_af.table_map_filter,
1162
- 'Error: suppress inactive value does not match set value')
823
+ assert(bgp_af.table_map_filter)
1163
824
 
1164
- val = bgp_af.default_table_map_filter
1165
- bgp_af.table_map_set('sjc', val)
1166
- refute(bgp_af.table_map_filter,
1167
- 'Error: suppress inactive value does not match default value')
825
+ default = bgp_af.default_table_map_filter
826
+ bgp_af.table_map_set('sjc', default)
827
+ assert_equal(default, bgp_af.table_map_filter)
1168
828
  end
1169
829
 
1170
830
  def test_table_map
831
+ if platform == :ios_xr
832
+ config_no_warn('route-policy sjc', 'end-policy')
833
+ config_ios_xr_dependencies('55')
834
+ end
835
+
1171
836
  afs = [%w(ipv4 unicast), %w(ipv6 unicast)]
1172
837
  afs.each do |af|
1173
838
  table_map(55, 'red', af)
1174
839
  end
840
+
841
+ config('no route-policy sjc') if platform == :ios_xr
1175
842
  end
1176
843
  end