cisco_node_utils 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +66 -0
  4. data/Gemfile +1 -0
  5. data/README.md +44 -43
  6. data/bin/.rubocop.yml +18 -0
  7. data/bin/show_running_yang.rb +233 -0
  8. data/cisco_node_utils.gemspec +1 -1
  9. data/docs/README-maintainers.md +1 -0
  10. data/docs/README-utilities.md +14 -0
  11. data/lib/.rubocop.yml +1 -1
  12. data/lib/cisco_node_utils/aaa_authentication_login_service.rb +8 -3
  13. data/lib/cisco_node_utils/aaa_authorization_service.rb +6 -0
  14. data/lib/cisco_node_utils/bfd_global.rb +300 -0
  15. data/lib/cisco_node_utils/bgp.rb +6 -4
  16. data/lib/cisco_node_utils/bgp_af.rb +2 -0
  17. data/lib/cisco_node_utils/bgp_neighbor.rb +14 -0
  18. data/lib/cisco_node_utils/bgp_neighbor_af.rb +4 -1
  19. data/lib/cisco_node_utils/cisco_cmn_utils.rb +126 -0
  20. data/lib/cisco_node_utils/client/client.rb +6 -2
  21. data/lib/cisco_node_utils/client/grpc/client.rb +120 -36
  22. data/lib/cisco_node_utils/client/nxapi/client.rb +6 -2
  23. data/lib/cisco_node_utils/cmd_ref/DEPRECATED.yaml +118 -0
  24. data/lib/cisco_node_utils/cmd_ref/aaa_authorization_service.yaml +14 -0
  25. data/lib/cisco_node_utils/cmd_ref/bfd_global.yaml +117 -0
  26. data/lib/cisco_node_utils/cmd_ref/bgp.yaml +7 -7
  27. data/lib/cisco_node_utils/cmd_ref/bgp_neighbor.yaml +7 -0
  28. data/lib/cisco_node_utils/cmd_ref/dhcp_relay_global.yaml +125 -0
  29. data/lib/cisco_node_utils/cmd_ref/feature.yaml +10 -0
  30. data/lib/cisco_node_utils/cmd_ref/interface.yaml +141 -49
  31. data/lib/cisco_node_utils/cmd_ref/interface_ospf.yaml +44 -0
  32. data/lib/cisco_node_utils/cmd_ref/interface_portchannel.yaml +6 -0
  33. data/lib/cisco_node_utils/cmd_ref/ospf.yaml +6 -0
  34. data/lib/cisco_node_utils/cmd_ref/ospf_area.yaml +91 -0
  35. data/lib/cisco_node_utils/cmd_ref/ospf_area_vlink.yaml +88 -0
  36. data/lib/cisco_node_utils/cmd_ref/overlay_global.yaml +0 -3
  37. data/lib/cisco_node_utils/cmd_ref/show_version.yaml +3 -3
  38. data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +39 -15
  39. data/lib/cisco_node_utils/cmd_ref/snmp_notification_receiver.yaml +43 -21
  40. data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +48 -19
  41. data/lib/cisco_node_utils/cmd_ref/snmp_user.yaml +0 -0
  42. data/lib/cisco_node_utils/cmd_ref/tacacs_global.yaml +30 -0
  43. data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +18 -6
  44. data/lib/cisco_node_utils/cmd_ref/vdc.yaml +4 -0
  45. data/lib/cisco_node_utils/cmd_ref/virtual_service.yaml +1 -0
  46. data/lib/cisco_node_utils/cmd_ref/vlan.yaml +23 -10
  47. data/lib/cisco_node_utils/cmd_ref/vxlan_vtep.yaml +8 -2
  48. data/lib/cisco_node_utils/cmd_ref/yang.yaml +7 -0
  49. data/lib/cisco_node_utils/cmd_ref/yum.yaml +10 -1
  50. data/lib/cisco_node_utils/constants.rb +8 -1
  51. data/lib/cisco_node_utils/dhcp_relay_global.rb +302 -0
  52. data/lib/cisco_node_utils/exceptions.rb +29 -0
  53. data/lib/cisco_node_utils/feature.rb +28 -0
  54. data/lib/cisco_node_utils/interface.rb +493 -402
  55. data/lib/cisco_node_utils/interface_DEPRECATED.rb +513 -0
  56. data/lib/cisco_node_utils/interface_ospf.rb +126 -0
  57. data/lib/cisco_node_utils/interface_portchannel.rb +16 -0
  58. data/lib/cisco_node_utils/logger.rb +3 -0
  59. data/lib/cisco_node_utils/node.rb +29 -1
  60. data/lib/cisco_node_utils/overlay_global.rb +1 -12
  61. data/lib/cisco_node_utils/pim.rb +1 -0
  62. data/lib/cisco_node_utils/pim_group_list.rb +1 -0
  63. data/lib/cisco_node_utils/pim_rp_address.rb +1 -0
  64. data/lib/cisco_node_utils/platform.rb +9 -2
  65. data/lib/cisco_node_utils/router_ospf.rb +1 -1
  66. data/lib/cisco_node_utils/router_ospf_area.rb +416 -0
  67. data/lib/cisco_node_utils/router_ospf_area_vlink.rb +313 -0
  68. data/lib/cisco_node_utils/router_ospf_vrf.rb +17 -0
  69. data/lib/cisco_node_utils/snmp_notification_receiver.rb +27 -9
  70. data/lib/cisco_node_utils/snmpcommunity.rb +34 -8
  71. data/lib/cisco_node_utils/snmpserver.rb +4 -4
  72. data/lib/cisco_node_utils/snmpuser.rb +0 -0
  73. data/lib/cisco_node_utils/tacacs_global.rb +102 -0
  74. data/lib/cisco_node_utils/tacacs_server.rb +8 -7
  75. data/lib/cisco_node_utils/vdc.rb +25 -7
  76. data/lib/cisco_node_utils/version.rb +1 -1
  77. data/lib/cisco_node_utils/vlan.rb +30 -56
  78. data/lib/cisco_node_utils/vlan_DEPRECATED.rb +108 -0
  79. data/lib/cisco_node_utils/yang.rb +160 -0
  80. data/lib/cisco_node_utils/yum.rb +25 -32
  81. data/tests/.rubocop.yml +3 -0
  82. data/tests/ciscotest.rb +136 -19
  83. data/tests/cmd_config_invalid.yaml +1 -1
  84. data/tests/noop.rb +7 -0
  85. data/tests/tacacs_server.yaml.example +6 -0
  86. data/tests/test_aaa_authentication_login.rb +24 -1
  87. data/tests/test_aaa_authentication_login_service.rb +9 -16
  88. data/tests/test_aaa_authorization_service.rb +111 -84
  89. data/tests/test_bfd_global.rb +278 -0
  90. data/tests/test_bgp_neighbor.rb +20 -0
  91. data/tests/test_bridge_domain_vni.rb +2 -9
  92. data/tests/test_cmn_utils.rb +76 -0
  93. data/tests/test_dhcp_relay_global.rb +284 -0
  94. data/tests/test_dns_domain.rb +4 -4
  95. data/tests/test_domain_name.rb +2 -2
  96. data/tests/test_encapsulation.rb +2 -4
  97. data/tests/test_evpn_vni.rb +14 -7
  98. data/tests/test_fabricpath_global.rb +12 -13
  99. data/tests/test_feature.rb +35 -17
  100. data/tests/test_interface.rb +352 -127
  101. data/tests/test_interface_bdi.rb +2 -2
  102. data/tests/test_interface_channel_group.rb +1 -1
  103. data/tests/test_interface_ospf.rb +153 -23
  104. data/tests/test_interface_portchannel.rb +15 -6
  105. data/tests/test_interface_private_vlan.rb +200 -576
  106. data/tests/test_interface_svi.rb +5 -52
  107. data/tests/test_interface_switchport.rb +80 -240
  108. data/tests/test_itd_device_group.rb +2 -2
  109. data/tests/test_itd_device_group_node.rb +2 -2
  110. data/tests/test_itd_service.rb +1 -1
  111. data/tests/test_name_server.rb +3 -3
  112. data/tests/test_node_ext.rb +15 -17
  113. data/tests/test_ntp_config.rb +1 -1
  114. data/tests/test_ntp_server.rb +3 -3
  115. data/tests/test_nxapi.rb +1 -0
  116. data/tests/test_overlay_global.rb +15 -19
  117. data/tests/test_pim.rb +5 -5
  118. data/tests/test_pim_group_list.rb +1 -37
  119. data/tests/test_pim_rp_address.rb +1 -1
  120. data/tests/test_platform.rb +9 -11
  121. data/tests/test_portchannel_global.rb +43 -3
  122. data/tests/test_radius_server.rb +1 -1
  123. data/tests/test_radius_server_group.rb +1 -1
  124. data/tests/test_router_bgp.rb +17 -30
  125. data/tests/test_router_ospf_area.rb +433 -0
  126. data/tests/test_router_ospf_area_vlink.rb +298 -0
  127. data/tests/test_router_ospf_vrf.rb +17 -0
  128. data/tests/test_snmp_notification_receiver.rb +11 -11
  129. data/tests/test_snmpcommunity.rb +177 -69
  130. data/tests/test_snmpgroup.rb +7 -7
  131. data/tests/test_snmpserver.rb +164 -253
  132. data/tests/test_snmpuser.rb +73 -69
  133. data/tests/test_stp_global.rb +15 -15
  134. data/tests/test_syslog_settings.rb +1 -1
  135. data/tests/test_tacacs_global.rb +80 -0
  136. data/tests/test_tacacs_server.rb +129 -51
  137. data/tests/test_tacacs_server_group.rb +3 -29
  138. data/tests/test_tacacs_server_host.rb +24 -27
  139. data/tests/test_vlan.rb +57 -59
  140. data/tests/test_vlan_private.rb +271 -284
  141. data/tests/test_vpc.rb +10 -4
  142. data/tests/test_vrf.rb +2 -0
  143. data/tests/test_vrf_af.rb +2 -5
  144. data/tests/test_vtp.rb +5 -2
  145. data/tests/test_vxlan_vtep.rb +20 -44
  146. data/tests/test_vxlan_vtep_vni.rb +23 -16
  147. data/tests/test_yang.rb +369 -0
  148. data/tests/test_yum.rb +34 -42
  149. data/tests/yum_package.yaml +35 -0
  150. metadata +31 -4
  151. data/tests/test_vlan_mt_full.rb +0 -85
data/tests/test_vpc.rb CHANGED
@@ -368,10 +368,16 @@ class TestVpc < CiscoTestCase
368
368
  interface_pc.switchport_mode = :trunk
369
369
  refute(interface_pc.vpc_peer_link,
370
370
  'vpc_peer_link should not be set by default')
371
- interface_pc.vpc_peer_link = true
372
- assert(interface_pc.vpc_peer_link, 'vpc_peer_link should be set')
373
- interface_pc.vpc_peer_link = false
374
- refute(interface_pc.vpc_peer_link, 'vpc_peer_link should not be set')
371
+ begin
372
+ # vpc peer-link has linecard limitations
373
+ interface_pc.vpc_peer_link = true
374
+ assert(interface_pc.vpc_peer_link, 'vpc_peer_link should be set')
375
+ interface_pc.vpc_peer_link = false
376
+ refute(interface_pc.vpc_peer_link, 'vpc_peer_link should not be set')
377
+ rescue RuntimeError => e
378
+ raise unless e.message[/Interface needs to be 10G to act as a peer-link/]
379
+ end
380
+
375
381
  # clean up
376
382
  interface.channel_group = false
377
383
  refute(interface.channel_group, 'channel group should be unset')
data/tests/test_vrf.rb CHANGED
@@ -108,6 +108,8 @@ class TestVrf < CiscoTestCase
108
108
  end
109
109
 
110
110
  def test_description
111
+ skip_legacy_defect?('7.3.0.(N1|D1).1.bin',
112
+ 'CSCuy36637: Cannot remove description')
111
113
  v = Vrf.new('test_description')
112
114
  desc = 'tested by minitest'
113
115
  v.description = desc
data/tests/test_vrf_af.rb CHANGED
@@ -111,15 +111,12 @@ class TestVrfAf < CiscoTestCase
111
111
  end
112
112
 
113
113
  def test_route_target
114
+ vdc_limit_f3_no_intf_needed(:set)
114
115
  [%w(ipv4 unicast), %w(ipv6 unicast)].each { |af| route_target(af) }
116
+ vdc_limit_f3_no_intf_needed(:clear)
115
117
  end
116
118
 
117
119
  def route_target(af)
118
- #
119
- # TBD: The evpn parts of this test need to check for compatible linecards to
120
- # skip the evpn portions. Don't use vxlan_linecard? as that will cause all
121
- # tests to be skipped.
122
- #
123
120
  # Common tester for route-target properties. Tests evpn and non-evpn.
124
121
  # route_target_both_auto
125
122
  # route_target_both_auto_evpn
data/tests/test_vtp.rb CHANGED
@@ -87,9 +87,7 @@ class TestVtp < CiscoTestCase
87
87
  assert_raises(ArgumentError) { vtp_domain(nil) }
88
88
  assert_raises(ArgumentError) { vtp_domain('') }
89
89
 
90
- # Create the same domain twice
91
90
  vtp = vtp_domain('accounting')
92
- assert_raises(Cisco::CliError) { vtp_domain('accounting') }
93
91
 
94
92
  # Set password to nil
95
93
  assert_raises(TypeError) { vtp.password = nil }
@@ -176,7 +174,12 @@ class TestVtp < CiscoTestCase
176
174
  end
177
175
  end
178
176
 
177
+ # this fails on n7k running 7.3(0)D1.1 image but it
178
+ # is fixed in later releases. The bugID is CSCuy87970
179
+ # which is already verified.
179
180
  def test_password_special_characters
181
+ skip_legacy_defect?('7.3.0.(N1|D1).1.bin',
182
+ 'CSCuy87970: NXAPI incorrect backslash escape')
180
183
  vtp = vtp_domain('password')
181
184
  vtp.password = 'hello!//\\#%$x'
182
185
  assert_equal('hello!//\\#%$x', vtp.password)
@@ -22,42 +22,39 @@ include Cisco
22
22
  # TestVxlanVtep - Minitest for VxlanVtep node utility
23
23
  class TestVxlanVtep < CiscoTestCase
24
24
  @skip_unless_supported = 'vxlan_vtep'
25
+ @@pre_clean_needed = true # rubocop:disable Style/ClassVars
25
26
 
26
27
  def setup
27
28
  super
28
29
  skip('Platform does not support MT-full or MT-lite') unless
29
30
  VxlanVtep.mt_full_support || VxlanVtep.mt_lite_support
31
+ Interface.interfaces(:nve).each { |_nve, obj| obj.destroy }
32
+ vdc_limit_f3_no_intf_needed(:set)
33
+ feature_cleanup if @@pre_clean_needed
34
+ Feature.nv_overlay_enable
35
+ @@pre_clean_needed = false # rubocop:disable Style/ClassVars
30
36
  end
31
37
 
32
38
  def teardown
33
- Feature.nv_overlay_disable
34
- return unless Vdc.vdc_support
35
- # Reset the vdc module type back to default
36
- v = Vdc.new('default')
37
- v.limit_resource_module_type = '' if v.limit_resource_module_type == 'f3'
38
- end
39
-
40
- def mt_full_env_setup
41
- skip('Platform does not support MT-full') unless VxlanVtep.mt_full_support
42
- vxlan_linecard?
43
- v = Vdc.new('default')
44
- v.limit_resource_module_type = 'f3' unless
45
- v.limit_resource_module_type == 'f3'
46
- Feature.nv_overlay_disable
39
+ if first_or_last_teardown
40
+ vdc_limit_f3_no_intf_needed(:clear)
41
+ feature_cleanup
42
+ end
43
+ super
47
44
  end
48
45
 
49
- def mt_lite_env_setup
50
- skip('Platform does not support MT-lite') unless VxlanVtep.mt_lite_support
51
- vxlan_linecard?
52
- Feature.nv_overlay_disable
53
- config('no feature vn-segment-vlan-based')
46
+ def feature_cleanup
47
+ config_no_warn('no feature-set fabricpath')
48
+ config_no_warn('no feature vni')
49
+ config_no_warn('no feature vn-segment-vlan-based')
50
+ config_no_warn('no nv overlay evpn ; no feature nv overlay')
51
+ # Rapid nv feature toggle can cause failures on some platforms;
52
+ # symptom e.g. 'show runn | i ^feature' will hang
53
+ sleep 5
54
54
  end
55
55
 
56
56
  def test_create_destroy_one
57
57
  # VxlanVtep.new() will enable 'feature nv overlay'
58
- mt_full_env_setup if VxlanVtep.mt_full_support
59
- mt_lite_env_setup if VxlanVtep.mt_lite_support
60
-
61
58
  id = 'nve1'
62
59
  vtep = VxlanVtep.new(id)
63
60
  @default_show_command = "show running | i 'interface #{id}'"
@@ -74,11 +71,7 @@ class TestVxlanVtep < CiscoTestCase
74
71
  end
75
72
 
76
73
  def test_mt_full_create_destroy_multiple
77
- if VxlanVtep.mt_full_support
78
- mt_full_env_setup
79
- else
80
- skip('Platform does not support MT-full')
81
- end
74
+ skip('Platform does not support MT-full') unless VxlanVtep.mt_full_support
82
75
 
83
76
  id1 = 'nve1'
84
77
  id2 = 'nve2'
@@ -110,14 +103,11 @@ class TestVxlanVtep < CiscoTestCase
110
103
 
111
104
  def test_create_negative
112
105
  # MT-lite supports a single nve int, MT-full supports 4.
113
- mt_full_env_setup if VxlanVtep.mt_full_support
114
- mt_lite_env_setup if VxlanVtep.mt_lite_support
115
106
  if VxlanVtep.mt_lite_support
116
107
  VxlanVtep.new('nve1')
117
108
  negative_id = 'nve2'
118
109
 
119
110
  elsif VxlanVtep.mt_full_support
120
- mt_full_env_setup
121
111
  (1..4).each { |n| VxlanVtep.new("nve#{n}") }
122
112
  negative_id = 'nve5'
123
113
  end
@@ -128,9 +118,6 @@ class TestVxlanVtep < CiscoTestCase
128
118
  end
129
119
 
130
120
  def test_description
131
- mt_full_env_setup if VxlanVtep.mt_full_support
132
- mt_lite_env_setup if VxlanVtep.mt_lite_support
133
-
134
121
  vtep = VxlanVtep.new('nve1')
135
122
 
136
123
  # Set description to non-default value and verify
@@ -147,8 +134,6 @@ class TestVxlanVtep < CiscoTestCase
147
134
  def test_host_reachability
148
135
  skip("Test not supported on #{node.product_id}") if
149
136
  cmd_ref.lookup('vxlan_vtep', 'host_reachability').default_value.nil?
150
- mt_full_env_setup if VxlanVtep.mt_full_support
151
- mt_lite_env_setup if VxlanVtep.mt_lite_support
152
137
 
153
138
  vtep = VxlanVtep.new('nve1')
154
139
 
@@ -163,9 +148,6 @@ class TestVxlanVtep < CiscoTestCase
163
148
  end
164
149
 
165
150
  def test_shutdown
166
- mt_full_env_setup if VxlanVtep.mt_full_support
167
- mt_lite_env_setup if VxlanVtep.mt_lite_support
168
-
169
151
  vtep = VxlanVtep.new('nve1')
170
152
 
171
153
  vtep.shutdown = true
@@ -179,9 +161,6 @@ class TestVxlanVtep < CiscoTestCase
179
161
  end
180
162
 
181
163
  def test_source_interface
182
- mt_full_env_setup if VxlanVtep.mt_full_support
183
- mt_lite_env_setup if VxlanVtep.mt_lite_support
184
-
185
164
  vtep = VxlanVtep.new('nve1')
186
165
 
187
166
  # Set source_interface to non-default value
@@ -204,9 +183,6 @@ class TestVxlanVtep < CiscoTestCase
204
183
  end
205
184
 
206
185
  def test_source_interface_hold_down_time
207
- mt_full_env_setup if VxlanVtep.mt_full_support
208
- mt_lite_env_setup if VxlanVtep.mt_lite_support
209
-
210
186
  vtep = VxlanVtep.new('nve1')
211
187
  if validate_property_excluded?('vxlan_vtep', 'source_intf_hold_down_time')
212
188
  assert_nil(vtep.source_interface_hold_down_time)
@@ -25,31 +25,32 @@ class TestVxlanVtepVni < CiscoTestCase
25
25
 
26
26
  def setup
27
27
  super
28
- return unless @@pre_clean_needed
29
- # Disable features on initial cleanup only as it's too expensive
30
- # to do a disable for every testcase.
31
- Feature.nv_overlay_disable
32
- # nv overlay is slow on some platforms
33
- sleep 1
34
- vxlan_linecard?
35
- if VxlanVtep.mt_full_support
36
- return unless Vdc.vdc_support
37
- v = Vdc.new('default')
38
- v.limit_resource_module_type = 'f3' unless
39
- v.limit_resource_module_type == 'f3'
40
- else
41
- config_no_warn('no feature vn-segment-vlan-based')
42
- end
28
+ vdc_limit_f3_no_intf_needed(:set) if VxlanVtep.mt_full_support
29
+ Interface.interfaces(:nve).each { |_nve, obj| obj.destroy }
30
+ feature_cleanup if @@pre_clean_needed
43
31
  Feature.nv_overlay_enable
44
32
  config_no_warn('feature vn-segment-vlan-based') if VxlanVtep.mt_lite_support
45
33
  @@pre_clean_needed = false # rubocop:disable Style/ClassVars
46
34
  end
47
35
 
48
36
  def teardown
49
- config_no_warn('no interface nve1')
37
+ if first_or_last_teardown
38
+ vdc_limit_f3_no_intf_needed(:clear)
39
+ feature_cleanup
40
+ end
50
41
  super
51
42
  end
52
43
 
44
+ def feature_cleanup
45
+ config_no_warn('no feature-set fabricpath')
46
+ config_no_warn('no feature vni')
47
+ config_no_warn('no feature vn-segment-vlan-based')
48
+ config_no_warn('no nv overlay evpn ; no feature nv overlay')
49
+ # Rapid nv feature toggle can cause failures on some platforms;
50
+ # symptom e.g. 'show runn | i ^feature' will hang
51
+ sleep 5
52
+ end
53
+
53
54
  def test_create_with_existing
54
55
  VxlanVtep.new('nve1').host_reachability = 'evpn'
55
56
  associate_vrf = true
@@ -110,6 +111,9 @@ class TestVxlanVtepVni < CiscoTestCase
110
111
  end
111
112
 
112
113
  def test_ingress_replication
114
+ skip_legacy_defect?('7.0.3.I3.1',
115
+ 'CSCuy27700: Validation failed for vni mcast group configured')
116
+
113
117
  vni = VxlanVtepVni.new('nve1', '5000')
114
118
  if validate_property_excluded?('vxlan_vtep_vni', 'ingress_replication')
115
119
  assert_raises(Cisco::UnsupportedError) { vni.ingress_replication = 'bgp' }
@@ -138,6 +142,9 @@ class TestVxlanVtepVni < CiscoTestCase
138
142
  end
139
143
 
140
144
  def test_multicast_group
145
+ skip_legacy_defect?('7.0.3.I3.1',
146
+ 'CSCuy27700: Validation failed for vni mcast group configured')
147
+
141
148
  vni1 = VxlanVtepVni.new('nve1', '6000')
142
149
  vni2 = VxlanVtepVni.new('nve1', '8001-8200')
143
150
 
@@ -0,0 +1,369 @@
1
+ #!/usr/bin/env ruby
2
+ # Yang Unit Tests
3
+ #
4
+ # Charles Burkett, May, 2016
5
+ #
6
+ # Copyright (c) 2015-2016 Cisco and/or its affiliates.
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+ require_relative 'ciscotest'
21
+ require_relative '../lib/cisco_node_utils/yang'
22
+
23
+ # TestYang - Minitest for Yang class
24
+ class TestYang < CiscoTestCase
25
+ BLUE_VRF = '{"Cisco-IOS-XR-infra-rsi-cfg:vrfs":{
26
+ "vrf":[
27
+ {
28
+ "vrf-name":"BLUE",
29
+ "description":"Generic external traffic",
30
+ "create":[
31
+ null
32
+ ]
33
+ }
34
+ ]
35
+ }}'
36
+
37
+ RED_VRF = '{"Cisco-IOS-XR-infra-rsi-cfg:vrfs":{
38
+ "vrf":[
39
+ {
40
+ "vrf-name":"RED",
41
+ "create":[
42
+ null
43
+ ]
44
+ }
45
+ ]
46
+ }}'
47
+
48
+ GREEN_VRF = '{"Cisco-IOS-XR-infra-rsi-cfg:vrfs":{
49
+ "vrf":[
50
+ {
51
+ "vrf-name":"GREEN",
52
+ "create": [null]
53
+ }
54
+ ]
55
+ }}'
56
+
57
+ BLUE_GREEN_VRF = '{"Cisco-IOS-XR-infra-rsi-cfg:vrfs":{
58
+ "vrf":[
59
+ {
60
+ "vrf-name":"BLUE",
61
+ "create":[null],
62
+ "description":"Generic external traffic"
63
+ },
64
+ {
65
+ "vrf-name":"GREEN",
66
+ "create":[null]
67
+ }
68
+ ]
69
+ }}'
70
+
71
+ BLUE_VRF_NO_PROPERTIES = '{"Cisco-IOS-XR-infra-rsi-cfg:vrfs":{
72
+ "vrf":[
73
+ {
74
+ "vrf-name":"BLUE",
75
+ "create":[
76
+ null
77
+ ]
78
+ }
79
+ ]
80
+ }}'
81
+
82
+ BLUE_VRF_PROPERTIES1 = '{"Cisco-IOS-XR-infra-rsi-cfg:vrfs":{
83
+ "vrf":[
84
+ {
85
+ "vrf-name":"BLUE",
86
+ "create":[
87
+ null
88
+ ],
89
+ "vpn-id":{
90
+ "vpn-oui":0,
91
+ "vpn-index":0
92
+ }
93
+ }
94
+ ]
95
+ }}'
96
+
97
+ BLUE_VRF_PROPERTIES2 = '{"Cisco-IOS-XR-infra-rsi-cfg:vrfs":{
98
+ "vrf":[
99
+ {
100
+ "vrf-name":"BLUE",
101
+ "description":"Generic external traffic",
102
+ "create":[
103
+ null
104
+ ],
105
+ "vpn-id":{
106
+ "vpn-oui":0,
107
+ "vpn-index":0
108
+ }
109
+ }
110
+ ]
111
+ }}'
112
+
113
+ BLUE_VRF_PROPERTIES3 = '{"Cisco-IOS-XR-infra-rsi-cfg:vrfs":{
114
+ "vrf":[
115
+ {
116
+ "vrf-name":"BLUE",
117
+ "description":"Generic ext traffic",
118
+ "create":[
119
+ null
120
+ ],
121
+ "vpn-id":{
122
+ "vpn-oui":8,
123
+ "vpn-index":9
124
+ }
125
+ }
126
+ ]
127
+ }}'
128
+
129
+ NO_VRFS = '{"Cisco-IOS-XR-infra-rsi-cfg:vrfs": [null]}'
130
+ PATH_VRFS = '{"Cisco-IOS-XR-infra-rsi-cfg:vrfs": [null]}'
131
+
132
+ def self.runnable_methods
133
+ return [:all_skipped] unless platform == :ios_xr
134
+ super
135
+ end
136
+
137
+ def all_skipped
138
+ puts 'Node under test does not appear to use the gRPC client'
139
+ assert(validate_property_excluded?('yang', 'support'))
140
+ end
141
+
142
+ def setup
143
+ super
144
+ clear_vrfs
145
+ end
146
+
147
+ def teardown
148
+ super
149
+ clear_vrfs
150
+ end
151
+
152
+ def clear_vrfs
153
+ return unless platform == :ios_xr
154
+ current_vrfs = node.get_yang(PATH_VRFS)
155
+
156
+ # remove all vrfs
157
+ node.delete_yang(PATH_VRFS) unless Yang.empty?(current_vrfs)
158
+ end
159
+
160
+ def test_delete_vrfs
161
+ node.merge_yang(BLUE_VRF) # ensure at least one VRF is there
162
+ assert(node.get_yang(PATH_VRFS).match('BLUE'), 'Did not find the BLUE vrf')
163
+
164
+ clear_vrfs
165
+ assert_equal('', node.get_yang(PATH_VRFS),
166
+ 'There are still vrfs configured')
167
+ end
168
+
169
+ def test_add_vrf
170
+ node.merge_yang(BLUE_VRF) # create a single VRF
171
+ assert(node.get_yang(PATH_VRFS).match('BLUE'), 'Did not find the BLUE vrf')
172
+
173
+ node.replace_yang(GREEN_VRF) # create a single VRF
174
+ assert(node.get_yang(PATH_VRFS).match('GREEN'),
175
+ 'Did not find the GREEN vrf')
176
+ refute(node.get_yang(PATH_VRFS).match('BLUE'),
177
+ 'Found the BLUE vrf')
178
+ end
179
+
180
+ def test_errors
181
+ # Note: Originally, we were checking for YangErrors and ClientErrors,
182
+ # but the type of error raised seemed to change from one XR image to the
183
+ # next, so now we check for the more general CiscoError in these tests.
184
+
185
+ # === test get_yang ===========
186
+
187
+ # Request is not wellformed
188
+ assert_raises(Cisco::CiscoError) { node.get_yang('aabbcc') }
189
+
190
+ # parse error: object key and value must be separated by a colon
191
+ assert_raises(Cisco::CiscoError) { node.get_yang('{"aabbcc"}') }
192
+
193
+ # unknown-namespace
194
+ assert_raises(Cisco::CiscoError) { node.get_yang('{"aabbcc": "foo"}') }
195
+
196
+ # unknown-element
197
+ assert_raises(Cisco::CiscoError) do
198
+ node.get_yang('{"Cisco-IOS-XR-infra-rsi-cfg:aabbcc": "foo"}')
199
+ end
200
+
201
+ # parse error: premature EOF
202
+ assert_raises(Cisco::CiscoError) { node.get_yang('{') }
203
+
204
+ # parse error: invalid object key (must be a string)
205
+ assert_raises(Cisco::CiscoError) { node.get_yang('{: "foo"}') }
206
+
207
+ # === test merge_yang ===========
208
+
209
+ # Request is not wellformed
210
+ assert_raises(Cisco::CiscoError) { node.merge_yang('aabbcc') }
211
+
212
+ # unknown-element
213
+ assert_raises(Cisco::CiscoError) do
214
+ node.merge_yang('{"Cisco-IOS-XR-infra-rsi-cfg:aabbcc": "foo"}')
215
+ end
216
+
217
+ # bad-element
218
+ assert_raises(Cisco::CiscoError) do
219
+ node.merge_yang('{"Cisco-IOS-XR-infra-rsi-cfg:vrfs": "foo"}')
220
+ end
221
+
222
+ # missing-element
223
+ assert_raises(Cisco::CiscoError) do
224
+ node.merge_yang('{"Cisco-IOS-XR-infra-rsi-cfg:vrfs": {"vrf":[{}]}}')
225
+ end
226
+
227
+ # === test replace_yang ===========
228
+
229
+ # unknown-namespace
230
+ assert_raises(Cisco::CiscoError) do
231
+ node.replace_yang('{"Cisco-IOS-XR-infra-rsi-cfg:aabbcc": "foo"}')
232
+ end
233
+
234
+ # Request is not wellformed
235
+ assert_raises(Cisco::CiscoError) do
236
+ node.replace_yang('{"Cisco-IOS-XR-infra-rsi-cfg:vrfs": }')
237
+ end
238
+ end
239
+
240
+ def test_merge_diff
241
+ # ensure we think that a merge is needed (in-sinc = false)
242
+ refute(Yang.insync_for_merge?(BLUE_VRF, node.get_yang(PATH_VRFS)),
243
+ 'Expected not in-sync')
244
+
245
+ node.merge_yang(BLUE_VRF) # create the blue VRF
246
+
247
+ # ensure we think that a merge is NOT needed (in-sinc = true)
248
+ assert(Yang.insync_for_merge?(BLUE_VRF, node.get_yang(PATH_VRFS)),
249
+ 'Expected in-sync')
250
+
251
+ # ensure we think that the merge is needed (in-sinc = false)
252
+ refute(Yang.insync_for_merge?(RED_VRF, node.get_yang(PATH_VRFS)),
253
+ 'Expected not in-sync')
254
+
255
+ node.merge_yang(RED_VRF) # create the red VRF
256
+
257
+ # ensure we think that a merge is NOT needed (in-sinc = true)
258
+ assert(Yang.insync_for_merge?(RED_VRF, node.get_yang(PATH_VRFS)),
259
+ 'Expected in-sync')
260
+
261
+ node.merge_yang(GREEN_VRF) # create green VRF
262
+ # ensure we think that a merge is NOT needed (in-sinc = true)
263
+ assert(Yang.insync_for_merge?(GREEN_VRF, node.get_yang(PATH_VRFS)),
264
+ 'Expected in-sync')
265
+ end
266
+
267
+ def test_replace_diff
268
+ # ensure we think that a merge is needed (in-sinc = false)
269
+ refute(Yang.insync_for_replace?(BLUE_VRF, node.get_yang(PATH_VRFS)),
270
+ 'Expected not in-sync')
271
+
272
+ node.replace_yang(BLUE_VRF) # create the blue VRF
273
+ # ensure we think that a replace is NOT needed (in-sinc = true)
274
+ assert(Yang.insync_for_replace?(BLUE_VRF, node.get_yang(PATH_VRFS)),
275
+ 'Expected in-sync')
276
+
277
+ node.replace_yang(RED_VRF) # create the red VRF
278
+ # ensure we think that a replace is NOT needed (in-sinc = true)
279
+ assert(Yang.insync_for_replace?(RED_VRF, node.get_yang(PATH_VRFS)),
280
+ 'Expected in-sync')
281
+
282
+ node.replace_yang(GREEN_VRF) # create green VRF
283
+ # ensure we think that a replace is NOT needed (in-sinc = true)
284
+ assert(Yang.insync_for_replace?(GREEN_VRF, node.get_yang(PATH_VRFS)),
285
+ 'Expected in-sync')
286
+
287
+ node.merge_yang(BLUE_VRF)
288
+
289
+ # ensure we think that a replace is NOT needed (in-sinc = true)
290
+ assert(Yang.insync_for_replace?(BLUE_GREEN_VRF, node.get_yang(PATH_VRFS)),
291
+ 'Expected in sync')
292
+ # ensure we think that a replace is needed (in-sinc = true)
293
+ refute(Yang.insync_for_replace?(BLUE_VRF, node.get_yang(PATH_VRFS)),
294
+ 'Expected not in sync')
295
+ refute(Yang.insync_for_replace?(GREEN_VRF, node.get_yang(PATH_VRFS)),
296
+ 'Expected not in sync')
297
+
298
+ node.replace_yang(BLUE_VRF)
299
+ # ensure we think that a replace is NOT needed (in-sinc = true)
300
+ assert(Yang.insync_for_replace?(BLUE_VRF, node.get_yang(PATH_VRFS)),
301
+ 'Expected in-sync')
302
+ # ensure we think that a replace is needed (in-sinc = true)
303
+ refute(Yang.insync_for_replace?(GREEN_VRF, node.get_yang(PATH_VRFS)),
304
+ 'Expected not in-sync')
305
+ refute(Yang.insync_for_replace?(BLUE_GREEN_VRF, node.get_yang(PATH_VRFS)),
306
+ 'Expected not in-sync')
307
+ end
308
+
309
+ def test_merge_leaves
310
+ node.merge_yang(BLUE_VRF) # create blue vrf with description
311
+
312
+ # merge blue vrf with vpn id to blue vrf with description
313
+ node.merge_yang(BLUE_VRF_PROPERTIES1)
314
+
315
+ # ensure that new leaves are merged with old.
316
+ assert(Yang.insync_for_merge?(BLUE_VRF_PROPERTIES2,
317
+ node.get_yang(PATH_VRFS)), 'Expected in-sync')
318
+
319
+ # update description and vpn-id
320
+ node.merge_yang(BLUE_VRF_PROPERTIES3)
321
+ assert(Yang.insync_for_merge?(BLUE_VRF_PROPERTIES3,
322
+ node.get_yang(PATH_VRFS)), 'Expected in-sync')
323
+ end
324
+
325
+ def test_replace_leaves
326
+ node.replace_yang(BLUE_VRF) # create blue vrf with description
327
+
328
+ # replace blue vrf (description) by blue vrf (vpn-id)
329
+ node.replace_yang(BLUE_VRF_PROPERTIES1)
330
+
331
+ # ensure that new properties are replaced by old.
332
+ assert(Yang.insync_for_replace?(BLUE_VRF_PROPERTIES1,
333
+ node.get_yang(PATH_VRFS)),
334
+ 'Expected in-sync')
335
+
336
+ # replace description and vpn-id
337
+ node.replace_yang(BLUE_VRF_PROPERTIES3)
338
+ assert(Yang.insync_for_replace?(BLUE_VRF_PROPERTIES3,
339
+ node.get_yang(PATH_VRFS)),
340
+ 'Expected in-sync')
341
+ end
342
+
343
+ def test_merge
344
+ node.merge_yang(BLUE_VRF) # create blue vrf
345
+ node.merge_yang(GREEN_VRF) # create green vrf
346
+
347
+ yang = node.get_yang(PATH_VRFS)
348
+
349
+ assert_yang_equal(BLUE_GREEN_VRF, yang)
350
+ end
351
+
352
+ def test_replace
353
+ node.merge_yang(BLUE_VRF) # create blue vrf
354
+ node.replace_yang(GREEN_VRF) # create green vrf
355
+
356
+ yang = node.get_yang(PATH_VRFS)
357
+
358
+ assert_yang_equal(GREEN_VRF, yang)
359
+ end
360
+
361
+ def assert_yang_equal(expected, actual)
362
+ equal = Yang.insync_for_replace?(expected, actual) &&
363
+ Yang.insync_for_replace?(actual, expected)
364
+ assert(equal,
365
+ "Expected: '#{expected}',\n"\
366
+ "Actual: '#{actual}',\n",
367
+ )
368
+ end
369
+ end