rbeapi 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/.gitignore +5 -0
  2. data/.rubocop.yml +21 -0
  3. data/CHANGELOG.md +24 -0
  4. data/Gemfile +3 -1
  5. data/Guardfile +3 -3
  6. data/README.md +92 -17
  7. data/Rakefile +99 -4
  8. data/gems/README.rst +4 -0
  9. data/gems/inifile/.gitignore +2 -0
  10. data/gems/inifile/README.rst +5 -0
  11. data/gems/inifile/inifile.spec.tmpl +84 -0
  12. data/gems/net_http_unix/.gitignore +2 -0
  13. data/gems/net_http_unix/README.rst +5 -0
  14. data/gems/net_http_unix/net_http_unix.spec.tmpl +54 -0
  15. data/gems/netaddr/README.rst +5 -0
  16. data/gems/netaddr/netaddr.spec.tmpl +50 -0
  17. data/lib/rbeapi/api/aaa.rb +14 -17
  18. data/lib/rbeapi/api/acl.rb +276 -0
  19. data/lib/rbeapi/api/dns.rb +7 -4
  20. data/lib/rbeapi/api/interfaces.rb +239 -239
  21. data/lib/rbeapi/api/ipinterfaces.rb +5 -3
  22. data/lib/rbeapi/api/logging.rb +8 -5
  23. data/lib/rbeapi/api/mlag.rb +45 -127
  24. data/lib/rbeapi/api/ntp.rb +1 -4
  25. data/lib/rbeapi/api/ospf.rb +16 -13
  26. data/lib/rbeapi/api/prefixlists.rb +4 -4
  27. data/lib/rbeapi/api/radius.rb +34 -25
  28. data/lib/rbeapi/api/routemaps.rb +16 -10
  29. data/lib/rbeapi/api/snmp.rb +26 -13
  30. data/lib/rbeapi/api/staticroutes.rb +6 -5
  31. data/lib/rbeapi/api/stp.rb +77 -18
  32. data/lib/rbeapi/api/switchports.rb +20 -12
  33. data/lib/rbeapi/api/system.rb +6 -6
  34. data/lib/rbeapi/api/tacacs.rb +9 -6
  35. data/lib/rbeapi/api/varp.rb +15 -10
  36. data/lib/rbeapi/api/vlans.rb +5 -6
  37. data/lib/rbeapi/api.rb +56 -16
  38. data/lib/rbeapi/client.rb +85 -50
  39. data/lib/rbeapi/eapilib.rb +95 -56
  40. data/lib/rbeapi/netdev/snmp.rb +7 -16
  41. data/lib/rbeapi/utils.rb +3 -5
  42. data/lib/rbeapi/version.rb +1 -1
  43. data/rbeapi.gemspec +4 -2
  44. data/rbeapi.spec.tmpl +72 -0
  45. data/spec/support/fixtures.rb +6 -4
  46. data/spec/support/shared_examples_for_api_modules.rb +3 -18
  47. data/spec/system/api_acl_spec.rb +128 -0
  48. data/spec/system/api_ospf_interfaces_spec.rb +17 -14
  49. data/spec/system/api_ospf_spec.rb +8 -8
  50. data/spec/system/api_varp_interfaces_spec.rb +22 -13
  51. data/spec/system/api_varp_spec.rb +1 -4
  52. data/spec/system/rbeapi/api/interfaces_base_spec.rb +3 -4
  53. data/spec/system/rbeapi/api/interfaces_ethernet_spec.rb +13 -9
  54. data/spec/system/rbeapi/api/interfaces_portchannel_spec.rb +43 -26
  55. data/spec/system/rbeapi/api/interfaces_vxlan_spec.rb +7 -6
  56. data/spec/system/rbeapi/api/ipinterfaces_spec.rb +34 -21
  57. data/spec/system/rbeapi/api/mlag_interfaces_spec.rb +15 -38
  58. data/spec/system/rbeapi/api/mlag_spec.rb +26 -30
  59. data/spec/system/rbeapi/api/snmp_spec.rb +0 -3
  60. data/spec/system/rbeapi/api/stp_instances_spec.rb +20 -12
  61. data/spec/system/rbeapi/api/stp_interfaces_spec.rb +1 -3
  62. data/spec/system/rbeapi/api/switchports_spec.rb +14 -12
  63. data/spec/system/rbeapi/api/system_spec.rb +0 -3
  64. data/spec/system/rbeapi/api/vlans_spec.rb +19 -9
  65. data/spec/unit/rbeapi/api/acl/default_spec.rb +158 -0
  66. data/spec/unit/rbeapi/api/acl/fixture_acl_standard.text +22 -0
  67. data/spec/unit/rbeapi/api/interfaces/base_spec.rb +123 -0
  68. data/spec/unit/rbeapi/api/interfaces/ethernet_spec.rb +89 -0
  69. data/spec/unit/rbeapi/api/interfaces/fixture_interfaces.text +219 -0
  70. data/spec/unit/rbeapi/api/interfaces/portchannel_spec.rb +149 -0
  71. data/spec/unit/rbeapi/api/interfaces/vxlan_spec.rb +243 -0
  72. data/spec/unit/rbeapi/api/mlag/default_spec.rb +218 -0
  73. data/spec/unit/rbeapi/api/mlag/fixture_mlag.text +238 -0
  74. data/spec/unit/rbeapi/api/vlans/default_spec.rb +135 -0
  75. data/spec/unit/rbeapi/api/vlans/fixture_vlans.text +5 -0
  76. metadata +79 -4
  77. data/lib/rbeapi/api/radius.rb.old +0 -399
@@ -31,14 +31,16 @@
31
31
  #
32
32
  require 'rbeapi/api'
33
33
 
34
-
34
+ ##
35
+ # Rbeapi toplevel namespace
35
36
  module Rbeapi
36
37
  ##
37
- # Eos is module namesapce for working with the EOS command API
38
+ # Rbeapi::Api
38
39
  module Api
39
-
40
+ ##
41
+ # The Aaa class manages Authorization, Authentication and Accounting (AAA)
42
+ # on an EOS node.
40
43
  class Aaa < Entity
41
-
42
44
  def get
43
45
  response = {}
44
46
  response[:groups] = groups.getall
@@ -52,14 +54,12 @@ module Rbeapi
52
54
  end
53
55
  end
54
56
 
55
-
57
+ ##
58
+ # The AaaGroups class manages the server groups on a EOS node.
56
59
  class AaaGroups < Entity
57
-
58
-
59
60
  DEFAULT_RADIUS_AUTH_PORT = 1812
60
61
  DEFAULT_RADIUS_ACCT_PORT = 1813
61
62
 
62
-
63
63
  # Regular express that parses the radius servers from the aaa group
64
64
  # server radius configuration block
65
65
  RADIUS_GROUP_SERVER = /\s{3}server
@@ -74,7 +74,6 @@ module Rbeapi
74
74
  (?:[ ]vrf[ ](\w+))?
75
75
  (?:[ ]port[ ](\d+))?/x
76
76
 
77
-
78
77
  ##
79
78
  # get returns the aaa server group resource hash that describes the
80
79
  # current configuration for the specified server group name
@@ -200,7 +199,6 @@ module Rbeapi
200
199
  end
201
200
  private :parse_radius_server
202
201
 
203
-
204
202
  ##
205
203
  # find_type is a utility method to find the type of aaa server group for
206
204
  # the specified name. This method will scan the current running
@@ -241,7 +239,7 @@ module Rbeapi
241
239
  #
242
240
  # @return [Boolean] returns true if the commands complete successfully
243
241
  def create(name, type)
244
- configure ["aaa group server #{type} #{name}", "exit"]
242
+ configure ["aaa group server #{type} #{name}", 'exit']
245
243
  end
246
244
 
247
245
  ##
@@ -292,7 +290,7 @@ module Rbeapi
292
290
  hostname = srv[:name]
293
291
  return false unless add_server(name, hostname, srv)
294
292
  end
295
- return true
293
+ true
296
294
  end
297
295
 
298
296
  ##
@@ -349,10 +347,9 @@ module Rbeapi
349
347
  server << "auth-port #{opts[:auth_port]} " if opts[:auth_port]
350
348
  server << "acct-port #{opts[:acct_port]} " if opts[:acct_port]
351
349
  server << "vrf #{opts[:vrf]}" if opts[:vrf]
352
- configure ["aaa group server radius #{name}", server, "exit"]
350
+ configure ["aaa group server radius #{name}", server, 'exit']
353
351
  end
354
352
 
355
-
356
353
  ##
357
354
  # add_tacacs_server adds a new tacacs server to the nodes current
358
355
  # configuration. If the server already exists in the specified group
@@ -379,7 +376,7 @@ module Rbeapi
379
376
  server = "server #{server} "
380
377
  server << "vrf #{opts[:vrf]} " if opts[:vrf]
381
378
  server << "port #{opts[:port]} " if opts[:port]
382
- configure ["aaa group server tacacs+ #{name}", server, "exit"]
379
+ configure ["aaa group server tacacs+ #{name}", server, 'exit']
383
380
  end
384
381
 
385
382
  ##
@@ -398,12 +395,12 @@ module Rbeapi
398
395
  # @param [String] :server The IP address or host name of the server
399
396
  #
400
397
  # @return [Boolean] returns true if the commands complete successfully
401
- def remove_server(name, server, opts={})
398
+ def remove_server(name, server, opts = {})
402
399
  type = find_type(name)
403
400
  return false unless type
404
401
  server = "no server #{server} "
405
402
  server << "vrf #{opts[:vrf]}" if opts[:vrf]
406
- configure ["aaa group server #{type} #{name}", server, "exit"]
403
+ configure ["aaa group server #{type} #{name}", server, 'exit']
407
404
  end
408
405
  end
409
406
  end
@@ -0,0 +1,276 @@
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 'netaddr'
33
+ require 'rbeapi/api'
34
+
35
+ ##
36
+ # Eos is the toplevel namespace for working with Arista EOS nodes
37
+ module Rbeapi
38
+ ##
39
+ # Api is module namespace for working with the EOS command API
40
+ module Api
41
+ ##
42
+ # The Acl class manages the set of standard ACLs.
43
+ class Acl < Entity
44
+ def initialize(node)
45
+ super(node)
46
+ @entry_re = Regexp.new(%r{(\d+)
47
+ (?:\ ([p|d]\w+))
48
+ (?:\ (any))?
49
+ (?:\ (host))?
50
+ (?:\ ([0-9]+(?:\.[0-9]+){3}))?
51
+ (?:/([0-9]{1,2}))?
52
+ (?:\ ([0-9]+(?:\.[0-9]+){3}))?
53
+ (?:\ (log))?}x)
54
+ end
55
+
56
+ ##
57
+ # get returns the specified ACL from the nodes current configuration.
58
+ #
59
+ # @param [String] :name The ACL name.
60
+ #
61
+ # @return [nil, Hash<Symbol, Object>] Returns the ACL resource as a
62
+ # Hash.
63
+ def get(name)
64
+ config = get_block("ip access-list standard #{name}")
65
+ return nil unless config
66
+
67
+ parse_entries(config)
68
+ end
69
+
70
+ ##
71
+ # getall returns the collection of ACLs from the nodes running
72
+ # configuration as a hash. The ACL resource collection hash is
73
+ # keyed by the ACL name.
74
+ #
75
+ # @return [nil, Hash<Symbol, Object>] Returns a hash that represents
76
+ # the entire ACL collection from the nodes running configuration.
77
+ # If there are no ACLs configured, this method will return an
78
+ # empty hash.
79
+ def getall
80
+ acls = config.scan(/ip access-list standard ([^\s]+)/)
81
+ acls.each_with_object({}) do |name, hsh|
82
+ resource = get(name[0])
83
+ hsh[name[0]] = resource if resource
84
+ end
85
+ end
86
+
87
+ ##
88
+ # mask_to_prefixlen converts a subnet mask from dotted decimal to
89
+ # bit length
90
+ #
91
+ # @param [String] :mask The dotted decimal subnet mask to convert
92
+ #
93
+ # @return [String] The subnet mask as a valid prefix length
94
+ def mask_to_prefixlen(mask)
95
+ mask = '255.255.255.255' unless mask
96
+ NetAddr::CIDR.create('0.0.0.0/' + mask).netmask_ext
97
+ end
98
+
99
+ ##
100
+ # parse_entries scans the nodes configurations and parses
101
+ # the entries within an ACL.
102
+ #
103
+ # @api private
104
+ #
105
+ # @param [String] :config The switch config.
106
+ #
107
+ # @return [Hash<Symbol, Object>] resource hash attribute
108
+
109
+ def parse_entries(config)
110
+ entries = {}
111
+
112
+ lines = config.scan(/\d+ [p|d].*$/)
113
+ lines.each do |line|
114
+ entry = line.scan(@entry_re).map \
115
+ do |(seqno, act, _anyip, _host, ip, mlen, mask, log)|
116
+ {
117
+ seqno: seqno,
118
+ action: act,
119
+ srcaddr: ip || '0.0.0.0',
120
+ srcprefixlen: mlen || mask_to_prefixlen(mask),
121
+ log: log
122
+ }
123
+ end
124
+ entries[entry[0][:seqno]] = entry[0]
125
+ end
126
+ entries
127
+ end
128
+ private :parse_entries
129
+
130
+ ##
131
+ # create will create a new ACL resource in the nodes current
132
+ # configuration with the specified name. If the create method
133
+ # is called and the ACL already exists, this method will still
134
+ # return true. The ACL will not have any entries. Use add_entry
135
+ # to add entries to the ACL.
136
+ #
137
+ # @eos_version 4.13.7M
138
+ #
139
+ # @commands
140
+ # ip access-list standard <name>
141
+ #
142
+ # @param [String] :name The ACL name to create on the node. Must
143
+ # begin with an alphabetic character. Cannot contain spaces or
144
+ # quotation marks.
145
+ #
146
+ # @return [Boolean] returns true if the command completed successfully
147
+ def create(name)
148
+ configure("ip access-list standard #{name}")
149
+ end
150
+
151
+ ##
152
+ # delete will delete an existing ACL resource from the nodes current
153
+ # running configuration. If the delete method is called and the ACL
154
+ # does not exist, this method will succeed.
155
+ #
156
+ # @eos_version 4.13.7M
157
+ #
158
+ # @commands
159
+ # no ip access-list standard <name>
160
+ #
161
+ # @param [String] :name The ACL name to delete on the node.
162
+ #
163
+ # @return [Boolean] returns true if the command completed successfully
164
+ def delete(name)
165
+ configure("no ip access-list standard #{name}")
166
+ end
167
+
168
+ ##
169
+ # default will configure the ACL using the default keyword. This
170
+ # command has the same effect as deleting the ACL from the nodes
171
+ # running configuration.
172
+ #
173
+ # @eos_version 4.13.7M
174
+ #
175
+ # @commands
176
+ # default no ip access-list standard <name>
177
+ #
178
+ # @param [String] :name The ACL name to set to the default value
179
+ # on the node.
180
+ #
181
+ # @return [Boolean] returns true if the command complete successfully
182
+ def default(name)
183
+ configure("default ip access-list standard #{name}")
184
+ end
185
+
186
+ ##
187
+ # build_entry will build the commands to add an entry.
188
+ #
189
+ # @api private
190
+ #
191
+ # @param [Hash] :opts the options for the entry
192
+ # @option :opts [String] :seqno The sequence number of the entry in
193
+ # the ACL to add. Default is nil, will be assigned.
194
+ # @option :opts [String] :action The action triggered by the ACL. Valid
195
+ # values are 'permit', 'deny', or 'remark'
196
+ # @option :opts [String] :addr The IP address to permit or deny.
197
+ # @option :opts [String] :prefixlen The prefixlen for the IP address.
198
+ # @option :opts [Boolean] :log Triggers an informational log message
199
+ # to the console about the matching packet.
200
+ #
201
+ # @return [String] returns commands to create an entry
202
+ def build_entry(entry)
203
+ cmds = "#{entry[:seqno]} " if entry[:seqno]
204
+ cmds << "#{entry[:action]} #{entry[:srcaddr]}/#{entry[:srcprefixlen]}"
205
+ cmds << ' log' if entry[:log]
206
+ cmds
207
+ end
208
+ private :build_entry
209
+
210
+ ##
211
+ # update_entry will update an entry, identified by the seqno
212
+ # in the ACL specified by name, with the passed in parameters.
213
+ #
214
+ # @eos_version 4.13.7M
215
+ #
216
+ # @param [String] :name The ACL name to update on the node.
217
+ # @param [Hash] :opts the options for the entry
218
+ # @option :opts [String] :seqno The sequence number of the entry in
219
+ # the ACL to update.
220
+ # @option :opts [String] :action The action triggered by the ACL. Valid
221
+ # values are 'permit', 'deny', or 'remark'
222
+ # @option :opts [String] :addr The IP address to permit or deny.
223
+ # @option :opts [String] :prefixlen The prefixlen for the IP address.
224
+ # @option :opts [Boolean] :log Triggers an informational log message
225
+ # to the console about the matching packet.
226
+ #
227
+ # @return [Boolean] returns true if the command complete successfully
228
+ def update_entry(name, entry)
229
+ cmds = ["ip access-list standard #{name}"]
230
+ cmds << "no #{entry[:seqno]}"
231
+ cmds << build_entry(entry)
232
+ cmds << 'exit'
233
+ configure(cmds)
234
+ end
235
+
236
+ ##
237
+ # add_entry will add an entry to the specified ACL with the
238
+ # passed in parameters.
239
+ #
240
+ # @eos_version 4.13.7M
241
+ #
242
+ # @param [String] :name The ACL name to add an entry to on the node.
243
+ # @param [Hash] :opts the options for the entry
244
+ # @option :opts [String] :action The action triggered by the ACL. Valid
245
+ # values are 'permit', 'deny', or 'remark'
246
+ # @option :opts [String] :addr The IP address to permit or deny.
247
+ # @option :opts [String] :prefixlen The prefixlen for the IP address.
248
+ # @option :opts [Boolean] :log Triggers an informational log message
249
+ # to the console about the matching packet.
250
+ #
251
+ # @return [Boolean] returns true if the command complete successfully
252
+ def add_entry(name, entry)
253
+ cmds = ["ip access-list standard #{name}"]
254
+ cmds << build_entry(entry)
255
+ cmds << 'exit'
256
+ configure(cmds)
257
+ end
258
+
259
+ ##
260
+ # remove_entry will remove the entry specified by the seqno for
261
+ # the ACL specified by name.
262
+ #
263
+ # @eos_version 4.13.7M
264
+ #
265
+ # @param [String] :name The ACL name to update on the node.
266
+ # @param [String] :seqno The sequence number of the entry in
267
+ # the ACL to remove.
268
+ #
269
+ # @return [Boolean] returns true if the command complete successfully
270
+ def remove_entry(name, seqno)
271
+ cmds = ["ip access-list standard #{name}", "no #{seqno}", 'exit']
272
+ configure(cmds)
273
+ end
274
+ end
275
+ end
276
+ end
@@ -31,12 +31,15 @@
31
31
  #
32
32
  require 'rbeapi/api'
33
33
 
34
+ ##
35
+ # Rbeapi toplevel namespace
34
36
  module Rbeapi
35
-
37
+ ##
38
+ # Rbeapi::Api
36
39
  module Api
37
-
40
+ ##
41
+ # The Dns class manages DNS settings on an EOS node.
38
42
  class Dns < Entity
39
-
40
43
  ##
41
44
  # Returns the DNS resource
42
45
  #
@@ -173,7 +176,7 @@ module Rbeapi
173
176
 
174
177
  case default
175
178
  when true
176
- cmds = 'default ip domain-list'
179
+ cmds = 'default ip domain-list'
177
180
  when false
178
181
  cmds = []
179
182
  parse_domain_list[:domain_list].each do |name|