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
@@ -21,6 +21,8 @@ require_relative '../lib/cisco_node_utils/snmp_notification_receiver'
21
21
  # TestSnmpNotificationReceiver - Minitest for SnmpNotificationReceiver
22
22
  # node utility.
23
23
  class TestSnmpNotificationReceiver < CiscoTestCase
24
+ @skip_unless_supported = 'snmp_notification_receiver'
25
+
24
26
  def setup
25
27
  # setup runs at the beginning of each test
26
28
  super
@@ -25,6 +25,8 @@ end
25
25
 
26
26
  # TestSnmpCommunity - Minitest for SnmpCommunity node utility
27
27
  class TestSnmpCommunity < CiscoTestCase
28
+ @skip_unless_supported = 'snmp_community'
29
+
28
30
  SNMP_COMMUNITY_NAME_STR = 128
29
31
  SNMP_GROUP_NAME_STR = 128
30
32
  DEFAULT_SNMP_COMMUNITY_GROUP = 'network-operator'
@@ -17,6 +17,8 @@ require_relative '../lib/cisco_node_utils/snmpgroup'
17
17
 
18
18
  # TestSnmpGroup - Minitest for SnmpGroup node utility.
19
19
  class TestSnmpGroup < CiscoTestCase
20
+ @skip_unless_supported = 'snmp_group'
21
+
20
22
  # NXOS snmp groups will not be empty
21
23
  def test_snmpgroup_collection_not_empty
22
24
  snmpgroups = SnmpGroup.groups
@@ -18,26 +18,35 @@
18
18
  require_relative 'ciscotest'
19
19
  require_relative '../lib/cisco_node_utils/snmpnotification'
20
20
 
21
- # TestRadiusGlobal - Minitest for RadiusGlobal node utility.
21
+ # TestSnmpNotification - Minitest for SnmpNotification node utility.
22
22
  class TestSnmpNotification < CiscoTestCase
23
+ @skip_unless_supported = 'snmpnotification'
23
24
  def setup
24
25
  # setup runs at the beginning of each test
25
26
  super
26
27
  no_snmp_notification
27
- config('no feature bgp')
28
- config('feature bgp')
28
+ if platform == :nexus
29
+ config('no feature bgp')
30
+ config('feature bgp')
31
+ else
32
+ config('snmp-server traps bgp')
33
+ end
29
34
  end
30
35
 
31
36
  def teardown
32
37
  # teardown runs at the end of each test
33
38
  no_snmp_notification
34
- config('no feature bgp')
39
+ config('no feature bgp') if platform == :nexus
35
40
  super
36
41
  end
37
42
 
38
43
  def no_snmp_notification
39
44
  # Turn the feature off for a clean test.
40
- config('no snmp-server enable traps')
45
+ if platform == :nexus
46
+ config('no snmp-server enable traps')
47
+ else
48
+ config('no snmp-server traps')
49
+ end
41
50
  end
42
51
 
43
52
  # TESTS
@@ -46,27 +55,37 @@ class TestSnmpNotification < CiscoTestCase
46
55
  # test traps returned
47
56
  assert_equal(false, Cisco::SnmpNotification.notifications.empty?,
48
57
  'notifications is not empty')
49
- assert_equal(Cisco::SnmpNotification,
50
- Cisco::SnmpNotification.notifications['vtp notifs'].class,
51
- 'vtp notifs exists')
58
+ if platform == :nexus
59
+ assert_equal(Cisco::SnmpNotification,
60
+ Cisco::SnmpNotification.notifications['vtp notifs'].class,
61
+ 'vtp notifs exists')
62
+ else
63
+ assert_equal(Cisco::SnmpNotification,
64
+ Cisco::SnmpNotification.notifications['bgp'].class,
65
+ 'bgp exists')
66
+ end
52
67
 
53
68
  # set up some traps
54
- cfs_state = Cisco::SnmpNotification.new('cfs state-change-notif')
55
- bgp = Cisco::SnmpNotification.new('bgp cbgp2 state-changes')
56
-
69
+ if platform == :nexus
70
+ trap1 = Cisco::SnmpNotification.new('cfs state-change-notif')
71
+ trap2 = Cisco::SnmpNotification.new('bgp cbgp2 state-changes')
72
+ else
73
+ trap1 = Cisco::SnmpNotification.new('bfd')
74
+ trap2 = Cisco::SnmpNotification.new('flash insertion')
75
+ end
57
76
  # Default Checking
58
- assert_equal(cfs_state.enable, false)
59
- assert_equal(bgp.enable, false)
77
+ assert_equal(trap1.enable, false)
78
+ assert_equal(trap2.enable, false)
60
79
 
61
- cfs_state.enable = true
62
- bgp.enable = true
63
- assert_equal(cfs_state.enable, true)
64
- assert_equal(bgp.enable, true)
80
+ trap1.enable = true
81
+ trap2.enable = true
82
+ assert_equal(trap1.enable, true)
83
+ assert_equal(trap2.enable, true)
65
84
 
66
85
  # Setting back to default and re-checking
67
- cfs_state.enable = false
68
- bgp.enable = false
69
- assert_equal(cfs_state.enable, false)
70
- assert_equal(bgp.enable, false)
86
+ trap1.enable = false
87
+ trap2.enable = false
88
+ assert_equal(trap1.enable, false)
89
+ assert_equal(trap2.enable, false)
71
90
  end
72
91
  end
@@ -17,6 +17,8 @@ require_relative '../lib/cisco_node_utils/snmpserver'
17
17
 
18
18
  # TestSnmpServer - Minitest for SnmpServer node utility
19
19
  class TestSnmpServer < CiscoTestCase
20
+ @skip_unless_supported = 'snmp_server'
21
+
20
22
  DEFAULT_SNMP_SERVER_AAA_USER_CACHE_TIMEOUT = 3600
21
23
  DEFAULT_SNMP_SERVER_LOCATION = ''
22
24
  DEFAULT_SNMP_SERVER_CONTACT = ''
@@ -21,6 +21,8 @@ DEFAULT_SNMP_USER_GROUP_NAME = 'network-operator'
21
21
 
22
22
  # TestSnmpUser - Minitest for SnmpUser node utility class
23
23
  class TestSnmpUser < CiscoTestCase
24
+ @skip_unless_supported = 'snmp_user'
25
+
24
26
  @@existing_users = nil # rubocop:disable Style/ClassVars
25
27
 
26
28
  def setup
@@ -0,0 +1,563 @@
1
+ # Copyright (c) 2016 Cisco and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require_relative 'ciscotest'
16
+ require_relative '../lib/cisco_node_utils/stp_global'
17
+
18
+ # TestStpGlobal - Minitest for StpGlobal node utility class
19
+ class TestStpGlobal < CiscoTestCase
20
+ @skip_unless_supported = 'stp_global'
21
+ # TESTS
22
+
23
+ @@clean = false # rubocop:disable Style/ClassVars
24
+ def setup
25
+ super
26
+ config 'no spanning-tree mode'
27
+ config 'system bridge-domain none' if /N7/ =~ node.product_id
28
+ @intf = Interface.new(interfaces[0])
29
+
30
+ # Only pre-clean interface on initial setup
31
+ config("default interface #{interfaces[0]}") unless @@clean
32
+ @@clean = true # rubocop:disable Style/ClassVars
33
+ @intf.switchport_enable
34
+ end
35
+
36
+ def teardown
37
+ config 'no spanning-tree mode'
38
+ config 'system bridge-domain none' if /N7/ =~ node.product_id
39
+ super
40
+ end
41
+
42
+ def test_bd_forward_time_change
43
+ global = StpGlobal.new('default')
44
+ bdft = [%w(2-4,6,8-12 4), %w(14 30)]
45
+ if validate_property_excluded?('stp_global', 'bd_forward_time')
46
+ assert_nil(global.bd_forward_time)
47
+ assert_raises(Cisco::UnsupportedError) do
48
+ global.bd_forward_time = bdft
49
+ end
50
+ else
51
+ config 'system bridge-domain all'
52
+ global.bd_forward_time = global.default_bd_forward_time
53
+ assert_equal(global.default_bd_forward_time,
54
+ global.bd_forward_time)
55
+ global.bd_forward_time = bdft
56
+ assert_equal(bdft, global.bd_forward_time)
57
+ global.bd_forward_time = global.default_bd_forward_time
58
+ assert_equal(global.default_bd_forward_time,
59
+ global.bd_forward_time)
60
+ end
61
+ end
62
+
63
+ def test_bd_hello_time_change
64
+ global = StpGlobal.new('default')
65
+ bdft = [%w(2-4,6,8-12 1), %w(14 10)]
66
+ if validate_property_excluded?('stp_global', 'bd_hello_time')
67
+ assert_nil(global.bd_hello_time)
68
+ assert_raises(Cisco::UnsupportedError) do
69
+ global.bd_hello_time = bdft
70
+ end
71
+ else
72
+ config 'system bridge-domain all'
73
+ global.bd_hello_time = global.default_bd_hello_time
74
+ assert_equal(global.default_bd_hello_time,
75
+ global.bd_hello_time)
76
+ global.bd_hello_time = bdft
77
+ assert_equal(bdft, global.bd_hello_time)
78
+ global.bd_hello_time = global.default_bd_hello_time
79
+ assert_equal(global.default_bd_hello_time,
80
+ global.bd_hello_time)
81
+ end
82
+ end
83
+
84
+ def test_bd_max_age_change
85
+ global = StpGlobal.new('default')
86
+ bdft = [%w(2-4,6,8-12 10), %w(14 40)]
87
+ if validate_property_excluded?('stp_global', 'bd_max_age')
88
+ assert_nil(global.bd_max_age)
89
+ assert_raises(Cisco::UnsupportedError) do
90
+ global.bd_max_age = bdft
91
+ end
92
+ else
93
+ config 'system bridge-domain all'
94
+ global.bd_max_age = global.default_bd_max_age
95
+ assert_equal(global.default_bd_max_age,
96
+ global.bd_max_age)
97
+ global.bd_max_age = bdft
98
+ assert_equal(bdft, global.bd_max_age)
99
+ global.bd_max_age = global.default_bd_max_age
100
+ assert_equal(global.default_bd_max_age,
101
+ global.bd_max_age)
102
+ end
103
+ end
104
+
105
+ def test_bd_priorities_change
106
+ global = StpGlobal.new('default')
107
+ bdft = [%w(2-4,6,8-12 4096), %w(14 8192)]
108
+ if validate_property_excluded?('stp_global', 'bd_priority')
109
+ assert_nil(global.bd_priority)
110
+ assert_nil(global.bd_root_priority)
111
+ assert_nil(global.bd_designated_priority)
112
+ assert_raises(Cisco::UnsupportedError) do
113
+ global.bd_priority = bdft
114
+ end
115
+ assert_raises(Cisco::UnsupportedError) do
116
+ global.bd_root_priority = bdft
117
+ end
118
+ assert_raises(Cisco::UnsupportedError) do
119
+ global.bd_designated_priority = bdft
120
+ end
121
+ else
122
+ config 'system bridge-domain all'
123
+ global.bd_priority = global.default_bd_priority
124
+ global.bd_root_priority = global.default_bd_root_priority
125
+ global.bd_designated_priority = global.default_bd_designated_priority
126
+ assert_equal(global.default_bd_priority,
127
+ global.bd_priority)
128
+ assert_equal(global.default_bd_root_priority,
129
+ global.bd_root_priority)
130
+ assert_equal(global.default_bd_designated_priority,
131
+ global.bd_designated_priority)
132
+ global.bd_priority = bdft
133
+ global.bd_root_priority = bdft
134
+ global.bd_designated_priority = bdft
135
+ assert_equal(bdft, global.bd_priority)
136
+ assert_equal(bdft, global.bd_root_priority)
137
+ assert_equal(bdft, global.bd_designated_priority)
138
+ global.bd_priority = global.default_bd_priority
139
+ global.bd_root_priority = global.default_bd_root_priority
140
+ global.bd_designated_priority = global.default_bd_designated_priority
141
+ assert_equal(global.default_bd_priority,
142
+ global.bd_priority)
143
+ assert_equal(global.default_bd_root_priority,
144
+ global.bd_root_priority)
145
+ assert_equal(global.default_bd_designated_priority,
146
+ global.bd_designated_priority)
147
+ end
148
+ end
149
+
150
+ def test_get_set_bpdufilter
151
+ global = StpGlobal.new('default')
152
+ global.bpdufilter = true
153
+ assert_equal(true, global.bpdufilter)
154
+ global.bpdufilter =
155
+ global.default_bpdufilter
156
+ assert_equal(global.default_bpdufilter,
157
+ global.bpdufilter)
158
+ end
159
+
160
+ def test_get_set_bpduguard
161
+ global = StpGlobal.new('default')
162
+ global.bpduguard = true
163
+ assert_equal(true, global.bpduguard)
164
+ global.bpduguard =
165
+ global.default_bpduguard
166
+ assert_equal(global.default_bpduguard,
167
+ global.bpduguard)
168
+ end
169
+
170
+ def test_get_set_bridge_assurance
171
+ global = StpGlobal.new('default')
172
+ global.bridge_assurance = false
173
+ assert_equal(false, global.bridge_assurance)
174
+ global.bridge_assurance =
175
+ global.default_bridge_assurance
176
+ assert_equal(global.default_bridge_assurance,
177
+ global.bridge_assurance)
178
+ end
179
+
180
+ def test_get_set_domain
181
+ global = StpGlobal.new('default')
182
+ if validate_property_excluded?('stp_global', 'domain')
183
+ assert_nil(global.domain)
184
+ assert_raises(Cisco::UnsupportedError) do
185
+ global.domain = 200
186
+ end
187
+ else
188
+ global.domain = 100
189
+ assert_equal(100, global.domain)
190
+ global.domain =
191
+ global.default_domain
192
+ assert_equal(global.default_domain,
193
+ global.domain)
194
+ end
195
+ end
196
+
197
+ def test_get_set_fcoe
198
+ global = StpGlobal.new('default')
199
+ if validate_property_excluded?('stp_global', 'fcoe')
200
+ assert_nil(global.fcoe)
201
+ assert_raises(Cisco::UnsupportedError) do
202
+ global.fcoe = false
203
+ end
204
+ else
205
+ global.fcoe = false
206
+ assert_equal(false, global.fcoe)
207
+ global.fcoe =
208
+ global.default_fcoe
209
+ assert_equal(global.default_fcoe,
210
+ global.fcoe)
211
+ end
212
+ end
213
+
214
+ def test_get_set_loopguard
215
+ global = StpGlobal.new('default')
216
+ global.loopguard = true
217
+ assert_equal(true, global.loopguard)
218
+ global.loopguard =
219
+ global.default_loopguard
220
+ assert_equal(global.default_loopguard,
221
+ global.loopguard)
222
+ end
223
+
224
+ def test_get_set_mode
225
+ global = StpGlobal.new('default')
226
+ global.mode = 'mst'
227
+ assert_equal('mst', global.mode)
228
+ global.mode =
229
+ global.default_mode
230
+ assert_equal(global.default_mode,
231
+ global.mode)
232
+ end
233
+
234
+ def test_get_set_mst_priorities
235
+ global = StpGlobal.new('default')
236
+ global.mode = 'mst'
237
+ global.mst_priority = global.default_mst_priority
238
+ global.mst_root_priority = global.default_mst_root_priority
239
+ global.mst_designated_priority = global.default_mst_designated_priority
240
+ assert_equal(global.default_mst_priority,
241
+ global.mst_priority)
242
+ assert_equal(global.default_mst_root_priority,
243
+ global.mst_root_priority)
244
+ assert_equal(global.default_mst_designated_priority,
245
+ global.mst_designated_priority)
246
+ bddp = [%w(0-4,6,8-12 4096), %w(14 8192)]
247
+ global.mst_priority = bddp
248
+ global.mst_root_priority = bddp
249
+ global.mst_designated_priority = bddp
250
+ assert_equal(bddp, global.mst_priority)
251
+ assert_equal(bddp, global.mst_root_priority)
252
+ assert_equal(bddp, global.mst_designated_priority)
253
+ global.mst_priority = global.default_mst_priority
254
+ global.mst_root_priority = global.default_mst_root_priority
255
+ global.mst_designated_priority = global.default_mst_designated_priority
256
+ assert_equal(global.default_mst_priority,
257
+ global.mst_priority)
258
+ assert_equal(global.default_mst_root_priority,
259
+ global.mst_root_priority)
260
+ assert_equal(global.default_mst_designated_priority,
261
+ global.mst_designated_priority)
262
+ end
263
+
264
+ def test_get_set_mst_forward_time
265
+ global = StpGlobal.new('default')
266
+ global.mode = 'mst'
267
+ global.mst_forward_time = 25
268
+ assert_equal(25, global.mst_forward_time)
269
+ global.mst_forward_time =
270
+ global.default_mst_forward_time
271
+ assert_equal(global.default_mst_forward_time,
272
+ global.mst_forward_time)
273
+ end
274
+
275
+ def test_get_set_mst_hello_time
276
+ global = StpGlobal.new('default')
277
+ global.mode = 'mst'
278
+ global.mst_hello_time = 5
279
+ assert_equal(5, global.mst_hello_time)
280
+ global.mst_hello_time =
281
+ global.default_mst_hello_time
282
+ assert_equal(global.default_mst_hello_time,
283
+ global.mst_hello_time)
284
+ end
285
+
286
+ def test_get_set_mst_inst_vlan_map
287
+ global = StpGlobal.new('default')
288
+ global.mode = 'mst'
289
+ global.mst_inst_vlan_map = global.default_mst_inst_vlan_map
290
+ assert_equal(global.default_mst_inst_vlan_map,
291
+ global.mst_inst_vlan_map)
292
+ bddp = [%w(8 2-65), %w(14 200-300)]
293
+ global.mst_inst_vlan_map = bddp
294
+ assert_equal(bddp, global.mst_inst_vlan_map)
295
+ global.mst_inst_vlan_map = global.default_mst_inst_vlan_map
296
+ assert_equal(global.default_mst_inst_vlan_map,
297
+ global.mst_inst_vlan_map)
298
+ end
299
+
300
+ def test_get_set_mst_max_age
301
+ global = StpGlobal.new('default')
302
+ global.mode = 'mst'
303
+ global.mst_max_age = 35
304
+ assert_equal(35, global.mst_max_age)
305
+ global.mst_max_age =
306
+ global.default_mst_max_age
307
+ assert_equal(global.default_mst_max_age,
308
+ global.mst_max_age)
309
+ end
310
+
311
+ def test_get_set_mst_max_hops
312
+ global = StpGlobal.new('default')
313
+ global.mode = 'mst'
314
+ global.mst_max_hops = 200
315
+ assert_equal(200, global.mst_max_hops)
316
+ global.mst_max_hops =
317
+ global.default_mst_max_hops
318
+ assert_equal(global.default_mst_max_hops,
319
+ global.mst_max_hops)
320
+ end
321
+
322
+ def test_get_set_mst_name
323
+ global = StpGlobal.new('default')
324
+ global.mode = 'mst'
325
+ global.mst_name = 'nexus'
326
+ assert_equal('nexus', global.mst_name)
327
+ global.mst_name =
328
+ global.default_mst_name
329
+ assert_equal(global.default_mst_name,
330
+ global.mst_name)
331
+ end
332
+
333
+ def test_get_set_mst_revision
334
+ global = StpGlobal.new('default')
335
+ global.mode = 'mst'
336
+ global.mst_revision = 34
337
+ assert_equal(34, global.mst_revision)
338
+ global.mst_revision =
339
+ global.default_mst_revision
340
+ assert_equal(global.default_mst_revision,
341
+ global.mst_revision)
342
+ end
343
+
344
+ def test_get_set_pathcost
345
+ global = StpGlobal.new('default')
346
+ global.pathcost = 'long'
347
+ assert_equal('long', global.pathcost)
348
+ global.pathcost =
349
+ global.default_pathcost
350
+ assert_equal(global.default_pathcost,
351
+ global.pathcost)
352
+ end
353
+
354
+ def test_get_set_vlan_forward_time
355
+ global = StpGlobal.new('default')
356
+ global.vlan_forward_time = global.default_vlan_forward_time
357
+ assert_equal(global.default_vlan_forward_time,
358
+ global.vlan_forward_time)
359
+ bddp = [%w(1-4,6,8-12 10), %w(14 8)]
360
+ global.vlan_forward_time = bddp
361
+ assert_equal(bddp, global.vlan_forward_time)
362
+ global.vlan_forward_time = global.default_vlan_forward_time
363
+ assert_equal(global.default_vlan_forward_time,
364
+ global.vlan_forward_time)
365
+ end
366
+
367
+ def test_get_set_vlan_hello_time
368
+ global = StpGlobal.new('default')
369
+ global.vlan_hello_time = global.default_vlan_hello_time
370
+ assert_equal(global.default_vlan_hello_time,
371
+ global.vlan_hello_time)
372
+ bddp = [%w(1-4,6,8-12 5), %w(14 8)]
373
+ global.vlan_hello_time = bddp
374
+ assert_equal(bddp, global.vlan_hello_time)
375
+ global.vlan_hello_time = global.default_vlan_hello_time
376
+ assert_equal(global.default_vlan_hello_time,
377
+ global.vlan_hello_time)
378
+ end
379
+
380
+ def test_get_set_vlan_max_age
381
+ global = StpGlobal.new('default')
382
+ global.vlan_max_age = global.default_vlan_max_age
383
+ assert_equal(global.default_vlan_max_age,
384
+ global.vlan_max_age)
385
+ bddp = [%w(1-4,6,8-12 40), %w(14 35)]
386
+ global.vlan_max_age = bddp
387
+ assert_equal(bddp, global.vlan_max_age)
388
+ global.vlan_max_age = global.default_vlan_max_age
389
+ assert_equal(global.default_vlan_max_age,
390
+ global.vlan_max_age)
391
+ end
392
+
393
+ def test_get_set_vlan_priorities
394
+ global = StpGlobal.new('default')
395
+ global.vlan_priority = global.default_vlan_priority
396
+ global.vlan_root_priority = global.default_vlan_root_priority
397
+ global.vlan_designated_priority = global.default_vlan_designated_priority
398
+ assert_equal(global.default_vlan_priority,
399
+ global.vlan_priority)
400
+ assert_equal(global.default_vlan_root_priority,
401
+ global.vlan_root_priority)
402
+ assert_equal(global.default_vlan_designated_priority,
403
+ global.vlan_designated_priority)
404
+ bddp = [%w(1-4,6,8-12 4096), %w(14 8192)]
405
+ global.vlan_priority = bddp
406
+ global.vlan_root_priority = bddp
407
+ global.vlan_designated_priority = bddp
408
+ assert_equal(bddp, global.vlan_priority)
409
+ assert_equal(bddp, global.vlan_root_priority)
410
+ assert_equal(bddp, global.vlan_designated_priority)
411
+ global.vlan_priority = global.default_vlan_priority
412
+ global.vlan_root_priority = global.default_vlan_root_priority
413
+ global.vlan_designated_priority = global.default_vlan_designated_priority
414
+ assert_equal(global.default_vlan_priority,
415
+ global.vlan_priority)
416
+ assert_equal(global.default_vlan_root_priority,
417
+ global.vlan_root_priority)
418
+ assert_equal(global.default_vlan_designated_priority,
419
+ global.vlan_designated_priority)
420
+ end
421
+
422
+ def test_interface_stp_bpdufilter_change
423
+ @intf.stp_bpdufilter = 'enable'
424
+ assert_equal('enable', @intf.stp_bpdufilter)
425
+ @intf.stp_bpdufilter = 'disable'
426
+ assert_equal('disable', @intf.stp_bpdufilter)
427
+ @intf.stp_bpdufilter = @intf.default_stp_bpdufilter
428
+ assert_equal(@intf.default_stp_bpdufilter,
429
+ @intf.stp_bpdufilter)
430
+ end
431
+
432
+ def test_interface_stp_bpduguard_change
433
+ @intf.stp_bpduguard = 'enable'
434
+ assert_equal('enable', @intf.stp_bpduguard)
435
+ @intf.stp_bpduguard = 'disable'
436
+ assert_equal('disable', @intf.stp_bpduguard)
437
+ @intf.stp_bpduguard = @intf.default_stp_bpduguard
438
+ assert_equal(@intf.default_stp_bpduguard,
439
+ @intf.stp_bpduguard)
440
+ end
441
+
442
+ def test_interface_stp_cost_change
443
+ @intf.stp_cost = 2000
444
+ assert_equal(2000, @intf.stp_cost)
445
+ @intf.stp_cost = @intf.default_stp_cost
446
+ assert_equal(@intf.default_stp_cost,
447
+ @intf.stp_cost)
448
+ end
449
+
450
+ def test_interface_stp_guard_change
451
+ @intf.stp_guard = 'loop'
452
+ assert_equal('loop', @intf.stp_guard)
453
+ @intf.stp_guard = 'none'
454
+ assert_equal('none', @intf.stp_guard)
455
+ @intf.stp_guard = 'root'
456
+ assert_equal('root', @intf.stp_guard)
457
+ @intf.stp_guard = @intf.default_stp_guard
458
+ assert_equal(@intf.default_stp_guard,
459
+ @intf.stp_guard)
460
+ end
461
+
462
+ def test_interface_stp_link_type_change
463
+ @intf.stp_link_type = 'shared'
464
+ assert_equal('shared', @intf.stp_link_type)
465
+ @intf.stp_link_type = 'point-to-point'
466
+ assert_equal('point-to-point', @intf.stp_link_type)
467
+ @intf.stp_link_type = @intf.default_stp_link_type
468
+ assert_equal(@intf.default_stp_link_type,
469
+ @intf.stp_link_type)
470
+ end
471
+
472
+ def test_interface_stp_port_priority_change
473
+ @intf.stp_port_priority = 32
474
+ assert_equal(32, @intf.stp_port_priority)
475
+ @intf.stp_port_priority = @intf.default_stp_port_priority
476
+ assert_equal(@intf.default_stp_port_priority,
477
+ @intf.stp_port_priority)
478
+ end
479
+
480
+ def test_interface_stp_port_type_change
481
+ @intf.switchport_mode = :disabled
482
+ @intf.switchport_mode = :trunk
483
+ @intf.stp_port_type = 'edge'
484
+ assert_equal('edge', @intf.stp_port_type)
485
+ @intf.stp_port_type = 'edge trunk'
486
+ assert_equal('edge trunk', @intf.stp_port_type)
487
+ @intf.stp_port_type = 'network'
488
+ assert_equal('network', @intf.stp_port_type)
489
+ @intf.stp_port_type = 'normal'
490
+ assert_equal('normal', @intf.stp_port_type)
491
+ @intf.stp_port_type = @intf.default_stp_port_type
492
+ assert_equal(@intf.default_stp_port_type,
493
+ @intf.stp_port_type)
494
+ end
495
+
496
+ def test_interface_stp_mst_cost_change
497
+ @intf.stp_mst_cost = @intf.default_stp_mst_cost
498
+ assert_equal(@intf.default_stp_mst_cost,
499
+ @intf.stp_mst_cost)
500
+ mc = [%w(0,2-4,6,8-12 4500), %w(1 20000)]
501
+ @intf.stp_mst_cost = mc
502
+ assert_equal(mc, @intf.stp_mst_cost)
503
+ @intf.stp_mst_cost = @intf.default_stp_mst_cost
504
+ assert_equal(@intf.default_stp_mst_cost,
505
+ @intf.stp_mst_cost)
506
+ end
507
+
508
+ def test_interface_stp_mst_port_priority_change
509
+ @intf.stp_mst_port_priority = @intf.default_stp_mst_port_priority
510
+ assert_equal(@intf.default_stp_mst_port_priority,
511
+ @intf.stp_mst_port_priority)
512
+ mpp = [%w(0,2-4,6,8-12 224), %w(1 32)]
513
+ @intf.stp_mst_port_priority = mpp
514
+ assert_equal(mpp, @intf.stp_mst_port_priority)
515
+ @intf.stp_mst_port_priority = @intf.default_stp_mst_port_priority
516
+ assert_equal(@intf.default_stp_mst_port_priority,
517
+ @intf.stp_mst_port_priority)
518
+ end
519
+
520
+ def test_interface_stp_vlan_cost_change
521
+ @intf.stp_vlan_cost = @intf.default_stp_vlan_cost
522
+ assert_equal(@intf.default_stp_vlan_cost,
523
+ @intf.stp_vlan_cost)
524
+ vc = [%w(2-4,6,8-12 4500), %w(14 20000)]
525
+ @intf.stp_vlan_cost = vc
526
+ assert_equal(vc, @intf.stp_vlan_cost)
527
+ @intf.stp_vlan_cost = @intf.default_stp_vlan_cost
528
+ assert_equal(@intf.default_stp_vlan_cost,
529
+ @intf.stp_vlan_cost)
530
+ end
531
+
532
+ def test_interface_stp_vlan_port_priority_change
533
+ @intf.stp_vlan_port_priority = @intf.default_stp_vlan_port_priority
534
+ assert_equal(@intf.default_stp_vlan_port_priority,
535
+ @intf.stp_vlan_port_priority)
536
+ vpp = [%w(2-4,6,8-12 224), %w(14 32)]
537
+ @intf.stp_vlan_port_priority = vpp
538
+ assert_equal(vpp, @intf.stp_vlan_port_priority)
539
+ @intf.stp_vlan_port_priority = @intf.default_stp_vlan_port_priority
540
+ assert_equal(@intf.default_stp_vlan_port_priority,
541
+ @intf.stp_vlan_port_priority)
542
+ end
543
+
544
+ def test_interface_stp_props_switchport_disabled
545
+ @intf.switchport_enable(false)
546
+ proplist = {
547
+ 'bpdufilter' => 'enable',
548
+ 'cost' => 2000,
549
+ 'guard' => 'loop',
550
+ 'link_type' => 'shared',
551
+ 'mst_cost' => [%w(0,2-4,6,8-12 4500), %w(1 20000)],
552
+ 'mst_port_priority' => [%w(0,2-4,6,8-12 224), %w(1 32)],
553
+ 'port_priority' => 32,
554
+ 'vlan_cost' => [%w(2-4,6,8-12 4500), %w(14 20000)],
555
+ 'vlan_port_priority' => [%w(2-4,6,8-12 224), %w(14 32)],
556
+ }
557
+ proplist.each do |k, v|
558
+ assert_raises(RuntimeError, 'foo') do
559
+ @intf.send("stp_#{k}=", v)
560
+ end
561
+ end
562
+ end
563
+ end