rbeapi 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/.gitignore +35 -0
  2. data/Gemfile +25 -0
  3. data/Guardfile +15 -0
  4. data/LICENSE +28 -0
  5. data/README.md +218 -0
  6. data/Rakefile +12 -0
  7. data/lib/rbeapi.rb +32 -0
  8. data/lib/rbeapi/api.rb +135 -0
  9. data/lib/rbeapi/api/aaa.rb +410 -0
  10. data/lib/rbeapi/api/dns.rb +198 -0
  11. data/lib/rbeapi/api/interfaces.rb +1193 -0
  12. data/lib/rbeapi/api/ipinterfaces.rb +328 -0
  13. data/lib/rbeapi/api/logging.rb +157 -0
  14. data/lib/rbeapi/api/mlag.rb +519 -0
  15. data/lib/rbeapi/api/ntp.rb +201 -0
  16. data/lib/rbeapi/api/ospf.rb +214 -0
  17. data/lib/rbeapi/api/prefixlists.rb +98 -0
  18. data/lib/rbeapi/api/radius.rb +317 -0
  19. data/lib/rbeapi/api/radius.rb.old +399 -0
  20. data/lib/rbeapi/api/routemaps.rb +100 -0
  21. data/lib/rbeapi/api/snmp.rb +427 -0
  22. data/lib/rbeapi/api/staticroutes.rb +88 -0
  23. data/lib/rbeapi/api/stp.rb +381 -0
  24. data/lib/rbeapi/api/switchports.rb +272 -0
  25. data/lib/rbeapi/api/system.rb +87 -0
  26. data/lib/rbeapi/api/tacacs.rb +236 -0
  27. data/lib/rbeapi/api/varp.rb +181 -0
  28. data/lib/rbeapi/api/vlans.rb +338 -0
  29. data/lib/rbeapi/client.rb +454 -0
  30. data/lib/rbeapi/eapilib.rb +334 -0
  31. data/lib/rbeapi/netdev/snmp.rb +370 -0
  32. data/lib/rbeapi/utils.rb +70 -0
  33. data/lib/rbeapi/version.rb +37 -0
  34. data/rbeapi.gemspec +32 -0
  35. data/spec/fixtures/dut.conf +5 -0
  36. data/spec/spec_helper.rb +22 -0
  37. data/spec/support/fixtures.rb +114 -0
  38. data/spec/support/shared_examples_for_api_modules.rb +124 -0
  39. data/spec/system/api_ospf_interfaces_spec.rb +58 -0
  40. data/spec/system/api_ospf_spec.rb +111 -0
  41. data/spec/system/api_varp_interfaces_spec.rb +60 -0
  42. data/spec/system/api_varp_spec.rb +44 -0
  43. data/spec/system/rbeapi/api/dns_spec.rb +77 -0
  44. data/spec/system/rbeapi/api/interfaces_base_spec.rb +94 -0
  45. data/spec/system/rbeapi/api/interfaces_ethernet_spec.rb +135 -0
  46. data/spec/system/rbeapi/api/interfaces_portchannel_spec.rb +188 -0
  47. data/spec/system/rbeapi/api/interfaces_vxlan_spec.rb +115 -0
  48. data/spec/system/rbeapi/api/ipinterfaces_spec.rb +97 -0
  49. data/spec/system/rbeapi/api/logging_spec.rb +65 -0
  50. data/spec/system/rbeapi/api/mlag_interfaces_spec.rb +80 -0
  51. data/spec/system/rbeapi/api/mlag_spec.rb +94 -0
  52. data/spec/system/rbeapi/api/ntp_spec.rb +76 -0
  53. data/spec/system/rbeapi/api/snmp_spec.rb +68 -0
  54. data/spec/system/rbeapi/api/stp_instances_spec.rb +61 -0
  55. data/spec/system/rbeapi/api/stp_interfaces_spec.rb +71 -0
  56. data/spec/system/rbeapi/api/stp_spec.rb +57 -0
  57. data/spec/system/rbeapi/api/switchports_spec.rb +135 -0
  58. data/spec/system/rbeapi/api/system_spec.rb +38 -0
  59. data/spec/system/rbeapi/api/vlans_spec.rb +121 -0
  60. metadata +274 -0
@@ -0,0 +1,181 @@
1
+ #
2
+ # Copyright (c) 2014, 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 'rbeapi/api'
33
+
34
+ module Rbeapi
35
+
36
+ module Api
37
+
38
+ ##
39
+ # The Varp class provides an instance for working with the global
40
+ # VARP configuration of the node
41
+ class Varp < Entity
42
+
43
+ ##
44
+ # Returns the global VARP configuration from the node
45
+ #
46
+ # Example
47
+ # {
48
+ # "mac_address": <string>,
49
+ # "interfaces": {...}
50
+ # }
51
+ #
52
+ # @return [Hash] A Ruby hash object that provides the Varp settings as
53
+ # key / value pairs.
54
+ def get
55
+ response = {}
56
+
57
+ regex = %r{
58
+ (?<=^ip\svirtual-router\smac-address\s)
59
+ ((?:[a-f0-9]{2}:){5}[a-f0-9]{2})$
60
+ }x
61
+
62
+ mdata = regex.match(config)
63
+ response['mac_address'] = mdata.nil? ? '' : mdata[1]
64
+ response['interfaces'] = interfaces.getall
65
+ response
66
+ end
67
+
68
+ def interfaces
69
+ return @interfaces if @interfaces
70
+ @interfaces = VarpInterfaces.new(node)
71
+ @interfaces
72
+ end
73
+
74
+ ##
75
+ # Configure the VARP virtual-router mac-address value
76
+ #
77
+ # @param [Hash] opts The configuration parameters
78
+ # @option opts [string] :value The value to set the mac-address to
79
+ # @option opts [Boolean] :default The value should be set to default
80
+ #
81
+ # @return [Boolean] returns true if the command completed successfully
82
+ def set_mac_address(opts = {})
83
+ value = opts[:value]
84
+ default = opts[:default] || false
85
+
86
+ case default
87
+ when true
88
+ cmds = ['default ip virtual-router mac-address']
89
+ when false
90
+ cmds = (value ? "ip virtual-router mac-address #{value}" : \
91
+ 'no ip virtual-router mac-address')
92
+ end
93
+ configure(cmds)
94
+ end
95
+ end
96
+
97
+ class VarpInterfaces < Entity
98
+ ##
99
+ # Returns a single VARP interface configuration
100
+ #
101
+ # Example
102
+ # {
103
+ # "name": <string>,
104
+ # "addresses": array<string>
105
+ # }
106
+ #
107
+ # @param [String] :name The interface name to return the configuration
108
+ # values for. This must be the full interface identifier.
109
+ #
110
+ # @return [nil, Hash<String, String>] A Ruby hash that represents the
111
+ # VARP interface confguration. A nil object is returned if the
112
+ # specified interface is not configured
113
+ def get(name)
114
+ config = get_block("^interface #{name}")
115
+ return nil unless config
116
+ addrs = config.scan(/(?<=\s{3}ip\svirtual-router\saddress\s).+$/)
117
+ { 'addresses' => addrs }
118
+ end
119
+
120
+ ##
121
+ # Returns the collection of MLAG interfaces as a hash index by the
122
+ # interface name
123
+ #
124
+ # Example
125
+ # {
126
+ # <name>: {...},
127
+ # <name>: {...}
128
+ # }
129
+ #
130
+ # @return [nil, Hash<String, String>] A Ruby hash that represents the
131
+ # MLAG interface confguration. A nil object is returned if no
132
+ # interfaces are configured.
133
+ def getall
134
+ interfaces = config.scan(/(?<=^interface\s)(Vl.+)$/)
135
+ interfaces.first.each_with_object({}) do |name, resp|
136
+ data = get(name)
137
+ resp[name] = data if data
138
+ end
139
+ end
140
+
141
+ ##
142
+ # Creates a new MLAG interface with the specified mlag id
143
+ #
144
+ # @param [String] :name The name of the interface to create. The
145
+ # name argument must be the full interface name. Valid interfaces
146
+ # are restricted to Port-Channel interfaces
147
+ # @param [String] :id The MLAG ID to confgure for the specified
148
+ # interface name
149
+ #
150
+ # @return [Boolean] True if the commands succeeds otherwise False
151
+ def set_addresses(name, opts = {})
152
+ value = opts[:value]
153
+ default = opts[:default] || false
154
+
155
+ case default
156
+ when true
157
+ return configure('default ip virtual-router address')
158
+ when false
159
+ get(name)['addresses'].each do |addr|
160
+ result = remove_address(name, addr)
161
+ return result unless result
162
+ end
163
+ value.each do |addr|
164
+ result = add_address(name, addr)
165
+ return result unless result
166
+ end
167
+ end
168
+ return true
169
+ end
170
+
171
+ def add_address(name, value)
172
+ configure(["interface #{name}", "ip virtual-router address #{value}"])
173
+ end
174
+
175
+ def remove_address(name, value)
176
+ configure(["interface #{name}",
177
+ "no ip virtual-router address #{value}"])
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,338 @@
1
+ #
2
+ # Copyright (c) 2014, 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 'rbeapi/api'
33
+
34
+ module Rbeapi
35
+
36
+ ##
37
+ # Api is module namesapce for working with the EOS command API
38
+ module Api
39
+
40
+ ##
41
+ # The Vlan class provides a class implementation for working with the
42
+ # collection of Vlans on the node. This class presents an abstraction
43
+ # of the nodes configured vlan id's from the running configuration.
44
+ #
45
+ # @eos_version 4.13.7M
46
+ class Vlans < Entity
47
+
48
+ ##
49
+ # get returns the specified vlan resource Hash that represents the
50
+ # nodes current vlan configuration.
51
+ #
52
+ # @example
53
+ # {
54
+ # name: <string>
55
+ # state: <string>
56
+ # trunk_groups: array[<string]
57
+ # }
58
+ #
59
+ # @param [String] id The vlan id to return a resource for from the
60
+ # nodes configuration
61
+ #
62
+ # @return [nil, Hash<Symbol, Object>] Returns the vlan resource as a
63
+ # Hash. If the specified vlan id is not found in the nodes current
64
+ # configuration a nil object is returned
65
+ def get(id)
66
+ config = get_block("vlan #{id}")
67
+ return nil unless config
68
+ response = {}
69
+ response.merge!(parse_name(config))
70
+ response.merge!(parse_state(config))
71
+ response.merge!(parse_trunk_groups(config))
72
+ response
73
+ end
74
+
75
+ ##
76
+ # getall returns the collection of vlan resources from the nodes
77
+ # running configuration as a hash. The vlan resource collection
78
+ # hash is keyed by the unique vlan id
79
+ #
80
+ # @example
81
+ # {
82
+ # <vlanid>: {...}
83
+ # }
84
+ #
85
+ # @see get Vlan resource example
86
+ #
87
+ # @return [Hash<Symbol, Object>] returns a hash that represents the
88
+ # entire vlan collection from the nodes running configuration. If
89
+ # there are no vlans configured, this method will return an empty
90
+ # hash
91
+ def getall
92
+ vlans = config.scan(/(?<=^vlan\s)\d+$/)
93
+ vlans.each_with_object({}) do |vid, hsh|
94
+ resource = get vid
95
+ hsh[vid] = resource if resource
96
+ end
97
+ end
98
+
99
+ ##
100
+ # parse_name scans the provided configuration block and parses the
101
+ # vlan name value. The vlan name should always return a value
102
+ # from the running conifguration. The return value is intended to
103
+ # be merged into the resource hash
104
+ #
105
+ # @api private
106
+ #
107
+ # @return [Hash<Symbol, Object>] resource hash attribute
108
+ def parse_name(config)
109
+ mdata = /name (\w+)$/.match(config)
110
+ { name: mdata[1] }
111
+ end
112
+ private :parse_name
113
+
114
+ ##
115
+ # parse_state scans the provided configuration block and parses the
116
+ # vlan state value. The vlan state should always return a value from
117
+ # the nodes running configuration. The return hash is intended to be
118
+ # merged into the resource hash
119
+ #
120
+ # @api private
121
+ #
122
+ # @return [Hash<Symbol, Object>] resource hash attribute
123
+ def parse_state(config)
124
+ mdata = /state (\w+)$/.match(config)
125
+ { state: mdata[1] }
126
+ end
127
+ private :parse_state
128
+
129
+ ##
130
+ # parse_trunk_groups scans the provided configuration block and parses
131
+ # the trunk groups. If no trunk groups are found in the nodes
132
+ # running configuration then an empty array is returned as the value.
133
+ # The return hash is intedned to be merged into the resource hash.
134
+ #
135
+ # @api private
136
+ #
137
+ # @return [Hash<Symbol, Object>] resource hash attribute
138
+ def parse_trunk_groups(config)
139
+ values = config.scan(/trunk group (.+)$/).first
140
+ values = [] unless values
141
+ { trunk_groups: values }
142
+ end
143
+ private :parse_trunk_groups
144
+
145
+ ##
146
+ # create will create a new vlan resource in the nodes current
147
+ # configuration with the specified vlan id. If the create method
148
+ # is called and the vlan id already exists, this method will still
149
+ # return true.
150
+ #
151
+ # @eos_version 4.13.7M
152
+ #
153
+ # @commands
154
+ # vlan <value>
155
+ #
156
+ # @param [String, Integer] :id The vlan id to create on the node. The
157
+ # vlan id must be in the valid range of 1 to 4094
158
+ #
159
+ # @return [Boolean] returns true if the command completed successfully
160
+ def create(id)
161
+ configure("vlan #{id}")
162
+ end
163
+
164
+ ##
165
+ # delete will delete an existing vlan resource from the nodes current
166
+ # running configuration. If the delete method is called and the vlan
167
+ # id does not exist, this method will succeed.
168
+ #
169
+ # @eos_version 4.13.7M
170
+ #
171
+ # @commands
172
+ # no vlan <value>
173
+ #
174
+ # @param [String, Integer] :id The vlan id to delete from the node. The
175
+ # id value should be in the valid range of 1 to 4094
176
+ #
177
+ # @return [Boolean] returns true if the command completed successfully
178
+ def delete(id)
179
+ configure("no vlan #{id}")
180
+ end
181
+
182
+ ##
183
+ # default will configure the vlan using the default keyword. This
184
+ # command has the same effect as deleting the vlan from the nodes
185
+ # running configuration.
186
+ #
187
+ # @eos_version 4.13.7M
188
+ #
189
+ # @commands
190
+ # default vlan <value>
191
+ #
192
+ # @param [String, Integer] :id The vlan id to default in the nodes
193
+ # configuration. Ths vid value should be in the valid range of 1
194
+ # to 4094
195
+ #
196
+ # @return [Boolean] returns true if the command complete successfully
197
+ def default(id)
198
+ configure("default vlan #{id}")
199
+ end
200
+
201
+ ##
202
+ # set_name configures the name value for the specified vlan id in the
203
+ # nodes running configuration. If the value is not provided in the
204
+ # opts keyword Hash then the name value is negated using the no
205
+ # keyword. If the default keyword is set to true, then the name value
206
+ # is defaulted using the default keyword. The default keyword takes
207
+ # precedence over the value keyword
208
+ #
209
+ # @eos_version 4.13.7M
210
+ #
211
+ # @commands
212
+ # vlan <id>
213
+ # name <value>
214
+ # no name
215
+ # defaul name
216
+ #
217
+ # @param [String, Integer] :id The vlan id to apply the configuration
218
+ # to. The id value should be in the valid range of 1 to 4094
219
+ #
220
+ # @param [Hash] :opts Optional keyword arguments
221
+ #
222
+ # @option :opts [String] :value The value to configure the vlan name
223
+ # to in the node configuration. The name parameter accepts a-z, 0-9
224
+ # and _.
225
+ #
226
+ # @option :opts [Boolean] :default Configure the vlan name value using
227
+ # the default keyword
228
+ #
229
+ # @return [Boolean] returns true if the command completed successfully
230
+ def set_name(id, opts = {})
231
+ value = opts[:value]
232
+ default = opts[:default] || false
233
+
234
+ cmds = ["vlan #{id}"]
235
+ case default
236
+ when true
237
+ cmds << 'default name'
238
+ when false
239
+ cmds << (value.nil? ? 'no name' : "name #{value}")
240
+ end
241
+ configure(cmds)
242
+ end
243
+
244
+ ##
245
+ # set_state configures the state value for the specified vlan id in
246
+ # the nodes running configuration. If the value is not provided in
247
+ # the opts keyword Hash then the state value is negated using the no
248
+ # keyword. If the default keyword is set to true, then the state
249
+ # value is defaulted using the default keyword. The default keyword
250
+ # takes precedence over the value keyword
251
+ #
252
+ # @eos_version 4.13.7M
253
+ #
254
+ # @commands
255
+ # vlan <id>
256
+ # state [active, suspend]
257
+ # no state
258
+ # default state
259
+ #
260
+ # @param [String, Integer] :id The vlan id to apply the configuration
261
+ # to. The id value should be in the valid range of 1 to 4094
262
+ #
263
+ # @param [Hash] :opts Optional keyword arguments
264
+ #
265
+ # @option :opts [String] :value The value to configure the vlan state
266
+ # to in the node's configuration. Accepted values are 'active' or
267
+ # 'suspend'
268
+ #
269
+ # @option :opts [Boolean] :deafult Configure the vlan state value using
270
+ # the default keyword
271
+ #
272
+ # @return [Boolean] returns true if the command completed successfully
273
+ #
274
+ # @raise [ArgumentError] if the value is not in the accept list of
275
+ # values
276
+ def set_state(id, opts = {})
277
+ value = opts[:value]
278
+ default = opts[:default] || false
279
+
280
+ unless ['active', 'suspend', nil].include?(value)
281
+ raise ArgumentError, 'state must be active, suspend or nil'
282
+ end
283
+
284
+ cmds = ["vlan #{id}"]
285
+ case default
286
+ when true
287
+ cmds << 'default state'
288
+ when false
289
+ cmds << (value.nil? ? 'no state' : "state #{value}")
290
+ end
291
+ configure(cmds)
292
+ end
293
+
294
+ ##
295
+ # add_trunk_group adds a new trunk group value to the specified vlan
296
+ # id in the nodes running configuration. The trunk group name value
297
+ # accepts a-z 0-9 and _
298
+ #
299
+ # @version 4.13.7M
300
+ #
301
+ # @commands
302
+ # vlan <id>
303
+ # trunk group <value>
304
+ #
305
+ # @param [String, Integer] :id The vlan id to apply the configuration
306
+ # to. the id value should be in the range of 1 to 4094
307
+ #
308
+ # @param [String] :value The value to add to the vlan id configuration
309
+ # on the node.
310
+ #
311
+ # @return [Boolean] returns true if the command completed successfully
312
+ def add_trunk_group(id, value)
313
+ configure(["vlan #{id}", "trunk group #{value}"])
314
+ end
315
+
316
+ ##
317
+ # remove_trunk_group removes the specified trunk group value from the
318
+ # specified vlan id in the node's configuration. If the trunk group
319
+ # name does not exist, this method will return success
320
+ #
321
+ # @eos_version 4.13.7M
322
+ #
323
+ # @commands
324
+ # vlan <id>
325
+ # no trunk group <value>
326
+ #
327
+ # @param [String, Integer] :id The vlan id to apply the configuration
328
+ # to. the id value should be in the range of 1 to 4094
329
+ #
330
+ # @param [String] :value The value to remove from the list of trunk
331
+ # group names configured for the specified vlan
332
+ #
333
+ def remove_trunk_group(id, value)
334
+ configure(["vlan #{id}", "no trunk group #{value}"])
335
+ end
336
+ end
337
+ end
338
+ end