netsnmp 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 615bdc207baf5d3c7db16cfe106324acbc2f434937366ed6750d653df712f36c
4
- data.tar.gz: d1601c013dadf943eb202964c43c2ac6a17eb40dddb9544577d901513eedcf08
3
+ metadata.gz: d6bb62b9abd416188660e04be1c12cf009b1df0e307030b9c239ea4b2acd73cc
4
+ data.tar.gz: ee88f7eb292f1a0077ab25e4677713290447e0e7755049bbe6db50f07d15d6a1
5
5
  SHA512:
6
- metadata.gz: f3fbc65c63d1c3c8d0711e8c2c225d3d0442211f8875befa0c62b0de44dbe5e9e22d03b0e55ac49cf05bbac80c282be59c73f21503166c1582389e196b3948a7
7
- data.tar.gz: 473a0f7f7f9f6d8fb9522bd809a7acd9644128bfdd471839a63e0ffb9b825b066cc1eb5e1be45f6a703fe94e18764212f6305b5f147ed04495eede058eb24b3b
6
+ metadata.gz: fc90cc626d4be2a04d598ec267bcfc108e87aea8e8a585a7611033fc56cb6c174a222250bb9eeeb05b2d03d058983b106c92c30ba3d91e922b171ecfbc37041a
7
+ data.tar.gz: '09dbbb277ae24d9b760c0de70738a02037da527d653d5e003632c1b41d808cc21c44034fb51bec63394a132fe3c30ffaac1adc846dc061ca483e13fc0719af97'
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # netsnmp
2
2
 
3
- [![Build Status](https://travis-ci.org/swisscom/ruby-netsnmp.svg?branch=master)](https://travis-ci.org/swisscom/ruby-netsnmp)
4
- [![Coverage Status](https://coveralls.io/repos/github/swisscom/ruby-netsnmp/badge.svg?branch=master)](https://coveralls.io/github/swisscom/ruby-netsnmp?branch=master)
3
+ ![Tests](https://github.com/swisscom/ruby-netsnmp/workflows/Tests/badge.svg)
5
4
  [![Code Climate](https://codeclimate.com/github/swisscom/ruby-netsnmp/badges/gpa.svg)](https://codeclimate.com/github/swisscom/ruby-netsnmp)
6
5
  [![Docs](http://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/github/swisscom/ruby-netsnmp/master)
7
6
 
@@ -223,6 +222,7 @@ All encoding/decoding/encryption/decryption/digests are done using `openssl`, wh
223
222
 
224
223
  This library uses RSpec. The client specs are "integration" tests, in that we communicate with an [snmpsim-built snmp agent simulator](https://github.com/etingof/snmpsim).
225
224
 
225
+
226
226
  ### RSpec
227
227
 
228
228
  You can run all tests by typing:
@@ -234,37 +234,31 @@ You can run all tests by typing:
234
234
  ...
235
235
  ```
236
236
 
237
- ### SNMP Simulator
238
-
239
- You can install the package yourself (ex: `pip install snmpsim`) and run the server locally, and then set the `SNMP_PORT` environment variable, where the snmp simulator is running.
240
237
 
241
- #### Docker
238
+ ### Docker
242
239
 
243
- The preferred way to use the snmp simulator is by using docker.
244
-
245
- In order to start the simulator container, run:
240
+ The most straightforward way of running the tests is by using the `docker-compose` setup (which is also what's used in the CI). Run it against the ruby version you're targeting:
246
241
 
247
242
  ```
248
- > spec/support/spec.sh start
243
+ > docker-compose -f docker-compose.yml -f docker-compose-ruby-${RUBY_MAJOR_VERSION}.${RUBY_MAJOR_VERSION}.yml run netsnmp
249
244
  ```
250
245
 
251
- after, you just need to set the `SNMP_PORT` variable to the port found typing:
246
+ The CI runs the tests against all supported ruby versions. If changes break a specific version of ruby, make sure you commit appropriate changes addressing the edge case, or let me know in the issues board, so I can help.
252
247
 
253
- ```
254
- > docker port test-snmp 1161/udp
255
- ```
248
+ ### SNMP Simulator
256
249
 
257
- and run the tests.
250
+ The SNMP simulator runs in its own container in the `docker` setup.
258
251
 
259
- #### CI
252
+ You can install the package yourself (ex: `pip install snmpsim`) and run the server locally, and then set the `SNMP_PORT` environment variable, where the snmp simulator is running.
260
253
 
261
- If you want to replicate what the CI is doing, just do:
254
+ #### CI
262
255
 
263
- ```
264
- > spec/support/spec.sh run
265
- ```
256
+ The job of the CI is:
266
257
 
267
- Which should: build and run the simulator container, run the tests, run rubocop, and remove all artifacts.
258
+ * Run all the tests;
259
+ * Make sure the tests cover an appropriate surface of the code;
260
+ * Lint the code;
261
+ * (for ruby 3.0) type check the code;
268
262
 
269
263
 
270
264
  ## Contributing
@@ -34,6 +34,18 @@ rescue LoadError
34
34
  end
35
35
 
36
36
  module NETSNMP
37
+ module StringExtensions
38
+ # If you wonder why this is there: the oauth feature uses a refinement to enhance the
39
+ # Regexp class locally with #match? , but this is never tested, because ActiveSupport
40
+ # monkey-patches the same method... Please ActiveSupport, stop being so intrusive!
41
+ # :nocov:
42
+ refine(String) do
43
+ def match?(*args)
44
+ !match(*args).nil?
45
+ end
46
+ end
47
+ end
48
+
37
49
  def self.debug=(io)
38
50
  @debug_output = io
39
51
  end
@@ -23,8 +23,7 @@ module NETSNMP
23
23
  # puts client.get(oid: "1.3.6.1.2.1.1.5.0")
24
24
  # end
25
25
  #
26
- def initialize(**options)
27
- version = options[:version]
26
+ def initialize(version: nil, **options)
28
27
  version = case version
29
28
  when Integer then version # assume the use know what he's doing
30
29
  when /v?1/ then 0
@@ -33,7 +32,7 @@ module NETSNMP
33
32
  end
34
33
 
35
34
  @retries = options.fetch(:retries, RETRIES)
36
- @session ||= version == 3 ? V3Session.new(options) : Session.new(options)
35
+ @session ||= version == 3 ? V3Session.new(**options) : Session.new(version: version, **options)
37
36
  return unless block_given?
38
37
  begin
39
38
  yield self
@@ -4,13 +4,14 @@ module NETSNMP
4
4
  # Abstracts the OID structure
5
5
  #
6
6
  module OID
7
+ using StringExtensions unless String.method_defined?(:match?)
8
+
7
9
  OIDREGEX = /^[\d\.]*$/
8
10
 
9
11
  module_function
10
12
 
11
13
  def build(o)
12
14
  case o
13
- when OID then o
14
15
  when Array
15
16
  o.join(".")
16
17
  when OIDREGEX
@@ -29,7 +30,7 @@ module NETSNMP
29
30
  # @return [true, false] whether the given OID belongs to the sub-tree
30
31
  #
31
32
  def parent?(parent_oid, child_oid)
32
- child_oid.match(/\A#{parent_oid}\./)
33
+ child_oid.match?(/\A#{parent_oid}\./)
33
34
  end
34
35
  end
35
36
  end
@@ -55,7 +55,7 @@ module NETSNMP
55
55
  when :response then 2
56
56
  else raise Error, "#{type} is not supported as type"
57
57
  end
58
- new(args.merge(type: typ))
58
+ new(type: typ, **args)
59
59
  end
60
60
  end
61
61
 
@@ -64,7 +64,7 @@ module NETSNMP
64
64
  attr_reader :version, :community, :request_id
65
65
 
66
66
  def initialize(type:, headers:,
67
- request_id: nil,
67
+ request_id: SecureRandom.random_number(MAXREQUESTID),
68
68
  error_status: 0,
69
69
  error_index: 0,
70
70
  varbinds: [])
@@ -75,9 +75,9 @@ module NETSNMP
75
75
  @type = type
76
76
  @varbinds = []
77
77
  varbinds.each do |varbind|
78
- add_varbind(varbind)
78
+ add_varbind(**varbind)
79
79
  end
80
- @request_id = request_id || SecureRandom.random_number(MAXREQUESTID)
80
+ @request_id = request_id
81
81
  check_error_status(@error_status)
82
82
  end
83
83
 
@@ -9,6 +9,8 @@ module NETSNMP
9
9
  super(type: type, headers: [3, nil], **options)
10
10
  end
11
11
 
12
+ private
13
+
12
14
  def encode_headers_asn
13
15
  [OpenSSL::ASN1::OctetString.new(@engine_id || ""),
14
16
  OpenSSL::ASN1::OctetString.new(@context || "")]
@@ -24,7 +24,7 @@ module NETSNMP
24
24
 
25
25
  # @param [String] username the snmp v3 username
26
26
  # @param [String] engine_id the device engine id (initialized to '' for report)
27
- # @param [Symbol, integer] security_level allowed snmp v3 security level (:auth_priv, :auh_no_priv, etc)
27
+ # @param [Symbol, integer] security_level allowed snmp v3 security level (:auth_priv, :auth_no_priv, etc)
28
28
  # @param [Symbol, nil] auth_protocol a supported authentication protocol (currently supported: :md5, :sha)
29
29
  # @param [Symbol, nil] priv_protocol a supported privacy protocol (currently supported: :des, :aes)
30
30
  # @param [String, nil] auth_password the authentication password
@@ -99,7 +99,7 @@ module NETSNMP
99
99
  # @note this method is used in the process of authenticating a message
100
100
  def sign(message)
101
101
  # don't sign unless you have to
102
- return nil unless @auth_protocol
102
+ return unless @auth_protocol
103
103
 
104
104
  key = auth_key.dup
105
105
 
@@ -211,7 +211,7 @@ module NETSNMP
211
211
  end
212
212
 
213
213
  def authorizable?
214
- @auth_protocol && @auth_protocol != :none
214
+ @auth_protocol != :none
215
215
  end
216
216
  end
217
217
  end
@@ -10,7 +10,7 @@ module NETSNMP
10
10
  def initialize(version: 1, community: "public", **options)
11
11
  @version = version
12
12
  @community = community
13
- validate(options)
13
+ validate(**options)
14
14
  end
15
15
 
16
16
  # Closes the session
@@ -36,23 +36,20 @@ module NETSNMP
36
36
  # @return [NETSNMP::PDU] the response pdu
37
37
  #
38
38
  def send(pdu)
39
- encoded_request = encode(pdu)
39
+ encoded_request = pdu.to_der
40
40
  encoded_response = @transport.send(encoded_request)
41
- decode(encoded_response)
41
+ PDU.decode(encoded_response)
42
42
  end
43
43
 
44
44
  private
45
45
 
46
- def validate(**options)
47
- proxy = options[:proxy]
46
+ def validate(host: nil, port: 161, proxy: nil, timeout: TIMEOUT, **)
48
47
  if proxy
49
48
  @proxy = true
50
49
  @transport = proxy
51
50
  else
52
- host, port = options.values_at(:host, :port)
53
51
  raise "you must provide an hostname/ip under :host" unless host
54
- port ||= 161 # default snmp port
55
- @transport = Transport.new(host, port.to_i, timeout: options.fetch(:timeout, TIMEOUT))
52
+ @transport = Transport.new(host, port.to_i, timeout: timeout)
56
53
  end
57
54
  @version = case @version
58
55
  when Integer then @version # assume the use know what he's doing
@@ -64,14 +61,6 @@ module NETSNMP
64
61
  end
65
62
  end
66
63
 
67
- def encode(pdu)
68
- pdu.to_der
69
- end
70
-
71
- def decode(stream)
72
- PDU.decode(stream)
73
- end
74
-
75
64
  class Transport
76
65
  MAXPDUSIZE = 0xffff + 1
77
66
 
@@ -4,7 +4,7 @@ module NETSNMP
4
4
  # Abstraction for the v3 semantics.
5
5
  class V3Session < Session
6
6
  # @param [String, Integer] version SNMP version (always 3)
7
- def initialize(version: 3, context: "", **opts)
7
+ def initialize(context: "", **opts)
8
8
  @context = context
9
9
  @security_parameters = opts.delete(:security_parameters)
10
10
  super
@@ -19,8 +19,10 @@ module NETSNMP
19
19
  end
20
20
 
21
21
  # @see {NETSNMP::Session#send}
22
- def send(*)
23
- pdu, = super
22
+ def send(pdu)
23
+ encoded_request = encode(pdu)
24
+ encoded_response = @transport.send(encoded_request)
25
+ pdu, = decode(encoded_response)
24
26
  pdu
25
27
  end
26
28
 
@@ -6,7 +6,7 @@ module NETSNMP
6
6
  class Varbind
7
7
  attr_reader :oid, :value
8
8
 
9
- def initialize(oid, value: nil, type: nil, **_opts)
9
+ def initialize(oid, value: nil, type: nil)
10
10
  @oid = OID.build(oid)
11
11
  @type = type
12
12
  @value = convert_val(value) if value
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NETSNMP
4
- VERSION = "0.1.9"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -0,0 +1,24 @@
1
+ module NETSNMP
2
+ class Client
3
+
4
+ def get: (*untyped) -> untyped
5
+ | (*untyped) { (PDU) -> void } -> untyped
6
+
7
+ def get_next: (*untyped) -> untyped
8
+ | (*untyped) { (PDU) -> void } -> untyped
9
+
10
+ def set: (*untyped) -> untyped
11
+ | (*untyped) { (PDU) -> void } -> untyped
12
+
13
+ def inform: (*untyped) -> untyped
14
+ | (*untyped) { (PDU) -> void } -> untyped
15
+
16
+ def walk: (oid: oid) -> _Each[oid_type, oid_value]
17
+
18
+ def close: () -> void
19
+
20
+ private
21
+
22
+ def initialize: (?version?: snmp_version, **untyped) -> untyped
23
+ end
24
+ end
@@ -0,0 +1,7 @@
1
+ module NETSNMP
2
+ module Message
3
+ def self?.decode: (String stream, security_parameters: SecurityParameters) -> [ScopedPDU, String, Integer, Integer]
4
+
5
+ def self?.encode: (ScopedPDU pdu, security_parameters: SecurityParameters, ?engine_boots: Integer, ?engine_time: Integer) -> String
6
+ end
7
+ end
@@ -0,0 +1,23 @@
1
+ module NETSNMP
2
+ interface _Logger
3
+ def <<: (string) -> void
4
+ end
5
+
6
+ interface _Authenticate
7
+ def reset: () -> void
8
+ def <<: (string) -> void
9
+ def digest: () -> String
10
+ end
11
+
12
+ interface _Encrypt
13
+ def encrypt: (String payload, engine_boots: Integer, engine_time: Integer) -> String
14
+
15
+ def decrypt: (String payload, salt: String, engine_boots: Integer, engine_time: Integer) -> String
16
+ end
17
+
18
+ type snmp_version = 0 | 1 | 3 | :v1 | :v2c | :v3 | nil
19
+
20
+ def self.debug=: (_Logger) -> void
21
+
22
+ def self.debug: { () -> string } -> void
23
+ end
@@ -0,0 +1,18 @@
1
+ module NETSNMP
2
+ type oid = String | Array[Integer]
3
+
4
+ type oid_type = Integer | :ipaddress | :counter32 | :gauge | :timetick | :opaque | :nsap | :counter64 | :uinteger
5
+
6
+ type oid_value = String | Integer | Timetick | true | false | nil | IPAddr
7
+
8
+ # type oid_options = {}
9
+
10
+ module OID
11
+
12
+ def self?.build: (oid) -> String
13
+
14
+ def self?.to_asn: (String oid) -> OpenSSL::ASN1::ObjectId
15
+
16
+ def self?.parent?: (String oid, String oid) -> bool
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ module OpenSSL
2
+ module ASN1
3
+ class ASN1Data
4
+ end
5
+ class ObjectId < ASN1Data
6
+ end
7
+ class Primitive < ASN1Data
8
+ end
9
+ class Integer < ASN1Data
10
+ end
11
+ class OctetString < ASN1Data
12
+ end
13
+ class Sequence < ASN1Data
14
+ end
15
+ end
16
+ end
17
+
18
+ interface _ToAsn
19
+ def to_asn: () -> OpenSSL::ASN1::ASN1Data
20
+ end
@@ -0,0 +1,48 @@
1
+ module NETSNMP
2
+ type pdu_type = :get | :getnext | :set | :inform | :trap | :response
3
+
4
+ class PDU
5
+
6
+ # type pdu_options = {
7
+ # headers: [snmp_version?, String?],
8
+ # ?request_id: String,
9
+ # ?error_status: Integer,
10
+ # ?error_index: Integer,
11
+ # ?varbinds: Array[varbind_options]
12
+ # }
13
+
14
+ attr_reader varbinds: Array[Varbind]
15
+ attr_reader type: pdu_type
16
+ attr_reader version: snmp_version
17
+ attr_reader community: String
18
+ attr_reader request_id: Integer
19
+
20
+ def self.decode: (String der) -> PDU
21
+ | (OpenSSL::ASN1::ASN1Data der) -> PDU
22
+
23
+ def self.build: (pdu_type, **untyped) -> PDU
24
+
25
+
26
+ def to_asn: () -> OpenSSL::ASN1::ASN1Data
27
+
28
+ def to_der: () -> String
29
+
30
+ def add_varbind: (oid: oid, **varbind_options) -> void
31
+ alias << add_varbind
32
+
33
+ private
34
+
35
+ def initialize: (
36
+ type: Integer,
37
+ headers: [snmp_version?, String?],
38
+ ?request_id: Integer,
39
+ ?error_status: Integer,
40
+ ?error_index: Integer,
41
+ ?varbinds: Array[varbind_options]
42
+ ) -> untyped
43
+
44
+ def encode_headers_asn: () -> [OpenSSL::ASN1::Integer, OpenSSL::ASN1::OctetString]
45
+
46
+ def check_error_status: (Integer) -> void
47
+ end
48
+ end
@@ -0,0 +1,15 @@
1
+ module NETSNMP
2
+ class ScopedPDU < PDU
3
+ attr_reader engine_id: String
4
+
5
+ private
6
+
7
+ def initialize: (
8
+ type: Integer,
9
+ headers: [String?, String?],
10
+ **untyped
11
+ ) -> void
12
+
13
+ def encode_headers_asn: () -> [OpenSSL::ASN1::OctetString, OpenSSL::ASN1::OctetString]
14
+ end
15
+ end
@@ -0,0 +1,56 @@
1
+ module NETSNMP
2
+ class SecurityParameters
3
+ type security_level = :noauth | :auth_no_priv | :auth_priv | 0 | 1 | 3 | nil
4
+
5
+ type auth_protocol = :md5 | :sha
6
+ type priv_protocol = :des | :aes
7
+
8
+
9
+ @auth_protocol: auth_protocol?
10
+ @auth_password: String?
11
+ @priv_protocol: priv_protocol?
12
+ @priv_password: String?
13
+ @digest: _Authenticate?
14
+ @encryption: _Encrypt?
15
+
16
+ attr_reader security_level: security_level
17
+ attr_reader username: String
18
+ attr_reader engine_id: String
19
+
20
+ def engine_id=: (String id) -> void
21
+
22
+ def encode: (_ToAsn, salt: OpenSSL::ASN1::ASN1Data, engine_time: Integer, engine_boots: Integer) -> [OpenSSL::ASN1::ASN1Data, OpenSSL::ASN1::ASN1Data]
23
+
24
+ def decode: (OpenSSL::ASN1::ASN1Data | String der, salt: OpenSSL::ASN1::ASN1Data | String, engine_time: Integer, engine_boots: Integer) -> OpenSSL::ASN1::ASN1Data
25
+
26
+ def sign: (String message) -> String?
27
+
28
+ def verify: (String stream, String salt) -> void
29
+
30
+ def must_revalidate?: () -> bool
31
+
32
+ private
33
+
34
+ def initialize: (
35
+ username: String,
36
+ ?engine_id: String,
37
+ ?security_level: security_level?,
38
+ ?auth_protocol: auth_protocol?,
39
+ ?auth_password: String?,
40
+ ?priv_protocol: priv_protocol?,
41
+ ?priv_password: String?,
42
+ ) -> untyped
43
+
44
+ def auth_key: () -> String
45
+
46
+ def priv_key: () -> String
47
+
48
+ def check_parameters: () -> void
49
+
50
+ def localize_key: (String key) -> String
51
+
52
+ def passkey: (String password) -> String
53
+
54
+ def authorizable?: () -> bool
55
+ end
56
+ end
@@ -0,0 +1,36 @@
1
+ module NETSNMP
2
+ class Session
3
+ @transport: _Transport
4
+ @version: 0 | 1 | 3
5
+ @community: String?
6
+
7
+ def close: () -> void
8
+
9
+ def build_pdu: (pdu_type, *untyped) -> PDU
10
+
11
+ def send: (PDU) -> PDU
12
+
13
+ private
14
+
15
+ def initialize: (?version: snmp_version, ?community: String, **untyped) -> untyped
16
+
17
+ def validate: (?host: String?, ?port: Integer, ?proxy: _Transport, ?timeout: Integer, **untyped) -> void
18
+
19
+ class Transport
20
+ def initialize: (String host, Integer port, timeout: Integer) -> untyped
21
+ def close: () -> void
22
+ def send: (String payload) -> String
23
+ def write: (String) -> void
24
+ def recv: () -> void
25
+
26
+ private
27
+
28
+ def wait: (:wait_readable | :wait_writable) -> void
29
+ end
30
+ end
31
+
32
+ interface _Transport
33
+ def close: () -> void
34
+ def send: (String payload) -> String
35
+ end
36
+ end
@@ -0,0 +1,7 @@
1
+ module NETSNMP
2
+ class Timetick < Numeric
3
+ @ticks: Integer
4
+
5
+ def to_asn: () -> OpenSSL::ASN1::ASN1Data
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ module NETSNMP
2
+ class V3Session < Session
3
+
4
+ def build_pdu: (pdu_type, *untyped) -> ScopedPDU
5
+
6
+ def send: (ScopedPDU pdu) -> ScopedPDU
7
+ | (ScopedPDU pdu) -> [PDU, String, Integer, Integer]
8
+
9
+ private
10
+
11
+ def encode: (ScopedPDU) -> String
12
+
13
+ def initialize: (?context: String, **untyped) -> untyped
14
+
15
+ def security_parameters: () -> SecurityParameters
16
+
17
+ def probe_for_engine: () -> String
18
+
19
+ def decode: (String, ?security_parameters: SecurityParameters) -> [PDU, String, Integer, Integer]
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ module NETSNMP
2
+ type varbind_options = untyped
3
+
4
+ class Varbind
5
+
6
+ type varbind_value = OpenSSL::ASN1::OctetString | OpenSSL::ASN1::Primitive | OpenSSL::ASN1::ASN1Data | oid_value
7
+
8
+ attr_reader oid: String
9
+ attr_reader value: oid_value
10
+
11
+ def to_asn: () -> OpenSSL::ASN1::Sequence
12
+
13
+ def to_der: () -> String
14
+
15
+ def convert_val: (varbind_value) -> oid_value
16
+
17
+
18
+ def convert_to_asn: (oid_type, oid_value) -> OpenSSL::ASN1::ASN1Data
19
+
20
+ def convert_application_asn: (OpenSSL::ASN1::ASN1Data asn) -> oid_value
21
+
22
+ private
23
+
24
+ def initialize: (oid, ?value: varbind_value, ?type: oid_type) -> untyped
25
+
26
+ def unpack_32bit_integer: (String) -> Integer
27
+
28
+ def unpack_64bit_integer: (String) -> Integer
29
+ end
30
+ end
@@ -3,11 +3,11 @@
3
3
  require_relative "support/request_examples"
4
4
 
5
5
  RSpec.describe NETSNMP::Client do
6
- let(:host) { "localhost" }
6
+ let(:host) { SNMPHOST }
7
7
 
8
8
  let(:device_options) do
9
9
  {
10
- peername: "localhost",
10
+ peername: SNMPHOST,
11
11
  port: SNMPPORT
12
12
  }
13
13
  end
@@ -31,14 +31,15 @@ RSpec.describe "with cellulloid", type: :celluloid do
31
31
  WALK
32
32
  end
33
33
 
34
+ before(:all) { Celluloid.boot }
34
35
  around(:each) do |example|
35
36
  within_io_actor { example.run }
36
37
  end
37
- let(:proxy) { CelluloidHelpers::Proxy.new("localhost", SNMPPORT) }
38
+ let(:proxy) { CelluloidHelpers::Proxy.new(SNMPHOST, SNMPPORT) }
38
39
  after(:each) { proxy.close }
39
40
 
40
41
  it_behaves_like "an snmp client" do
41
- subject { NETSNMP::Client.new(options) }
42
+ subject { NETSNMP::Client.new(**options) }
42
43
  let(:device_options) { { proxy: proxy } }
43
44
  let(:protocol_options) { user_options }
44
45
  let(:extra_options) { { version: 3, context: "a172334d7d97871b72241397f713fa12" } }
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe NETSNMP::Session do
4
- let(:host) { "localhost" }
4
+ let(:host) { SNMPHOST }
5
5
  let(:options) do
6
6
  {
7
7
  version: "2c",
@@ -9,6 +9,6 @@ RSpec.describe NETSNMP::Session do
9
9
  port: SNMPPORT
10
10
  }
11
11
  end
12
- subject { described_class.new(host, options) }
12
+ subject { described_class.new(host: host, **options) }
13
13
  after { subject.close }
14
14
  end
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "simplecov" if ENV["COVERAGE"]
4
- require "coveralls"
5
- Coveralls.wear!
3
+ if ENV.key?("CI")
4
+ require "simplecov"
5
+ SimpleCov.command_name "#{RUBY_ENGINE}-#{RUBY_VERSION}"
6
+ SimpleCov.coverage_dir "coverage/#{RUBY_ENGINE}-#{RUBY_VERSION}"
7
+ end
6
8
 
7
9
  if defined?(SimpleCov)
8
10
  SimpleCov.start do
@@ -17,7 +19,8 @@ Bundler.require(:default, :test)
17
19
 
18
20
  require "netsnmp"
19
21
 
20
- SNMPPORT = (ENV["SNMP_PORT"] || 1161).to_i
22
+ SNMPPORT = ENV.fetch("SNMP_PORT", 1161).to_i
23
+ SNMPHOST = ENV.fetch("SNMP_HOST", "localhost")
21
24
 
22
25
  # This file was generated by the `rspec --init` command. Conventionally, all
23
26
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
@@ -3,7 +3,7 @@
3
3
  RSpec.shared_examples "an snmp client" do
4
4
  let(:device_options) do
5
5
  {
6
- host: "localhost",
6
+ host: SNMPHOST,
7
7
  port: SNMPPORT
8
8
  }
9
9
  end
@@ -11,7 +11,7 @@ RSpec.shared_examples "an snmp client" do
11
11
  let(:extra_options) { {} }
12
12
  let(:options) { protocol_options.merge(device_options).merge(extra_options) }
13
13
 
14
- subject { described_class.new(options) }
14
+ subject { described_class.new(**options) }
15
15
 
16
16
  describe "#get" do
17
17
  let(:value) { subject.get(oid: get_oid) }
@@ -7,19 +7,19 @@ RSpec.describe NETSNMP::V3Session do
7
7
  priv_protocol: :des, security_level: :auth_priv }
8
8
  end
9
9
  it "generates the security parameters handler" do
10
- sess = described_class.new(security_options.merge(host: "localhost", port: SNMPPORT))
10
+ sess = described_class.new(**security_options.merge(host: SNMPHOST, port: SNMPPORT))
11
11
  # not generated yet
12
12
  expect(sess.instance_variable_get(:@security_parameters)).to be_a(NETSNMP::SecurityParameters)
13
13
  end
14
14
 
15
15
  it "allows to pass a custom one" do
16
- sec_params = NETSNMP::SecurityParameters.new(security_options)
17
- sess = described_class.new(host: "localhost", port: SNMPPORT, security_parameters: sec_params)
16
+ sec_params = NETSNMP::SecurityParameters.new(**security_options)
17
+ sess = described_class.new(host: SNMPHOST, port: SNMPPORT, security_parameters: sec_params)
18
18
  # not generated yet
19
19
  expect(sess.instance_variable_get(:@security_parameters)).to be(sec_params)
20
20
  end
21
21
 
22
22
  it "fails if the pass object doesn't follow the expected api" do
23
- expect { described_class.new(host: "localhost", port: SNMPPORT, security_parameters: double) }.to raise_error(NETSNMP::Error)
23
+ expect { described_class.new(host: SNMPHOST, port: SNMPPORT, security_parameters: double) }.to raise_error(NETSNMP::Error)
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,75 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: netsnmp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-29 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: rake
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: 10.1.0
20
- - - "~>"
21
- - !ruby/object:Gem::Version
22
- version: '10.1'
23
- type: :development
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- version: 10.1.0
30
- - - "~>"
31
- - !ruby/object:Gem::Version
32
- version: '10.1'
33
- - !ruby/object:Gem::Dependency
34
- name: rspec
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: 3.5.0
40
- - - "~>"
41
- - !ruby/object:Gem::Version
42
- version: '3.5'
43
- type: :development
44
- prerelease: false
45
- version_requirements: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 3.5.0
50
- - - "~>"
51
- - !ruby/object:Gem::Version
52
- version: '3.5'
53
- - !ruby/object:Gem::Dependency
54
- name: celluloid-io
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - "~>"
58
- - !ruby/object:Gem::Version
59
- version: '0.17'
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: 0.17.2
63
- type: :development
64
- prerelease: false
65
- version_requirements: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - "~>"
68
- - !ruby/object:Gem::Version
69
- version: '0.17'
70
- - - ">="
71
- - !ruby/object:Gem::Version
72
- version: 0.17.2
11
+ date: 2020-12-18 00:00:00.000000000 Z
12
+ dependencies: []
73
13
  description: |2
74
14
  Wraps the net-snmp core usage into idiomatic ruby.
75
15
  It is designed to support as many environments and concurrency frameworks as possible.
@@ -78,17 +18,9 @@ executables: []
78
18
  extensions: []
79
19
  extra_rdoc_files: []
80
20
  files:
81
- - ".coveralls.yml"
82
- - ".gitignore"
83
- - ".rspec"
84
- - ".rubocop.yml"
85
- - ".rubocop_todo.yml"
86
- - ".travis.yml"
87
21
  - AUTHORS
88
- - Gemfile
89
22
  - LICENSE.txt
90
23
  - README.md
91
- - Rakefile
92
24
  - lib/netsnmp.rb
93
25
  - lib/netsnmp/client.rb
94
26
  - lib/netsnmp/encryption/aes.rb
@@ -105,7 +37,18 @@ files:
105
37
  - lib/netsnmp/v3_session.rb
106
38
  - lib/netsnmp/varbind.rb
107
39
  - lib/netsnmp/version.rb
108
- - netsnmp.gemspec
40
+ - sig/client.rbs
41
+ - sig/message.rbs
42
+ - sig/netsnmp.rbs
43
+ - sig/oid.rbs
44
+ - sig/openssl.rbs
45
+ - sig/pdu.rbs
46
+ - sig/scoped_pdu.rbs
47
+ - sig/security_parameters.rbs
48
+ - sig/session.rbs
49
+ - sig/timeticks.rbs
50
+ - sig/v3_session.rbs
51
+ - sig/varbind.rbs
109
52
  - spec/client_spec.rb
110
53
  - spec/handlers/celluloid_spec.rb
111
54
  - spec/oid_spec.rb
@@ -113,11 +56,8 @@ files:
113
56
  - spec/security_parameters_spec.rb
114
57
  - spec/session_spec.rb
115
58
  - spec/spec_helper.rb
116
- - spec/support/Dockerfile
117
59
  - spec/support/celluloid.rb
118
60
  - spec/support/request_examples.rb
119
- - spec/support/specs.sh
120
- - spec/support/stop_docker.sh
121
61
  - spec/timeticks_spec.rb
122
62
  - spec/v3_session_spec.rb
123
63
  - spec/varbind_spec.rb
@@ -126,7 +66,7 @@ licenses:
126
66
  - Apache-2.0
127
67
  metadata:
128
68
  allowed_push_host: https://rubygems.org/
129
- post_install_message:
69
+ post_install_message:
130
70
  rdoc_options: []
131
71
  require_paths:
132
72
  - lib
@@ -142,23 +82,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
82
  version: '0'
143
83
  requirements:
144
84
  - net-snmp
145
- rubygems_version: 3.0.6
146
- signing_key:
85
+ rubygems_version: 3.1.4
86
+ signing_key:
147
87
  specification_version: 4
148
88
  summary: SNMP Client library
149
89
  test_files:
90
+ - spec/timeticks_spec.rb
91
+ - spec/spec_helper.rb
92
+ - spec/session_spec.rb
150
93
  - spec/client_spec.rb
151
- - spec/handlers/celluloid_spec.rb
152
94
  - spec/oid_spec.rb
95
+ - spec/varbind_spec.rb
96
+ - spec/support/request_examples.rb
97
+ - spec/support/celluloid.rb
153
98
  - spec/pdu_spec.rb
154
99
  - spec/security_parameters_spec.rb
155
- - spec/session_spec.rb
156
- - spec/spec_helper.rb
157
- - spec/support/Dockerfile
158
- - spec/support/celluloid.rb
159
- - spec/support/request_examples.rb
160
- - spec/support/specs.sh
161
- - spec/support/stop_docker.sh
162
- - spec/timeticks_spec.rb
163
100
  - spec/v3_session_spec.rb
164
- - spec/varbind_spec.rb
101
+ - spec/handlers/celluloid_spec.rb
@@ -1 +0,0 @@
1
- service_name: travis-ci
data/.gitignore DELETED
@@ -1,14 +0,0 @@
1
- /coverage/
2
- /doc/
3
- /pkg/
4
- /tmp/
5
- /log/
6
- /.yardoc/
7
- /.bundle
8
- /Gemfile.lock
9
- /vendor
10
- .env
11
-
12
- *.DS_Store
13
- *.sw[po]
14
- *.nfs*
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --color
2
- --require spec_helper
3
- --format documentation
@@ -1,11 +0,0 @@
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
@@ -1,69 +0,0 @@
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: 100
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: 50
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
@@ -1,28 +0,0 @@
1
- sudo: required
2
- services:
3
- - docker
4
-
5
- install:
6
- - gem i rubygems-update -v '<3' && update_rubygems
7
- - bundle install --path .bundle
8
-
9
- script:
10
- - spec/support/specs.sh run
11
-
12
- language: ruby
13
- rvm:
14
- - 2.1
15
- - 2.2
16
- - 2.3
17
- - 2.4
18
- - 2.5
19
- - 2.6
20
- - ruby-head
21
- - jruby-head
22
- - truffleruby
23
- matrix:
24
- allow_failures:
25
- - rvm: ruby-head
26
- - rvm: jruby-head
27
- # to figure out later
28
- - rvm: truffleruby
data/Gemfile DELETED
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source "https://rubygems.org/"
4
- ruby RUBY_VERSION
5
-
6
- gemspec
7
-
8
- gem "coveralls", require: false
9
-
10
- group :development do
11
- gem "pry"
12
- end
13
-
14
- gem "nio4r", "~> 1.2" if RUBY_VERSION < "2.2"
15
-
16
- platforms :mri do
17
- gem "pry-byebug", require: false
18
- gem "stackprof", require: false
19
- gem "xorcist", require: false
20
- end
21
-
22
- gem "rubocop", "0.52.1", require: false
data/Rakefile DELETED
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
5
- require "coveralls/rake/task"
6
- require "rubocop/rake_task"
7
-
8
- desc "runs the tests and sends to coveralls server"
9
- Coveralls::RakeTask.new
10
-
11
- desc "runs the tests"
12
- RSpec::Core::RakeTask.new
13
-
14
- desc "Run rubocop"
15
- task :rubocop do
16
- RuboCop::RakeTask.new
17
- end
18
-
19
- task default: [:spec]
20
-
21
- namespace :spec do
22
- desc "runs the tests in coverage mode"
23
- task :coverage do
24
- ENV["COVERAGE"] = "true"
25
- Rake::Task["spec"].execute
26
- end
27
-
28
- desc "runs tests, check coverage, pushes to coverage server"
29
- task ci: ["spec:coverage", "coveralls:push", "rubocop"]
30
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require File.expand_path("../lib/netsnmp/version", __FILE__)
4
-
5
- Gem::Specification.new do |gem|
6
- gem.name = "netsnmp"
7
- gem.summary = "SNMP Client library"
8
- gem.description = <<-DESC
9
- Wraps the net-snmp core usage into idiomatic ruby.
10
- It is designed to support as many environments and concurrency frameworks as possible.
11
- DESC
12
- gem.requirements = ["net-snmp"]
13
- gem.version = NETSNMP::VERSION
14
- gem.license = "Apache-2.0"
15
- gem.authors = ["Tiago Cardoso"]
16
- gem.email = "cardoso_tiago@hotmail.com"
17
- gem.homepage = ""
18
- gem.platform = Gem::Platform::RUBY
19
- gem.metadata["allowed_push_host"] = "https://rubygems.org/"
20
-
21
- # Manifest
22
- gem.files = `git ls-files`.split("\n") - Dir["tmp/**/*"]
23
- gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
- gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
25
- gem.require_paths = ["lib"]
26
-
27
- gem.add_development_dependency "rake", ["~> 10.1", ">= 10.1.0"]
28
- gem.add_development_dependency "rspec", ["~> 3.5", ">= 3.5.0"]
29
-
30
- gem.add_development_dependency "celluloid-io", ["~> 0.17", ">= 0.17.2"]
31
- end
@@ -1,14 +0,0 @@
1
- FROM python:2.7-alpine
2
- Maintainer Tiago Cardoso <cardoso_tiago@hotmail.com>
3
-
4
- RUN easy_install snmpsim==0.3.0
5
- RUN easy_install pycrypto==2.6.1
6
- EXPOSE 1161
7
- # Create non-privileged user
8
- RUN useradd -m snmp_server
9
-
10
-
11
- USER snmp_server
12
- ENTRYPOINT ["/usr/local/bin/snmpsimd.py"]
13
-
14
- CMD ["--help"]
@@ -1,51 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- function start {
4
- docker pull honeyryderchuck/snmp-server-emulator:latest
5
- docker run -d -p :1161/udp --name test-snmp -v $(pwd)/spec/support/snmpsim:/home/snmp_server/.snmpsim honeyryderchuck/snmp-server-emulator \
6
- --v3-engine-id=000000000000000000000002 \
7
- --agent-udpv4-endpoint=0.0.0.0:1161 --agent-udpv6-endpoint='[::0]:1161' \
8
- --v3-user=simulator --v3-auth-key=auctoritas --v3-priv-key=privatus \
9
- --v3-user=authmd5 --v3-auth-key=maplesyrup --v3-auth-proto=MD5 --v3-priv-proto=NONE \
10
- --v3-user=authsha --v3-auth-key=maplesyrup --v3-auth-proto=SHA --v3-priv-proto=NONE \
11
- --v3-user=authprivshaaes --v3-auth-key=maplesyrup --v3-auth-proto=SHA \
12
- --v3-priv-key=maplesyrup --v3-priv-proto=AES \
13
- --v3-user=authprivmd5aes --v3-auth-key=maplesyrup --v3-auth-proto=MD5 \
14
- --v3-priv-key=maplesyrup --v3-priv-proto=AES \
15
- --v3-user=authprivshades --v3-auth-key=maplesyrup --v3-auth-proto=SHA \
16
- --v3-priv-key=maplesyrup --v3-priv-proto=DES \
17
- --v3-user=authprivmd5des --v3-auth-key=maplesyrup --v3-auth-proto=MD5 \
18
- --v3-priv-key=maplesyrup --v3-priv-proto=DES \
19
- --v3-user=unsafe --v3-auth-proto=NONE --v3-priv-proto=NONE
20
-
21
- }
22
-
23
- function run {
24
- sleep 20 # give some time for the simulator to boot
25
-
26
- port="$(docker port test-snmp 1161/udp)"
27
- export SNMP_PORT=$(echo $port | cut -d':' -f2)
28
-
29
- bundle exec rake spec:ci
30
- }
31
-
32
- function finish {
33
- docker stop test-snmp
34
- docker rm test-snmp
35
- }
36
-
37
- trap finish EXIT
38
-
39
- case "$1" in
40
- start)
41
- start
42
- docker logs -f test-snmp
43
- ;;
44
- run)
45
- start
46
- run
47
- ;;
48
- *)
49
- echo $"Usage: $0 {start|run}"
50
- exit 1
51
- esac
@@ -1,5 +0,0 @@
1
- sudo docker stop test-snmp-emulator
2
- sudo docker rm test-snmp-emulator
3
- sudo docker rmi snmp-server-emulator
4
-
5
-