netsnmp 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8014fd377e09fcd49d70da331116b3d66bce52e3
4
- data.tar.gz: 9038971c4dd91219e581ddfdfa11d64b062790bf
2
+ SHA256:
3
+ metadata.gz: faea873fa6ca9eaf4c453c77dc2f897af13b523521344f8e39e72006f1493d23
4
+ data.tar.gz: 6e671ad1fb6ecb01ddbad7647ce2c01f532537845cd74fcd3db188a8af543010
5
5
  SHA512:
6
- metadata.gz: b1469577a0aa7719c12fa54eb445b4016f3e44b3caa2d51db8931b18f852256af0482261feeff407e195c0af2cf72d3ddb477ca6062b529f9dd0748e1dd2ffcc
7
- data.tar.gz: 31a013f21505b92217c276b33631c52c0cb42c9d493a24b51a3bd190304f4ac67c3a1e921fa59f6f432f8f5b4b6248f68e65581ef4f2c2f7f044968bda57a4ae
6
+ metadata.gz: 2a49e950ce387bf6c0e41d928b7a2617540990b399814cc5811969cedd4a65483454af203b990e4dcc041aa95cac7cdb19aa2c2fba3c7b16cfb24c424eef5b43
7
+ data.tar.gz: 007eb164271090585dbcab085a0a4bdef899c8acbb8b79ac43cba99c7b859326b7c2b89c08af03716f24d2980110196ac8f1795b527377fedb178b53ca013055
data/.rubocop.yml ADDED
@@ -0,0 +1,11 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 2.3
5
+
6
+ Layout/IndentHeredoc:
7
+ Enabled: false
8
+
9
+ Style/NumericPredicate:
10
+ Exclude:
11
+ - lib/netsnmp.rb
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,69 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2018-02-07 22:49:11 +0000 using RuboCop version 0.52.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ Metrics/BlockLength:
10
+ Max: 200
11
+
12
+ # Offense count: 17
13
+ Metrics/AbcSize:
14
+ Max: 27
15
+
16
+ # Offense count: 2
17
+ # Configuration parameters: CountComments.
18
+ Metrics/ClassLength:
19
+ Max: 150
20
+
21
+ # Offense count: 8
22
+ Metrics/CyclomaticComplexity:
23
+ Max: 20
24
+
25
+ # Offense count: 22
26
+ # Configuration parameters: CountComments.
27
+ Metrics/MethodLength:
28
+ Max: 30
29
+
30
+ # Offense count: 2
31
+ # Configuration parameters: CountKeywordArgs.
32
+ Metrics/ParameterLists:
33
+ Max: 7
34
+
35
+ # Offense count: 1
36
+ Metrics/PerceivedComplexity:
37
+ Max: 9
38
+
39
+ # Offense count: 10
40
+ Style/Documentation:
41
+ Exclude:
42
+ - 'spec/**/*'
43
+ - 'test/**/*'
44
+ - 'lib/netsnmp.rb'
45
+ - 'lib/netsnmp/encryption/aes.rb'
46
+ - 'lib/netsnmp/encryption/des.rb'
47
+ - 'lib/netsnmp/encryption/none.rb'
48
+ - 'lib/netsnmp/scoped_pdu.rb'
49
+ - 'lib/netsnmp/session.rb'
50
+ - 'lib/netsnmp/timeticks.rb'
51
+
52
+ # Offense count: 8
53
+ # Cop supports --auto-correct.
54
+ # Configuration parameters: Strict.
55
+ Style/NumericLiterals:
56
+ MinDigits: 11
57
+
58
+ # Offense count: 264
59
+ # Cop supports --auto-correct.
60
+ # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
61
+ # SupportedStyles: single_quotes, double_quotes
62
+ Style/StringLiterals:
63
+ EnforcedStyle: double_quotes
64
+
65
+ # Offense count: 112
66
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
67
+ # URISchemes: http, https
68
+ Metrics/LineLength:
69
+ Max: 189
data/.travis.yml CHANGED
@@ -5,23 +5,14 @@ services:
5
5
  before_install:
6
6
  - sudo apt-add-repository multiverse
7
7
  - sudo apt-get update
8
- - sudo apt-get install -y sed
9
- - sudo apt-get install -y snmp
10
- - sudo apt-get install -y libsnmp-dev
11
- - sudo apt-get install -y snmp-mibs-downloader
12
- - sudo apt-get install -o Dpkg::Options::="--force-confold" --force-yes -y docker-engine
13
-
14
- before_script:
15
- - sudo download-mibs
16
- - sudo sed -i 's/^mibs/#mibs/g' /etc/snmp/snmp.conf
17
- - spec/support/start_docker.sh
18
- after_script: spec/support/stop_docker.sh
8
+ - sudo apt-get install -o Dpkg::Options::="--force-confold" --force-yes -y docker-ce
19
9
 
20
10
  install:
11
+ - gem update --system
21
12
  - bundle install --path .bundle
22
13
 
23
14
  script:
24
- - bundle exec rake spec:ci
15
+ - spec/support/specs.sh
25
16
 
26
17
  language: ruby
27
18
  rvm:
@@ -29,8 +20,9 @@ rvm:
29
20
  - 2.2
30
21
  - 2.3
31
22
  - 2.4
23
+ - 2.5
32
24
  - ruby-head
33
- - jruby-9.1.7.0
25
+ - jruby-9.1.15.0
34
26
  - jruby-head
35
27
  - rbx-2
36
28
  matrix:
@@ -38,5 +30,5 @@ matrix:
38
30
  - rvm: ruby-head
39
31
  - rvm: jruby-head
40
32
  # to figure out later
41
- - rvm: jruby-9.1.7.0
33
+ - rvm: jruby-9.1.15.0
42
34
  - rvm: rbx-2
data/Gemfile CHANGED
@@ -1,17 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source "https://rubygems.org/"
2
4
  ruby RUBY_VERSION
3
5
 
4
6
  gemspec
5
7
 
6
- gem 'coveralls', require: false
8
+ gem "coveralls", require: false
7
9
 
8
10
  group :development do
9
- gem 'pry'
11
+ gem "pry"
10
12
  end
11
13
 
12
- if RUBY_VERSION < "2.2"
13
- gem "nio4r", "~> 1.2"
14
- end
14
+ gem "nio4r", "~> 1.2" if RUBY_VERSION < "2.2"
15
15
 
16
16
  platforms :mri do
17
17
  gem "pry-byebug", require: false
@@ -19,3 +19,5 @@ platforms :mri do
19
19
  end
20
20
 
21
21
  gem "xorcist"
22
+
23
+ gem "rubocop", require: false
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # netsnmp
1
+ # netsnmp
2
2
 
3
3
  [![Build Status](https://travis-ci.org/swisscom/ruby-netsnmp.svg?branch=master)](https://travis-ci.org/swisscom/ruby-netsnmp)
4
4
  [![Coverage Status](https://coveralls.io/repos/github/swisscom/ruby-netsnmp/badge.svg?branch=master)](https://coveralls.io/github/swisscom/ruby-netsnmp?branch=master)
@@ -11,7 +11,7 @@ The `netsnmp` gem provides a ruby native implementation of the SNMP protocol (v1
11
11
 
12
12
  Add this line to your application's Gemfile:
13
13
 
14
- ```ruby
14
+ ```ruby
15
15
  gem 'netsnmp'
16
16
  ```
17
17
 
@@ -27,7 +27,7 @@ Or install it yourself as:
27
27
  $ gem install netsnmp
28
28
  ```
29
29
 
30
- ## Features
30
+ ## Features
31
31
 
32
32
  This gem provides:
33
33
 
@@ -38,46 +38,48 @@ This gem provides:
38
38
 
39
39
  ## Why?
40
40
 
41
- If you look for snmp gems in ruby toolbox, you'll find a bunch.
42
- You may ask, why not just use one of them?
41
+ If you look for snmp gems in ruby toolbox, you'll find a bunch.
42
+ You may ask, why not just use one of them?
43
43
 
44
44
  Most of them only implement v1 and v2, so if your requirement is to use v3, you're left with only 2 choices: [net-snmp](https://github.com/mixtli/net-snmp) (unmantained since 2013) and its follow-up [net-snmp2](https://github.com/jbreeden/net-snmp2), which started as a fork to fix some bugs left unattended. Both libraries wrap the C netsnmp library using FFI, which leaves them vulnerable to the following bugs (experienced in both libraries):
45
45
 
46
- * Dependency of specific versions of netsnmp C package.
46
+ * Dependency of specific versions of netsnmp C package.
47
47
  * Memory Leaks.
48
48
  * Doesn't work reliable in ruby > 2.0.0-p576, crashing the VM.
49
49
  * Network I/O done by the library, thereby blocking the GVL, thereby making all snmp calls block the whole ruby VM.
50
- * This means, multi-threading is impossible.
50
+ * This means, multi-threading is impossible.
51
51
  * This means, evented I/O is impossible.
52
52
 
53
- All of these issues are resolved here.
53
+ All of these issues are resolved here.
54
54
 
55
55
  ## Features
56
56
 
57
57
  * Client Interface, which supports SNMP v3, v2c, and v1
58
- * Supports get, getnext, set and walk calls.
58
+ * Supports get, getnext, set and walk calls.
59
59
  * Proxy IO object support (for eventmachine/celluloid-io)
60
- * Ruby >= 2.1 support
60
+ * Ruby >= 2.1 support (modern)
61
61
  * Pure Ruby (no FFI)
62
62
 
63
63
  ## Examples
64
64
 
65
- You can use the docker container provided under spec/support to test against these examples (the port used in the examples should be the docker external port mapped to port 161).
65
+ You can use the docker container provided under spec/support to test against these examples (the port used in the examples should be the docker external port mapped to port 161).
66
66
 
67
67
  ```ruby
68
68
  require 'netsnmp'
69
69
 
70
- # example you can test against the docker simulator provided. port attribute might be different.
70
+ # example you can test against the docker simulator provided. port attribute might be different.
71
71
  manager = NETSNMP::Client.new(host: "localhost", port: 33445, username: "simulator",
72
- auth_password: "auctoritas", auth_protocol: :md5,
72
+ auth_password: "auctoritas", auth_protocol: :md5,
73
73
  priv_password: "privatus", priv_protocol: :des,
74
74
  context: "a172334d7d97871b72241397f713fa12")
75
75
 
76
76
  # SNMP get
77
- manager.get(oid: "sysName.0") #=> 'tt'
77
+ # sysName.0
78
+ manager.get(oid: "1.3.6.1.2.1.1.0") #=> 'tt'
78
79
 
79
80
  # SNMP walk
80
- manager.walk("sysORDescr") do |oid_code, value|
81
+ # sysORDescr
82
+ manager.walk(oid: "1.3.6.1.2.1.1.1").each do |oid_code, value|
81
83
  # do something with them
82
84
  puts "for #{oid_code}: #{value}"
83
85
  end
@@ -86,18 +88,51 @@ manager.close
86
88
 
87
89
  # SNMP set
88
90
  manager2 = NETSNMP::Client.new(host: "localhost", port: 33445, username: "simulator",
89
- auth_password: "auctoritas", auth_protocol: :md5,
91
+ auth_password: "auctoritas", auth_protocol: :md5,
90
92
  priv_password: "privatus", priv_protocol: :des,
91
93
  context: "0886e1397d572377c17c15036a1e6c66")
92
94
 
93
95
  # setting to 43, becos yes
94
- manager2.set("sysUpTimeInstance", 43)
96
+ # sysUpTimeInstance
97
+ manager2.set("1.3.6.1.2.1.1.3.0", value: 43)
95
98
 
96
99
  manager2.close
97
100
  ```
98
101
 
99
- SNMP v2/v1 examples will be similar (beware of the differences in the initialization attributes).
102
+ SNMP v2/v1 examples will be similar (beware of the differences in the initialization attributes).
103
+
104
+ ## SNMP Application Types
105
+
106
+ All previous examples were done specifying primitive types, i.e. unless specified otherwise, it's gonna try to convert a ruby "primitive" type to an ASN.1 primitive type, and vice-versa:
107
+
108
+ * Integer -> ASN.1 Integer
109
+ * String -> ASN.1 Octet String
110
+ * nil -> ASN.1 Null
111
+ * true, false -> ASN.1 Boolean
112
+
113
+ That means that, if you pass `value: 43` to the `#set` call, it's going to build a varbind with an ASN.1 Integer. If You issue a `#get` and the response contains an ASN.1 Integer, it's going to return an Integer.
114
+
115
+ However, SNMP defines application-specific ASN.1 types, for which there is support, albeit limited. Currently, there is support for ip addresses and timeticks.
116
+
117
+ * IPAddr -> ASN.1 context-specific
100
118
 
119
+ If you create an `IPAddr` object (ruby standard library `ipaddr`) and pass it to the `#set` call, it will map to the SNMP content-specific code. If the response of a `#get` call contains an ip address, it will map to an `IPAddr` object.
120
+
121
+ * NETSNMP::Timeticks -> ASN.1 content-specific
122
+
123
+ The `NETSNMP::Timeticks` type is internal to this library, but it is a ruby `Numeric` type. You are safe to use it "as a numeric", that is, perform calculations.
124
+
125
+
126
+ You can find usage examples [here](https://github.com/swisscom/ruby-netsnmp/blob/master/spec/varbind_spec.rb). If you need support to a missing type, you have the following options:
127
+
128
+ * Use the `:type` parameter in `#set` calls:
129
+ ```ruby
130
+ # as a symbol
131
+ manager.set("somecounteroid", value: 999999, type: :counter64)
132
+ # as the SNMP specific type id, if you're familiar with the protocol
133
+ manager.set("somecounteroid", value: 999999, type: 6)
134
+ ```
135
+ * Fork this library, extend support, write a test and submit a PR (the desired solution ;) )
101
136
 
102
137
  ## Concurrency
103
138
 
@@ -106,8 +141,8 @@ In ruby, you are usually adviced not to share IO objects across threads. The sam
106
141
  ```ruby
107
142
  general_options = { auth_protocol: ....
108
143
  routers.map do |r|
109
- Thread.start do
110
- NETSNMP::Client.new(general_options.merge(host: r)) do |cl|
144
+ Thread.start do
145
+ NETSNMP::Client.new(general_options.merge(host: r)) do |cl|
111
146
  cli.get(oid: "1.6.3.......
112
147
 
113
148
  end
@@ -115,13 +150,13 @@ routers.map do |r|
115
150
  end.each(&:join)
116
151
  ```
117
152
 
118
- Evented IO is also supported, in that you can pass a `:proxy` object as an already opened channel of communication to the client. Very important: you have to take care of the lifecycle, as the client will not connect and will not close the object, it will assume no control over it.
153
+ Evented IO is also supported, in that you can pass a `:proxy` object as an already opened channel of communication to the client. Very important: you have to take care of the lifecycle, as the client will not connect and will not close the object, it will assume no control over it.
119
154
 
120
- When passing a proxy object, you can omit the `:host` parameter.
155
+ When passing a proxy object, you can omit the `:host` parameter.
121
156
 
122
157
  The proxy object will have to be a duck-type implementing `#send`, which is a method receiving the sending PDU payload, and return the payload of the receiving PDU.
123
158
 
124
- Here is a small pseudo-code example:
159
+ Here is a small pseudo-code example:
125
160
 
126
161
  ```ruby
127
162
  # beware, we are inside a warp-speed loop!!!
@@ -136,14 +171,14 @@ end
136
171
  proxy.close
137
172
  ```
138
173
 
139
- For more information about this subject, the specs test this feature against celluloid-io. An eventmachine could be added, if someone would be kind enough to provide an implementation.
174
+ For more information about this subject, the specs test this feature against celluloid-io. An eventmachine could be added, if someone would be kind enough to provide an implementation.
140
175
 
141
176
  ## Performance
142
177
 
143
178
 
144
179
  ### XOR
145
180
 
146
- This library has some workarounds to some missing features in the ruby language, namely the inexistence of a byte array structure. The closest we have is a byte stream presented as a String with ASCII encoding. A method was added to the String class called `#xor` for some operations needed internally. To prevent needless monkey-patches, Refinements have been employed.
181
+ This library has some workarounds to some missing features in the ruby language, namely the inexistence of a byte array structure. The closest we have is a byte stream presented as a String with ASCII encoding. A method was added to the String class called `#xor` for some operations needed internally. To prevent needless monkey-patches, Refinements have been employed.
147
182
 
148
183
  If `#xor` becomes at some point the bottleneck of your usage, this gem has also support for [xorcist](https://github.com/fny/xorcist/). You just have to add it to your Gemfile (or install it in the system):
149
184
 
@@ -152,12 +187,12 @@ If `#xor` becomes at some point the bottleneck of your usage, this gem has also
152
187
 
153
188
  gem 'netsnmp'
154
189
 
155
- # or, in the command line
190
+ # or, in the command line
156
191
 
157
192
  $ gem install netsnmp
158
193
  ```
159
194
 
160
- and `netsnmp` will automatically pick it up.
195
+ and `netsnmp` will automatically pick it up.
161
196
 
162
197
  ## Auth/Priv Key
163
198
 
@@ -166,7 +201,7 @@ If you'll use this gem often with SNMP v3 and auth/priv security level enabled,
166
201
  There is a recommended work-around, but this is only usable **if you are using the same user/authpass/privpass on all the hosts!!!**. Use this with care, then:
167
202
 
168
203
  ```ruby
169
- $shared_security_parameters = NETSNMP::SecurityParameters.new(security_level: :authpriv, username: "mustermann",
204
+ $shared_security_parameters = NETSNMP::SecurityParameters.new(security_level: :authpriv, username: "mustermann",
170
205
  auth_protocol: :md5, priv_protocol: :aes, ....
171
206
  # this will eager-load the auth/priv_key
172
207
  ...
@@ -184,9 +219,9 @@ All encoding/decoding/encryption/decryption/digests are done using `openssl`, wh
184
219
 
185
220
  ## Tests
186
221
 
187
- This library uses RSpec. The client specs are "integration" tests, in that we communicate with an snmp agent simulator.
222
+ This library uses RSpec. The client specs are "integration" tests, in that we communicate with an snmp agent simulator.
188
223
 
189
- To start the simulator locally, you'll need docker 1.9 or higher (Why 1.9? ```--build-arg``` parameter support was needed for our builds in the CI. You could use a lower version by providing the proxy environment variables in the Dockerfile directly, provided you don't merge these changes to master, thereby exposing your proxy).
224
+ To start the simulator locally, you'll need docker 1.9 or higher (Why 1.9? ```--build-arg``` parameter support was needed for our builds in the CI. You could use a lower version by providing the proxy environment variables in the Dockerfile directly, provided you don't merge these changes to master, thereby exposing your proxy).
190
225
 
191
226
  ```
192
227
  > spec/support/start_docker.sh
@@ -217,7 +252,6 @@ There are some features which this gem doesn't support. It was built to provide
217
252
 
218
253
  * No MIB support (you can only work with OIDs)
219
254
  * No server (Agent, in SNMP-ish) implementation.
220
- * No getbulk support.
255
+ * No getbulk support.
221
256
 
222
257
  So if you like the gem, but would rather have these features implemented, please help by sending us a PR and we'll gladly review it.
223
-
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require 'bundler/gem_tasks'
2
- require 'rspec/core/rake_task'
3
- require 'coveralls/rake/task'
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+ require "coveralls/rake/task"
4
6
 
5
7
  desc "runs the tests and sends to coveralls server"
6
8
  Coveralls::RakeTask.new
@@ -10,17 +12,13 @@ RSpec::Core::RakeTask.new
10
12
 
11
13
  task default: [:spec]
12
14
 
13
-
14
-
15
15
  namespace :spec do
16
16
  desc "runs the tests in coverage mode"
17
17
  task :coverage do
18
- ENV['COVERAGE'] = "true"
18
+ ENV["COVERAGE"] = "true"
19
19
  Rake::Task["spec"].execute
20
20
  end
21
21
 
22
22
  desc "runs tests, check coverage, pushes to coverage server"
23
- task :ci => ['spec:coverage', 'coveralls:push']
23
+ task ci: ["spec:coverage", "coveralls:push"]
24
24
  end
25
-
26
-
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
+
3
+ require "timeout"
4
+
2
5
  module NETSNMP
3
6
  # Main Entity, provides the user-facing API to communicate with SNMP Agents
4
7
  #
5
8
  # Under the hood it creates a "session" (analogous to the net-snmp C session), which will be used
6
9
  # to proxy all the communication to the agent. the Client ensures that you only write pure ruby and
7
- # read pure ruby, not concerning with snmp-speak like PDUs, varbinds and the like.
10
+ # read pure ruby, not concerning with snmp-speak like PDUs, varbinds and the like.
8
11
  #
9
12
  #
10
13
  class Client
@@ -14,7 +17,7 @@ module NETSNMP
14
17
  # @option options [String, Integer, nil] :version the version of the protocol (defaults to 3).
15
18
  # also accepts common known declarations like :v3, "v2c", etc
16
19
  # @option options [Integer] :retries number of retries for each failed PDU (after which it raise timeout error. Defaults to {RETRIES} retries)
17
- # @yield [client] the instantiated client, after which it closes it for use.
20
+ # @yield [client] the instantiated client, after which it closes it for use.
18
21
  # @example Yielding a clinet
19
22
  # NETSNMP::Client.new(host: "241.232.22.12") do |client|
20
23
  # puts client.get(oid: "1.3.6.1.2.1.1.5.0")
@@ -22,25 +25,24 @@ module NETSNMP
22
25
  #
23
26
  def initialize(**options)
24
27
  version = options[:version]
25
- version = case version
26
- when Integer then version # assume the use know what he's doing
27
- when /v?1/ then 0
28
- when /v?2c?/ then 1
29
- when /v?3/, nil then 3
30
- end
28
+ version = case version
29
+ when Integer then version # assume the use know what he's doing
30
+ when /v?1/ then 0
31
+ when /v?2c?/ then 1
32
+ when /v?3/, nil then 3
33
+ end
31
34
 
32
35
  @retries = options.fetch(:retries, RETRIES)
33
36
  @session ||= version == 3 ? V3Session.new(options) : Session.new(options)
34
- if block_given?
35
- begin
36
- yield self
37
- ensure
38
- close
39
- end
37
+ return unless block_given?
38
+ begin
39
+ yield self
40
+ ensure
41
+ close
40
42
  end
41
43
  end
42
44
 
43
- # Closes the inner section
45
+ # Closes the inner section
44
46
  def close
45
47
  @session.close
46
48
  end
@@ -49,23 +51,24 @@ module NETSNMP
49
51
  #
50
52
  # @see {NETSNMP::Varbind#new}
51
53
  #
52
- def get(oid_opts)
53
- request = @session.build_pdu(:get, oid_opts)
54
+ def get(*oid_opts)
55
+ request = @session.build_pdu(:get, *oid_opts)
54
56
  response = handle_retries { @session.send(request) }
55
57
  yield response if block_given?
56
- response.varbinds.first.value
58
+ values = response.varbinds.map(&:value)
59
+ values.size > 1 ? values : values.first
57
60
  end
58
61
 
59
62
  # Performs an SNMP GETNEXT Request
60
- #
63
+ #
61
64
  # @see {NETSNMP::Varbind#new}
62
65
  #
63
- def get_next(oid_opts)
64
- request = @session.build_pdu(:getnext, oid_opts)
66
+ def get_next(*oid_opts)
67
+ request = @session.build_pdu(:getnext, *oid_opts)
65
68
  response = handle_retries { @session.send(request) }
66
69
  yield response if block_given?
67
- varbind = response.varbinds.first
68
- [varbind.oid, varbind.value]
70
+ values = response.varbinds.map { |v| [v.oid, v.value] }
71
+ values.size > 1 ? values : values.first
69
72
  end
70
73
 
71
74
  # Perform a SNMP Walk (issues multiple subsequent GENEXT requests within the subtree rooted on an OID)
@@ -74,7 +77,7 @@ module NETSNMP
74
77
  #
75
78
  # @return [Enumerator] the enumerator-collection of the oid-value pairs
76
79
  #
77
- def walk(oid: )
80
+ def walk(oid:)
78
81
  walkoid = oid
79
82
  Enumerator.new do |y|
80
83
  code = walkoid
@@ -84,10 +87,10 @@ module NETSNMP
84
87
  get_next(oid: code) do |response|
85
88
  response.varbinds.each do |varbind|
86
89
  code = varbind.oid
87
- if !OID.parent?(walkoid, code) or
88
- varbind.value.eql?(:endofmibview) or
89
- code == first_response_code
90
- throw(:walk)
90
+ if !OID.parent?(walkoid, code) ||
91
+ varbind.value.eql?(:endofmibview) ||
92
+ (code == first_response_code)
93
+ throw(:walk)
91
94
  else
92
95
  y << [code, varbind.value]
93
96
  end
@@ -102,13 +105,13 @@ module NETSNMP
102
105
  # Perform a SNMP GETBULK Request (performs multiple GETNEXT)
103
106
  #
104
107
  # @param [String] oid the first oid
105
- # @param [Hash] options the varbind options
108
+ # @param [Hash] options the varbind options
106
109
  # @option options [Integer] :errstat sets the number of objects expected for the getnext instance
107
- # @option options [Integer] :errindex number of objects repeating for all the repeating IODs.
110
+ # @option options [Integer] :errindex number of objects repeating for all the repeating IODs.
108
111
  #
109
112
  # @return [Enumerator] the enumerator-collection of the oid-value pairs
110
113
  #
111
- #def get_bulk(oid)
114
+ # def get_bulk(oid)
112
115
  # request = @session.build_pdu(:getbulk, *oids)
113
116
  # request[:error_status] = options.delete(:non_repeaters) || 0
114
117
  # request[:error_index] = options.delete(:max_repetitions) || 10
@@ -118,29 +121,29 @@ module NETSNMP
118
121
  # y << [ varbind.oid, varbind.value ]
119
122
  # end
120
123
  # end
121
- #end
124
+ # end
122
125
 
123
126
  # Perform a SNMP SET Request
124
127
  #
125
128
  # @see {NETSNMP::Varbind#new}
126
129
  #
127
- def set(oid_opts)
128
- request = @session.build_pdu(:set, oid_opts)
130
+ def set(*oid_opts)
131
+ request = @session.build_pdu(:set, *oid_opts)
129
132
  response = handle_retries { @session.send(request) }
130
- yield response if block_given?
131
- response.varbinds.map(&:value)
133
+ yield response if block_given?
134
+ values = response.varbinds.map(&:value)
135
+ values.size > 1 ? values : values.first
132
136
  end
133
137
 
134
-
135
138
  private
136
139
 
137
- # Handles timeout errors by reissuing the same pdu until it runs out or retries.
140
+ # Handles timeout errors by reissuing the same pdu until it runs out or retries.
138
141
  def handle_retries
139
142
  retries = @retries
140
143
  begin
141
144
  yield
142
145
  rescue Timeout::Error => e
143
- raise e if retries == 0
146
+ raise e if retries.zero?
144
147
  retries -= 1
145
148
  retry
146
149
  end