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
data/lib/rbeapi/client.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2014, Arista Networks, Inc.
2
+ # Copyright (c) 2014, 2015 Arista Networks, Inc.
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
@@ -41,10 +41,8 @@ module Rbeapi
41
41
  ##
42
42
  # Rbeapi::Client
43
43
  module Client
44
-
45
44
  class << self
46
-
47
- DEFAULT_TRANSPORT = 'http'
45
+ DEFAULT_TRANSPORT = 'https'
48
46
 
49
47
  TRANSPORTS = { 'http' => 'Rbeapi::Eapilib::HttpEapiConnection',
50
48
  'https' => 'Rbeapi::Eapilib::HttpsEapiConnection',
@@ -60,15 +58,15 @@ module Rbeapi
60
58
  # with the eapi.conf file
61
59
  def config
62
60
  return @config if @config
63
- @config = Config.new()
64
- return @config
61
+ @config = Config.new
62
+ @config
65
63
  end
66
64
 
67
65
  ##
68
66
  # load_config overrides the default conf file loaded in the config
69
67
  # instances using the supplied conf argument as the conf file. This
70
68
  # method will clear out an previously loaded configuration and replace
71
- # all entries with the contects of the supplied file.
69
+ # all entries with the contents of the supplied file.
72
70
  #
73
71
  # @param [String] :conf The full path to the conf file to load into
74
72
  # the config instance.
@@ -77,8 +75,8 @@ module Rbeapi
77
75
  end
78
76
 
79
77
  ##
80
- # Returns the configuration options for the named connection from the
81
- # the loaded configuuration. The configuration name is specified as
78
+ # Returns the configuration options for the named connection from
79
+ # the loaded configuration. The configuration name is specified as
82
80
  # the string right of the colon in the section name.
83
81
  #
84
82
  # @param [String] :name The connection name to return from the loaded
@@ -88,7 +86,7 @@ module Rbeapi
88
86
  # the named configuration if found. If the name is not found, then
89
87
  # nil is returned
90
88
  def config_for(name)
91
- return config.get_connection(name)
89
+ config.get_connection(name)
92
90
  end
93
91
 
94
92
  ##
@@ -103,6 +101,7 @@ module Rbeapi
103
101
  def connect_to(name)
104
102
  config = config_for(name)
105
103
  return nil unless config
104
+ config['host'] = name if config['host'] == '*'
106
105
  config = Rbeapi::Utils.transform_keys_to_symbols(config)
107
106
  connection = connect config
108
107
  Node.new(connection)
@@ -118,13 +117,13 @@ module Rbeapi
118
117
  #
119
118
  # @param [Hash] :opts the options to create a message with
120
119
  # @option :opts [String] :host The IP address or hostname of the remote
121
- # eAPI endpint
120
+ # eAPI endpoint
122
121
  # @option :opts [String] :username The username to use to authenticate
123
122
  # the eAPI connection with
124
123
  # @option :opts [String] :password The password to use to authenticate
125
124
  # the eAPI connection with
126
125
  # @option :opts [String] :enable_pwd The enable password (if defined) to
127
- # pass to the remote node to enter priviledged mode
126
+ # pass to the remote node to enter privilege mode
128
127
  # @option :opts [String] :use_ssl Specifies whether or not to use the
129
128
  # HTTP or HTTPS protocol
130
129
  # @option :opts [String] :port The port to connect to. If not specified
@@ -153,15 +152,15 @@ module Rbeapi
153
152
  end
154
153
  end
155
154
 
155
+ ##
156
+ # The Config class holds the loaded configuration file data. It is a
157
+ # subclass of IniFile.
156
158
  class Config < IniFile
157
-
158
159
  CONFIG_SEARCH_PATH = ['~/.eapi.conf', '/mnt/flash/eapi.conf']
159
160
 
160
161
  ##
161
- # The Config class holds the loaded configuration file data. It is a
162
- # subclass of IniFile. The Config class will automatically search for
163
- # a filename to load (if none provided) and load the data when the
164
- # object is instantiated.
162
+ # The Config class will automatically search for a filename to load
163
+ # (if none provided) and load the data when the object is instantiated.
165
164
  #
166
165
  # @param [String] :filename The full path to the filename to load. If
167
166
  # the filename is not provided, then this class will attempt to find
@@ -173,7 +172,7 @@ module Rbeapi
173
172
  end
174
173
 
175
174
  ##
176
- # This private method automtically finds and loads the conf file
175
+ # This private method automatically finds and loads the conf file
177
176
  # into the instance using the class variable CONFIG_SEARCH_PATH. The
178
177
  # connections should be retrieved using the get_connection method
179
178
  #
@@ -189,8 +188,11 @@ module Rbeapi
189
188
 
190
189
  path.each do |fn|
191
190
  fn = File.expand_path(fn)
192
- return read(fn) if File.exists?(fn)
191
+ return read(fn) if File.exist?(fn)
193
192
  end
193
+
194
+ return if get_connection 'localhost'
195
+ add_connection('localhost', transport: 'socket')
194
196
  end
195
197
  private :autoload
196
198
 
@@ -202,15 +204,24 @@ module Rbeapi
202
204
  # @param [String] :filename The full path to the filename to load
203
205
  def read(filename)
204
206
  super(filename: filename)
205
- unless get_connection 'localhost'
206
- add_connection('localhost', transport: 'socket')
207
+
208
+ # For each section, if the host parameter is omitted then the
209
+ # connection name is used
210
+ sections.each do |name|
211
+ if name.start_with?('connection:')
212
+ conn = self["#{name}"]
213
+ conn['host'] = name.split(':')[1] unless conn['host']
214
+ end
207
215
  end
216
+
217
+ return if get_connection 'localhost'
218
+ add_connection('localhost', transport: 'socket')
208
219
  end
209
220
 
210
221
  ##
211
222
  # This method will cause the config to be loaded. The process of
212
223
  # finding the configuration will be repeated so it is possible a
213
- # different conf file could be choosen if the original file was
224
+ # different conf file could be chosen if the original file was
214
225
  # removed or a new file added higher on the search priority list
215
226
  #
216
227
  # @param [Hash] :opts The options for specifying the message
@@ -220,18 +231,22 @@ module Rbeapi
220
231
  end
221
232
 
222
233
  ##
223
- # Returns the configuration for the connection specified
234
+ # Returns the configuration for the connection specified. If a
235
+ # connection is not found matching the name and if a default
236
+ # connection has been specified then return the default connection.
224
237
  #
225
238
  # @param [String] :name The name of the connection to return from
226
239
  # the configuration. This should be the string right of the :
227
240
  # in the config section header
228
241
  #
229
242
  # @return [nil, Hash<String, String> Returns a hash of the connection
230
- # properities from the loaded config. This method will return nil
243
+ # properties from the loaded config. This method will return nil
231
244
  # if the connection name is not found.
232
245
  def get_connection(name)
233
- return nil unless sections.include? "connection:#{name}"
234
- self["connection:#{name}"]
246
+ return self["connection:#{name}"] \
247
+ if sections.include? "connection:#{name}"
248
+ return self['connection:*'] if sections.include? 'connection:*'
249
+ nil
235
250
  end
236
251
 
237
252
  ##
@@ -245,14 +260,15 @@ module Rbeapi
245
260
  end
246
261
  end
247
262
 
263
+ ##
264
+ # The Node object provides an instance for sending and receiving messages
265
+ # with a specific EOS device. The methods provided in this class allow
266
+ # for handling both enable mode and config mode commands
248
267
  class Node
249
-
250
268
  attr_reader :connection
251
269
 
252
270
  ##
253
- # The Node object provies an instnace for sending and receiveing messages
254
- # with a specific EOS device. The methods provided in this calss allow
255
- # for handling both enable mode and config mode commands
271
+ # Save the connection and set autorefresh to true.
256
272
  #
257
273
  # @param [Rbeapi::Eapilib::EapiConnection] :connection An instance of
258
274
  # EapiConnection used to send and receive eAPI formatted messages
@@ -269,18 +285,16 @@ module Rbeapi
269
285
  def running_config
270
286
  return @running_config if @running_config
271
287
  @running_config = get_config(params: 'all', as_string: true)
272
- return @running_config
273
288
  end
274
289
 
275
290
  ##
276
291
  # Provides access to the nodes startup-configuration. This is a lazily
277
- # loaded memoized prpoerty for working with the nodes startup config
292
+ # loaded memoized property for working with the nodes startup config
278
293
  #
279
294
  # @return [String] The node's startup-config as a string
280
295
  def startup_config
281
296
  return @startup_config if @startup_config
282
297
  @startup_config = get_config(config: 'startup-config', as_string: true)
283
- return @startup_config
284
298
  end
285
299
 
286
300
  ##
@@ -302,13 +316,20 @@ module Rbeapi
302
316
  # to the caller
303
317
  #
304
318
  # @param [Array<String>] commands An ordered list of commands to execute
319
+ # @option :opts [String] :encoding The encoding scheme to use for sending
320
+ # and receive eAPI messages. Valid values are json and text. The
321
+ # default value is json
322
+ # @option :opts [Float] :open_timeout Number of seconds to wait for the
323
+ # eAPI connection to open.
324
+ # @option :opts [Float] :read_timeout Number of seconds to wait for one
325
+ # block of eAPI results to be read (via one read(2) call).
305
326
  #
306
327
  # @return [Array<Hash>] ordered list of output from commands
307
- def config(commands)
328
+ def config(commands, opts = {})
308
329
  commands = [*commands] unless commands.respond_to?('each')
309
330
 
310
331
  commands.insert(0, 'configure')
311
- response = run_commands commands
332
+ response = run_commands(commands, opts)
312
333
 
313
334
  refresh if @autorefresh
314
335
 
@@ -318,34 +339,42 @@ module Rbeapi
318
339
 
319
340
  ##
320
341
  # The enable method is a convenience method that will handling putting
321
- # the switch into priviledge mode prior to executing commands.
342
+ # the switch into privilege mode prior to executing commands.
343
+ #
344
+ # rubocop:disable Metrics/MethodLength
322
345
  #
323
346
  # @param [Array<String>] commands An ordered list of commands to execute
324
- # @param [String] :encoding The encoding scheme to use for sending and
325
- # receive eAPI messages. Valid values are json and text. The default
326
- # value is json
347
+ # @option :opts [String] :encoding The encoding scheme to use for sending
348
+ # and receive eAPI messages. Valid values are json and text. The
349
+ # default value is json
350
+ # @option :opts [Float] :open_timeout Number of seconds to wait for the
351
+ # eAPI connection to open.
352
+ # @option :opts [Float] :read_timeout Number of seconds to wait for one
353
+ # block of eAPI results to be read (via one read(2) call).
327
354
  #
328
355
  # @return [Array<Hash>] ordered list of output from commands
329
356
  def enable(commands, opts = {})
330
357
  commands = [*commands] unless commands.respond_to?('each')
331
358
 
332
359
  encoding = opts.fetch(:encoding, 'json')
360
+ opts[:encoding] = encoding
333
361
  strict = opts.fetch(:strict, false)
334
362
 
335
363
  results = []
336
364
  if strict
337
- responses = run_commands(commands, encoding)
365
+ responses = run_commands(commands, opts)
338
366
  responses.each_with_index do |resp, idx|
339
367
  results << make_response(commands[idx], resp, encoding)
340
368
  end
341
369
  else
342
370
  commands.each do |cmd|
343
371
  begin
344
- response = run_commands(cmd, encoding)
372
+ response = run_commands(cmd, opts)
345
373
  results << make_response(cmd, response.first, encoding)
346
374
  rescue Rbeapi::Eapilib::CommandError => exc
347
375
  raise unless exc.error_code == 1003
348
- response = run_commands(cmd, 'text')
376
+ opts[:encoding] = 'text'
377
+ response = run_commands(cmd, opts)
349
378
  results << make_response(cmd, response.first, encoding)
350
379
  end
351
380
  end
@@ -376,20 +405,26 @@ module Rbeapi
376
405
  #
377
406
  # @param [Array] :commands The ordered list of commands to send to the
378
407
  # destination node.
379
- # @param [String] :encoding The encoding scheme to use for sending and
380
- # receive eAPI requests. This argument is optional. Valid values
381
- # include json or text. The default is json
382
- def run_commands(commands, encoding = 'json')
408
+ # @option :opts [String] :encoding The encoding scheme to use for
409
+ # sending and receive eAPI requests. This argument is optional.
410
+ # Valid values include json or text. The default is json
411
+ # @option :opts [Float] :open_timeout Number of seconds to wait for the
412
+ # eAPI connection to open.
413
+ # @option :opts [Float] :read_timeout Number of seconds to wait for one
414
+ # block of eAPI results to be read (via one read(2) call).
415
+ def run_commands(commands, opts = {})
416
+ encoding = opts.fetch(:encoding, 'json')
383
417
  commands = [*commands] unless commands.respond_to?('each')
384
418
  commands = commands.dup
385
419
 
386
420
  if @enablepwd
387
- commands.insert(0, { 'cmd' => 'enable', 'input' => @enablepwd })
421
+ commands.insert(0, 'cmd' => 'enable', 'input' => @enablepwd)
388
422
  else
389
423
  commands.insert(0, 'enable')
390
424
  end
391
425
 
392
- response = @connection.execute(commands, format: encoding)
426
+ opts[:format] = encoding
427
+ response = @connection.execute(commands, opts)
393
428
  response.shift
394
429
  response
395
430
  end
@@ -424,13 +459,13 @@ module Rbeapi
424
459
  config = opts.fetch(:config, 'running-config')
425
460
  params = opts.fetch(:params, '')
426
461
  as_string = opts.fetch(:as_string, false)
427
- result = run_commands("show #{config} #{params}", 'text')
462
+ result = run_commands("show #{config} #{params}", encoding: 'text')
428
463
  return result.first['output'].strip.split("\n") unless as_string
429
464
  result.first['output'].strip
430
465
  end
431
466
 
432
467
  ##
433
- # Returns an API module for working with the active conifguraiton
468
+ # Returns an API module for working with the active configuration
434
469
  # of the node
435
470
  def api(name, opts = {})
436
471
  path = opts.fetch(:path, 'rbeapi/api')
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2014, Arista Networks, Inc.
2
+ # Copyright (c) 2014, 2015, Arista Networks, Inc.
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
@@ -31,28 +31,32 @@
31
31
  #
32
32
  require 'net/http'
33
33
  require 'json'
34
+ require 'openssl'
34
35
 
35
36
  require 'net_http_unix'
36
37
 
38
+ ##
39
+ # Rbeapi toplevel namespace
37
40
  module Rbeapi
38
-
41
+ ##
42
+ # Rbeapi::Eapilib
39
43
  module Eapilib
40
-
41
44
  DEFAULT_HTTP_PORT = 80
42
45
  DEFAULT_HTTPS_PORT = 443
43
46
  DEFAULT_HTTP_LOCAL_PORT = 8080
44
- DEFAULT_HTTP_TIMEOUT = 10
47
+ DEFAULT_HTTP_OPEN_TIMEOUT = 10
48
+ DEFAULT_HTTP_READ_TIMEOUT = 10
45
49
  DEFAULT_HTTP_PATH = '/command-api'
46
50
  DEFAULT_UNIX_SOCKET = '/var/run/command-api.sock'
47
51
 
52
+ ##
53
+ # Base error class for generating exceptions. The EapiError class
48
54
  class EapiError < StandardError
49
-
50
55
  attr_accessor :commands
51
56
 
52
57
  ##
53
- # Base error class for generating exceptions. The EapiError class
54
- # provides one property for holding the set of commands issued
55
- # when the error was generated
58
+ # The EapiError class provides one property for holding the set of
59
+ # commands issued when the error was generated.
56
60
  #
57
61
  # @param [String] :message The error message to return from raising
58
62
  # the exception
@@ -63,20 +67,20 @@ module Rbeapi
63
67
  end
64
68
  end
65
69
 
70
+ ##
71
+ # A CommandError exception is raised in response to an eAPI call that
72
+ # returns a failure message.
66
73
  class CommandError < EapiError
67
-
68
74
  attr_reader :error_code
69
75
  attr_reader :error_text
70
76
 
71
77
  ##
72
- # A CommandError exception is raised in response to an eAPI call that
73
- # returns a failure message. The exception contains the eAPI error
74
- # code and error text.
78
+ # The exception contains the eAPI error code and error text.
75
79
  #
76
80
  # @param [String] :message The error message to return from raising
77
81
  # this exception
78
82
  # @param [Integer] :code The error code associated with the error
79
- # messsage to be raised
83
+ # message to be raised
80
84
  # @param [Array] :commands The list of commands that were used in the
81
85
  # eAPI request message
82
86
  def initialize(message, code, commands = nil)
@@ -88,13 +92,14 @@ module Rbeapi
88
92
  end
89
93
  end
90
94
 
95
+ ##
96
+ # A ConnectionError exception is raised when the connection object
97
+ # is unable to establish a connection with eAPI.
91
98
  class ConnectionError < EapiError
92
-
93
99
  attr_accessor :connection_type
94
100
 
95
101
  ##
96
- # A ConnectionError exception is raised when the connection object
97
- # is unable to establish a connection with eAPI.
102
+ # The exception contains the eAPI error code and error text.
98
103
  #
99
104
  # @param [String] :message The error message to return from raising
100
105
  # this exception
@@ -109,16 +114,16 @@ module Rbeapi
109
114
  end
110
115
  end
111
116
 
117
+ ##
118
+ # The EapiConnection provides a base class for building eAPI connection
119
+ # instances with a specific transport for connecting to Arista EOS
120
+ # devices. This class handles sending and receiving eAPI calls using
121
+ # JSON-RPC. This class should not need to be directly instantiated.
112
122
  class EapiConnection
113
-
114
123
  attr_reader :error
115
124
 
116
125
  ##
117
- # The EapiConnection provides a base class for building eAPI connection
118
- # instances with a specific transport for connecting to Arista EOS
119
- # devices. This class handles sending and receiving eAPI calls using
120
- # JSON-RPC over HTTP. This class should not need to be directly
121
- # instantiated.
126
+ # The connection contains the transport.
122
127
  #
123
128
  # @param [Net::HTTP] :transport The HTTP transport to use for sending
124
129
  # and receive eAPI request and response messages
@@ -129,17 +134,32 @@ module Rbeapi
129
134
 
130
135
  ##
131
136
  # Configures the connection authentication values (username and
132
- # and password). The authentication values are used to authenticate
137
+ # password). The authentication values are used to authenticate
133
138
  # the eAPI connection. Using authentication is only required for
134
139
  # connections that use Http or Https transports
135
140
  #
136
- # @param [String] :username The username to use to authenticate to
137
- # eAPI with
138
- # @param [String] :password The password to use to authenticate to
139
- # eAPI with
140
- def authentication(username, password)
141
- @username = username
142
- @password = password
141
+ # @options :opts [String] :username The username to use to
142
+ # authenticate with eAPI. Default is 'admin'.
143
+ # @options :opts [String] :password The password to use to
144
+ # authenticate with eAPI. Default is ''.
145
+ def authentication(opts = {})
146
+ @username = opts.fetch(:username, 'admin')
147
+ @password = opts.fetch(:password, '')
148
+ end
149
+
150
+ ##
151
+ # Configures the connection timeout values (open_timeout and
152
+ # read_timeout). The timeout values are used for the eAPI
153
+ # connection.
154
+ #
155
+ # @option :opts [Float] :open_timeout Number of seconds to wait for the
156
+ # eAPI connection to open. Default is DEFAULT_HTTP_OPEN_TIMEOUT.
157
+ # @option :opts [Float] :read_timeout Number of seconds to wait for one
158
+ # block of eAPI results to be read (via one read(2) call). Default
159
+ # is DEFAULT_HTTP_READ_TIMEOUT.
160
+ def timeouts(opts = {})
161
+ @open_timeout = opts.fetch(:open_timeout, DEFAULT_HTTP_OPEN_TIMEOUT)
162
+ @read_timeout = opts.fetch(:read_timeout, DEFAULT_HTTP_READ_TIMEOUT)
143
163
  end
144
164
 
145
165
  ##
@@ -170,9 +190,9 @@ module Rbeapi
170
190
  # value is json
171
191
  #
172
192
  # @return [Hash] Returns a Ruby hash of the request message that is
173
- # suitable to be JSON encoded and sent to the desitination node
193
+ # suitable to be JSON encoded and sent to the destination node
174
194
  def request(commands, opts = {})
175
- id = opts.fetch(:reqid, self.object_id)
195
+ id = opts.fetch(:reqid, object_id)
176
196
  format = opts.fetch(:format, 'json')
177
197
  cmds = [*commands]
178
198
  params = { 'version' => 1, 'cmds' => cmds, 'format' => format }
@@ -222,18 +242,26 @@ module Rbeapi
222
242
  #
223
243
  # @param [Hash] :data A hash containing the body of the request
224
244
  # message. This should be a valid eAPI request message.
245
+ # @option :opts [Float] :open_timeout Number of seconds to wait for the
246
+ # eAPI connection to open.
247
+ # @option :opts [Float] :read_timeout Number of seconds to wait for one
248
+ # block of eAPI results to be read (via one read(2) call).
225
249
  #
226
250
  # @return [Hash] returns the response message as a Ruby hash object
227
251
  #
228
252
  # @raises [CommandError] Raised if an eAPI failure response is return
229
253
  # from the destination node.
230
- def send(data)
254
+ def send(data, opts)
231
255
  request = Net::HTTP::Post.new('/command-api')
232
256
  request.body = JSON.dump(data)
233
257
  request.basic_auth @username, @password
234
258
 
259
+ open_timeout = opts.fetch(:open_timeout, @open_timeout)
260
+ read_timeout = opts.fetch(:read_timeout, @read_timeout)
261
+
235
262
  begin
236
- @transport.open_timeout = DEFAULT_HTTP_TIMEOUT
263
+ @transport.open_timeout = open_timeout
264
+ @transport.read_timeout = read_timeout
237
265
  response = @transport.request(request)
238
266
  decoded = JSON(response.body)
239
267
 
@@ -246,18 +274,22 @@ module Rbeapi
246
274
  raise ConnectionError, 'unable to connect to eAPI'
247
275
  end
248
276
 
249
- return decoded
277
+ decoded
250
278
  end
251
279
 
252
280
  ##
253
281
  # Executes the commands on the destination node and returns the
254
282
  # response from the node.
255
283
  #
256
- # @param [Array] :commands The ordered list of commandst to execute
284
+ # @param [Array] :commands The ordered list of commands to execute
257
285
  # on the destination node.
258
286
  # @param [Hash] :opts Optional keyword arguments
259
287
  # @option :opts [String] :encoding Used to specify the encoding to be
260
288
  # used for the response. Valid encoding values are json or text
289
+ # @option :opts [Float] :open_timeout Number of seconds to wait for the
290
+ # eAPI connection to open.
291
+ # @option :opts [Float] :read_timeout Number of seconds to wait for one
292
+ # block of eAPI results to be read (via one read(2) call).
261
293
  #
262
294
  # @returns [Array<Hash>] This method will return the array of responses
263
295
  # for each command executed on the node.
@@ -265,22 +297,23 @@ module Rbeapi
265
297
  # @raises [CommandError] Raises a CommandError if rescued from the
266
298
  # send method and adds the list of commands to the exception message
267
299
  #
268
- # @raises [ConnectionError] Raises a ConnectionError if resuced and
300
+ # @raises [ConnectionError] Raises a ConnectionError if rescued and
269
301
  # adds the list of commands to the exception message
270
302
  def execute(commands, opts = {})
271
- begin
272
- @error = nil
273
- request = request(commands, opts)
274
- response = send request
275
- return response['result']
276
- rescue ConnectionError, CommandError => exc
277
- exc.commands = commands
278
- @error = exc
279
- raise
280
- end
303
+ @error = nil
304
+ request = request(commands, opts)
305
+ response = send(request, opts)
306
+ return response['result']
307
+ rescue ConnectionError, CommandError => exc
308
+ exc.commands = commands
309
+ @error = exc
310
+ raise
281
311
  end
282
312
  end
283
313
 
314
+ ##
315
+ # The SocketEapiConnection provides a class for building a domain
316
+ # socket eAPI connection to Arista EOS devices.
284
317
  class SocketEapiConnection < EapiConnection
285
318
  def initialize(opts = {})
286
319
  path = opts.fetch(:path, DEFAULT_UNIX_SOCKET)
@@ -289,6 +322,9 @@ module Rbeapi
289
322
  end
290
323
  end
291
324
 
325
+ ##
326
+ # The HttpEapiConnection provides a class for building an HTTP
327
+ # eAPI connection to a Arista EOS devices.
292
328
  class HttpEapiConnection < EapiConnection
293
329
  def initialize(opts = {})
294
330
  port = opts.fetch(:port, DEFAULT_HTTP_PORT)
@@ -297,24 +333,28 @@ module Rbeapi
297
333
  transport = Net::HTTP.new(host, port.to_i)
298
334
  super(transport)
299
335
 
300
- user = opts.fetch(:username, 'admin')
301
- pass = opts.fetch(:password, '')
302
- authentication(user, pass)
336
+ authentication(opts)
337
+ timeouts(opts)
303
338
  end
304
339
  end
305
340
 
341
+ ##
342
+ # The HttpLocalEapiConnection provides a class for building an HTTP
343
+ # eAPI connection to a local Arista EOS devices.
306
344
  class HttpLocalEapiConnection < EapiConnection
307
345
  def initialize(opts = {})
308
346
  port = opts.fetch(:port, DEFAULT_HTTP_LOCAL_PORT)
309
347
  transport = Net::HTTP.new('localhost', port)
310
348
  super(transport)
311
349
 
312
- user = opts.fetch(:username, 'admin')
313
- pass = opts.fetch(:password, '')
314
- authentication(user, pass)
350
+ authentication(opts)
351
+ timeouts(opts)
315
352
  end
316
353
  end
317
354
 
355
+ ##
356
+ # The HttpEapiConnection provides a class for building an HTTPS
357
+ # eAPI connection to a Arista EOS devices.
318
358
  class HttpsEapiConnection < EapiConnection
319
359
  def initialize(opts = {})
320
360
  host = opts.fetch(:host, 'localhost')
@@ -325,9 +365,8 @@ module Rbeapi
325
365
  transport.verify_mode = OpenSSL::SSL::VERIFY_NONE
326
366
  super(transport)
327
367
 
328
- user = opts.fetch(:username, 'admin')
329
- pass = opts.fetch(:password, '')
330
- authentication(user, pass)
368
+ authentication(opts)
369
+ timeouts(opts)
331
370
  end
332
371
  end
333
372
  end