rbeapi 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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