rbeapi 0.4.0 → 0.5.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 (83) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG.md +20 -0
  3. data/Gemfile +1 -1
  4. data/README.md +11 -11
  5. data/Rakefile +19 -0
  6. data/guide/Makefile +177 -0
  7. data/guide/_static/arista_logo_11-trans-w.png +0 -0
  8. data/guide/_static/arista_logo_jpg-11.jpg +0 -0
  9. data/guide/_static/favicon.ico +0 -0
  10. data/guide/conf.py +279 -0
  11. data/guide/cookbook.rst +4 -0
  12. data/guide/developing.rst +4 -0
  13. data/guide/faq.rst +4 -0
  14. data/guide/index.rst +23 -0
  15. data/guide/installation.rst +4 -0
  16. data/guide/license.rst +5 -0
  17. data/guide/overview.rst +20 -0
  18. data/guide/quickstart.rst +4 -0
  19. data/guide/release-notes-0.5.0.rst +60 -0
  20. data/guide/release-notes.rst +6 -0
  21. data/guide/testing.rst +4 -0
  22. data/guide/troubleshooting.rst +1 -0
  23. data/lib/rbeapi/api/aaa.rb +54 -18
  24. data/lib/rbeapi/api/acl.rb +60 -2
  25. data/lib/rbeapi/api/bgp.rb +81 -0
  26. data/lib/rbeapi/api/dns.rb +48 -2
  27. data/lib/rbeapi/api/interfaces.rb +97 -32
  28. data/lib/rbeapi/api/ipinterfaces.rb +13 -2
  29. data/lib/rbeapi/api/logging.rb +11 -2
  30. data/lib/rbeapi/api/mlag.rb +20 -10
  31. data/lib/rbeapi/api/ntp.rb +4 -3
  32. data/lib/rbeapi/api/ospf.rb +102 -10
  33. data/lib/rbeapi/api/prefixlists.rb +47 -4
  34. data/lib/rbeapi/api/radius.rb +9 -9
  35. data/lib/rbeapi/api/routemaps.rb +7 -5
  36. data/lib/rbeapi/api/snmp.rb +13 -4
  37. data/lib/rbeapi/api/staticroutes.rb +1 -1
  38. data/lib/rbeapi/api/stp.rb +39 -14
  39. data/lib/rbeapi/api/switchports.rb +126 -2
  40. data/lib/rbeapi/api/system.rb +24 -3
  41. data/lib/rbeapi/api/tacacs.rb +9 -10
  42. data/lib/rbeapi/api/users.rb +12 -3
  43. data/lib/rbeapi/api/varp.rb +40 -8
  44. data/lib/rbeapi/api/vlans.rb +15 -5
  45. data/lib/rbeapi/client.rb +19 -11
  46. data/lib/rbeapi/eapilib.rb +8 -0
  47. data/lib/rbeapi/utils.rb +10 -0
  48. data/lib/rbeapi/version.rb +1 -1
  49. data/spec/fixtures/eapi.conf.yaml +6 -0
  50. data/spec/fixtures/empty.conf +0 -0
  51. data/spec/fixtures/env_path.conf +5 -0
  52. data/spec/fixtures/test.conf +39 -0
  53. data/spec/fixtures/wildcard.conf +43 -0
  54. data/spec/system/rbeapi/api/aaa_groups_spec.rb +122 -0
  55. data/spec/system/rbeapi/api/aaa_spec.rb +90 -0
  56. data/spec/system/{api_acl_spec.rb → rbeapi/api/acl_spec.rb} +0 -0
  57. data/spec/system/rbeapi/api/bgp_neighbors_spec.rb +354 -0
  58. data/spec/system/rbeapi/api/bgp_spec.rb +275 -0
  59. data/spec/system/rbeapi/api/dns_spec.rb +17 -1
  60. data/spec/system/rbeapi/api/interfaces_base_spec.rb +46 -5
  61. data/spec/system/rbeapi/api/interfaces_ethernet_spec.rb +14 -0
  62. data/spec/system/rbeapi/api/interfaces_portchannel_spec.rb +68 -0
  63. data/spec/system/rbeapi/api/interfaces_vxlan_spec.rb +0 -1
  64. data/spec/system/{api_ospf_interfaces_spec.rb → rbeapi/api/ospf_interfaces_spec.rb} +3 -2
  65. data/spec/system/{api_ospf_spec.rb → rbeapi/api/ospf_spec.rb} +11 -2
  66. data/spec/system/rbeapi/api/routemaps_spec.rb +3 -4
  67. data/spec/system/rbeapi/api/snmp_spec.rb +65 -0
  68. data/spec/system/rbeapi/api/staticroutes_spec.rb +177 -0
  69. data/spec/system/rbeapi/api/stp_instances_spec.rb +20 -0
  70. data/spec/system/rbeapi/api/stp_interfaces_spec.rb +7 -0
  71. data/spec/system/rbeapi/api/switchports_spec.rb +86 -16
  72. data/spec/system/rbeapi/api/users_spec.rb +324 -0
  73. data/spec/system/rbeapi/api/varp_interfaces_spec.rb +34 -0
  74. data/spec/system/rbeapi/api/vrrp_spec.rb +707 -0
  75. data/spec/system/rbeapi/client_spec.rb +367 -0
  76. data/spec/unit/rbeapi/api/aaa/aaa_groups_spec.rb +111 -0
  77. data/spec/unit/rbeapi/api/aaa/aaa_spec.rb +77 -0
  78. data/spec/unit/rbeapi/api/aaa/fixture_aaa.text +3 -0
  79. data/spec/unit/rbeapi/api/switchports/default_spec.rb +249 -0
  80. data/spec/unit/rbeapi/api/switchports/fixture_switchports.text +284 -0
  81. data/spec/unit/rbeapi/api/users/default_spec.rb +1 -1
  82. data/spec/unit/rbeapi/client_spec.rb +211 -0
  83. metadata +65 -10
@@ -0,0 +1,367 @@
1
+ #
2
+ # Copyright (c) 2015, Arista Networks, Inc.
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are
7
+ # met:
8
+ #
9
+ # Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # Neither the name of Arista Networks nor the names of its
17
+ # contributors may be used to endorse or promote products derived from
18
+ # this software without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS
24
+ # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30
+ # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ #
32
+ require 'spec_helper'
33
+
34
+ require 'rbeapi/client'
35
+
36
+ describe Rbeapi::Client do
37
+ subject { described_class }
38
+
39
+ def dut_conf
40
+ fixture_file('dut.conf')
41
+ end
42
+
43
+ def test_conf
44
+ fixture_file('test.conf')
45
+ end
46
+
47
+ let(:node) do
48
+ subject.config.read(fixture_file('dut.conf'))
49
+ subject.connect_to('dut')
50
+ end
51
+
52
+ let(:dut) do
53
+ File.read(dut_conf)
54
+ end
55
+
56
+ let(:test) do
57
+ File.read(test_conf)
58
+ end
59
+
60
+ let(:enablepwd) { 'enable_admin' }
61
+
62
+ let(:veos01) do
63
+ {
64
+ 'username' => 'eapi',
65
+ 'password' => 'password',
66
+ 'transport' => 'http',
67
+ 'host' => 'veos01'
68
+ }
69
+ end
70
+
71
+ let(:veos05) do
72
+ {
73
+ 'host' => '172.16.131.40',
74
+ 'username' => 'admin',
75
+ 'password' => 'admin',
76
+ 'enablepwd' => 'password',
77
+ 'transport' => 'https',
78
+ 'port' => 1234,
79
+ 'open_timeout' => 12,
80
+ 'read_timeout' => 12
81
+ }
82
+ end
83
+
84
+ let(:test_data) do
85
+ [
86
+ '[connection:veos01]'
87
+ ]
88
+ end
89
+
90
+ # Client class methods
91
+ describe '#config_for' do
92
+ it 'returns the configuration options for the connection' do
93
+ expect(subject.load_config(test_conf)).to eq(nil)
94
+ expect(subject.config_for('veos01')).to eq(veos01)
95
+ end
96
+
97
+ it 'returns nil if connection does not exist' do
98
+ expect(subject.config_for('veos22')).to eq(nil)
99
+ end
100
+ end
101
+
102
+ describe '#connect_to' do
103
+ it 'retrieves the node config' do
104
+ expect(subject.connect_to('veos01')).to be_truthy
105
+ end
106
+
107
+ it 'returns nil if connection does not exist' do
108
+ expect(subject.connect_to('veos22')).to eq(nil)
109
+ end
110
+ end
111
+
112
+ describe '#load_config' do
113
+ it 'overrides the default conf file loaded in the config' do
114
+ expect(subject.load_config(test_conf)).to eq(nil)
115
+ end
116
+
117
+ it 'returns nil if connection does not exit' do
118
+ expect(subject.load_config(test_conf)).to eq(nil)
119
+ expect(subject.config_for('dut')).to eq(nil)
120
+ end
121
+
122
+ it 'returns conf settings if connection exists' do
123
+ expect(subject.load_config(test_conf)).to eq(nil)
124
+ expect(subject.config_for('veos01')).to eq(veos01)
125
+ end
126
+ end
127
+
128
+ # Config class methods
129
+ describe 'config' do
130
+ it 'gets the loaded configuration file data' do
131
+ expect(subject.load_config(test_conf)).to eq(nil)
132
+ expect(subject.config.to_s).to include(test_data[0])
133
+ end
134
+ end
135
+
136
+ describe '#read' do
137
+ it 'read the specified filename and load dut' do
138
+ expect(subject.config.read(dut_conf)).to eq(nil)
139
+ expect(subject.config.to_s)
140
+ .to include('host', 'username', 'password', '[connection:dut]')
141
+ end
142
+
143
+ it 'read the specified filename and load test' do
144
+ expect(subject.config.read(test_conf)).to eq(nil)
145
+ expect(subject.config.to_s).to include(test_data[0])
146
+ end
147
+ end
148
+
149
+ describe '#get_connection' do
150
+ it 'get connection veos01' do
151
+ expect(subject.config.get_connection('veos01')).to eq(veos01)
152
+ end
153
+
154
+ it 'get connection veos05' do
155
+ expect(subject.config.get_connection('veos05')).to eq(veos05)
156
+ end
157
+ end
158
+
159
+ describe '#reload' do
160
+ it 'reloads the configuration file' do
161
+ expect(subject.config.get_connection('veos01')).to eq(veos01)
162
+ expect(subject.config.reload(filename: [dut_conf])).to eq(nil)
163
+ expect(subject.config.get_connection('veos01')).to eq(nil)
164
+ expect(subject.config.get_connection('dut')).not_to be_nil
165
+ end
166
+ end
167
+
168
+ describe '#add_connection' do
169
+ it 'adds a new connection section' do
170
+ expect(subject.config.add_connection('test2',
171
+ username: 'test2',
172
+ password: 'test',
173
+ transport: 'http',
174
+ host: 'test2'
175
+ )).to eq(nil)
176
+ expect(subject.config.get_connection('test2'))
177
+ .to eq(username: 'test2',
178
+ password: 'test',
179
+ transport: 'http',
180
+ host: 'test2')
181
+ end
182
+ end
183
+
184
+ # Node Class Methods
185
+ describe 'node' do
186
+ it 'retrieves the node' do
187
+ expect(node).to be_kind_of(Rbeapi::Client::Node)
188
+ end
189
+ end
190
+
191
+ describe '#running_config' do
192
+ it 'gets the nodes running config' do
193
+ expect(node.running_config).to be_truthy
194
+ end
195
+
196
+ it 'expects running config to return a string' do
197
+ expect(node.running_config).to be_kind_of(String)
198
+ end
199
+ end
200
+
201
+ describe '#startup_config' do
202
+ it 'gets the nodes startup-configuration' do
203
+ expect(node.startup_config).to be_truthy
204
+ end
205
+
206
+ it 'expects startup-configuration to be a string' do
207
+ expect(node.startup_config).to be_kind_of(String)
208
+ end
209
+ end
210
+
211
+ describe '#config' do
212
+ it 'puts switch into config mode' do
213
+ expect(node.config(['no ip virtual-router mac-address']))
214
+ .to be_truthy
215
+ end
216
+
217
+ it 'expects config to return array' do
218
+ expect(node.config(['no ip virtual-router mac-address']))
219
+ .to be_kind_of(Array)
220
+ end
221
+
222
+ it 'puts switch into config mode with options and returns array' do
223
+ expect(node.config(['no ip virtual-router mac-address'],
224
+ encoding: 'json',
225
+ open_timeout: 27.00,
226
+ read_timeout: 27.00))
227
+ .to be_kind_of(Array)
228
+ end
229
+
230
+ describe 'set dry run' do
231
+ before do
232
+ # Prevents puts from writing to console
233
+ allow($stdout).to receive(:puts)
234
+ node.dry_run = true
235
+ end
236
+
237
+ it 'expects config to do dry run' do
238
+ expect(node.config(['no ip virtual-router mac-address']))
239
+ .to eq(nil)
240
+ end
241
+ end
242
+
243
+ it 'returns error if invalid command' do
244
+ expect { node.config(['no ip virtual-router mac-addresses']) }
245
+ .to raise_error Rbeapi::Eapilib::CommandError
246
+ end
247
+ end
248
+
249
+ describe '#enable' do
250
+ it 'puts the switch into privilege mode' do
251
+ expect(node.enable('show hostname')[0][:result])
252
+ .to include('fqdn', 'hostname')
253
+ end
254
+
255
+ it 'puts the switch into privilege mode with encoding' do
256
+ expect(node.enable('show hostname', encoding: 'text')[0][:encoding])
257
+ .to eq('text')
258
+ end
259
+
260
+ it 'puts the switch into privilege mode with strict option' do
261
+ expect(node.enable('show hostname', strict: true)[0])
262
+ .to include(:command, :result, :encoding)
263
+ end
264
+
265
+ it 'puts the switch into privilege mode with read and open timeout' do
266
+ expect(node.enable('show hostname',
267
+ open_timeout: 29,
268
+ read_timeout: 29)[0]).to include(:command,
269
+ :result,
270
+ :encoding)
271
+ end
272
+
273
+ it 'raises invalid command error' do
274
+ expect { node.enable(['show hostname', 'do this thing']) }
275
+ .to raise_error Rbeapi::Eapilib::CommandError
276
+ end
277
+ end
278
+
279
+ describe '#run_commands' do
280
+ it 'expects run_commands to be a string' do
281
+ expect(node.run_commands('show hostname', encoding: 'text')[0]['output'])
282
+ .to be_kind_of String
283
+ end
284
+
285
+ it 'sends commands to node with encoding' do
286
+ expect(node.run_commands('show hostname', encoding: 'text')[0]['output'])
287
+ .to include('FQDN:', 'Hostname:')
288
+ end
289
+
290
+ it 'sends commands with open and read timeout' do
291
+ expect(node.run_commands('show hostname',
292
+ open_timeout: 26,
293
+ read_timeout: 26)[0]).to include('fqdn',
294
+ 'hostname')
295
+ end
296
+
297
+ it 'expects run_commands to raise a command error' do
298
+ expect { node.run_commands('do this thing') }
299
+ .to raise_error Rbeapi::Eapilib::CommandError
300
+ end
301
+ end
302
+
303
+ describe '#run_commands with enable password' do
304
+ # Before the tests Set the enable password on the dut
305
+ before(:each) { node.config(["enable secret 0 #{enablepwd}"]) }
306
+
307
+ # After the tests clear the enable password on the dut
308
+ after(:each) { node.config(['no enable secret']) }
309
+
310
+ it 'sends commands with enablepwd set' do
311
+ expect(node.enable_authentication(enablepwd)).to eq(enablepwd)
312
+ expect(node.run_commands('show hostname')).to be_truthy
313
+ end
314
+ end
315
+
316
+ describe '#get_config' do
317
+ it 'will retrieve the specified configuration and return array' do
318
+ expect(node.get_config(config: 'running-config'))
319
+ .to be_kind_of(Array)
320
+ end
321
+
322
+ it 'will retrieve with param and return array' do
323
+ expect(node.get_config(config: 'running-config', param: 'all'))
324
+ .to be_kind_of(Array)
325
+ end
326
+
327
+ it 'raises invalid command error' do
328
+ expect { node.get_config(config: 'running-configurations') }
329
+ .to raise_error Rbeapi::Eapilib::CommandError
330
+ end
331
+ end
332
+
333
+ describe '#api' do
334
+ it 'returns api module' do
335
+ expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans)
336
+ end
337
+
338
+ it 'returns error if invalid name' do
339
+ expect { node.api('vlanss') }.to raise_error
340
+ end
341
+ end
342
+
343
+ describe '#refresh' do
344
+ it 'refreshes configs for next call' do
345
+ expect(node.refresh).to eq(nil)
346
+ end
347
+ end
348
+
349
+ describe 'test timeouts' do
350
+ it 'loads default timeout values' do
351
+ expect(node.connection.get_timeouts).to eq(open_timeout: 10,
352
+ read_timeout: 10)
353
+ end
354
+
355
+ describe 'loads veos05' do
356
+ let(:node) do
357
+ subject.config.read(fixture_file('test.conf'))
358
+ subject.connect_to('veos05')
359
+ end
360
+
361
+ it 'loads timeout values from conf file' do
362
+ expect(node.connection.get_timeouts).to eq(open_timeout: 12,
363
+ read_timeout: 12)
364
+ end
365
+ end
366
+ end
367
+ end
@@ -0,0 +1,111 @@
1
+ #
2
+ # Copyright (c) 2015, Arista Networks, Inc.
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are
7
+ # met:
8
+ #
9
+ # Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # Neither the name of Arista Networks nor the names of its
17
+ # contributors may be used to endorse or promote products derived from
18
+ # this software without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS
24
+ # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30
+ # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ #
32
+ require 'spec_helper'
33
+
34
+ require 'rbeapi/api/aaa'
35
+
36
+ include FixtureHelpers
37
+
38
+ describe Rbeapi::Api::AaaGroups do
39
+ subject { described_class.new(node) }
40
+
41
+ let(:node) { double('node') }
42
+
43
+ let(:all) do
44
+ {
45
+ 'blah' => {
46
+ type: 'radius',
47
+ servers: []
48
+ }
49
+ }
50
+ end
51
+
52
+ let(:blah) do
53
+ {
54
+ type: 'radius',
55
+ servers: []
56
+ }
57
+ end
58
+
59
+ let(:blahthree) do
60
+ {
61
+ type: 'tacacs+',
62
+ servers: []
63
+ }
64
+ end
65
+
66
+ def aaa
67
+ aaa = Fixtures[:aaa]
68
+ return aaa if aaa
69
+ fixture('aaa', format: :text, dir: File.dirname(__FILE__))
70
+ end
71
+
72
+ before :each do
73
+ allow(subject.node).to receive(:running_config).and_return(aaa)
74
+ end
75
+
76
+ describe '#get' do
77
+ it 'returns the resource for given name' do
78
+ expect(subject.get('blah')).to eq(blah)
79
+ end
80
+ end
81
+
82
+ describe '#getall' do
83
+ it 'returns all of the aaa group resources' do
84
+ expect(subject.getall).to eq(all)
85
+ end
86
+ end
87
+
88
+ describe '#create' do
89
+ it 'adds a new aaa group' do
90
+ expect(node).to receive(:config)
91
+ .with(['aaa group server tacacs+ blahthree', 'exit'])
92
+ expect(subject.create('blahthree', 'tacacs+')).to eq(true)
93
+ end
94
+ end
95
+
96
+ describe '#delete' do
97
+ it 'removes specified aaa group' do
98
+ expect(subject.delete('blahthree')).to eq(true)
99
+ expect(subject.get('blahthree')).to eq(nil)
100
+ end
101
+ end
102
+
103
+ describe '#set_servers' do
104
+ it 'removes all servers and then adds one' do
105
+ expect(node).to receive(:config)
106
+ .with(['aaa group server radius blah', 'server localhost ', 'exit'])
107
+ expect(subject.set_servers('blah', [{ name: 'localhost' }]))
108
+ .to eq(true)
109
+ end
110
+ end
111
+ end