snmp-open 0.6.0 → 0.7.1

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
2
  SHA256:
3
- metadata.gz: 1362f32d8e43b509be4884b392c43689b9cba48c2e2d6f63c4912e645ba6fcc9
4
- data.tar.gz: d751cce9e00204ae0b0d131120338ce3b7beaf1bbfb2e71f114c60f8c9bfdfa8
3
+ metadata.gz: 0c647ac12c0055f8f71908c27d5460e3b220d2c265751987d7a08ac1b1179efa
4
+ data.tar.gz: 74dfcf665582e2d23f093a6e67b83e9def03c1b8939d9772b7a645e884f95dbe
5
5
  SHA512:
6
- metadata.gz: 51603c2ee2b8d5077be2dcc8f26b74ad174d09a31fe6b6879343d98b33bba5f30f6246cf2ac3999f3a3aa46fda3b5cf7f849310016de5725cbdd0574741af99c
7
- data.tar.gz: 2670576c9373c22e74e5bc7a118317ffdefb33d685ef654236e1ec5f369f9ac772d619ff7cfba3e8532ba52a5fc3b0d52bc67439cbeb96d84a08d6cc36f40819
6
+ metadata.gz: d8bd115d0a86d384dc860191bbb045e4903ab739ef1581041b6e030134345a60a3481a4f75554ddaf527587db8e72d0b544949590638606fabe0ea2ada23a77d
7
+ data.tar.gz: d505743d70310b076a783e1cdad8ab95a1a5776c6e8f5caf467c827791216896d76db3baf5fc9c4ca25519de6bf6336a7c6e27c3bff308e8eb65235c68ecf597
@@ -12,7 +12,7 @@ jobs:
12
12
  fail-fast: false
13
13
  matrix:
14
14
  os: [ubuntu-latest, macos-latest]
15
- ruby: [2.4, 2.5, 2.6, 2.7, jruby, truffleruby]
15
+ ruby: [2.4, 2.5, 2.6, 2.7, jruby]
16
16
  runs-on: ${{ matrix.os }}
17
17
  steps:
18
18
  - uses: actions/checkout@v2
data/.rubocop.yml CHANGED
@@ -1,2 +1,62 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.4
3
+
1
4
  Style/CommentedKeyword:
2
5
  Enabled: false
6
+
7
+ Lint/MissingSuper:
8
+ Exclude:
9
+ - 'lib/snmp/open/parser/value_parser.rb'
10
+
11
+ Metrics/ClassLength:
12
+ Exclude:
13
+ - 'lib/snmp/open/parser.rb'
14
+
15
+ Style/AccessModifierDeclarations: {Enabled: false}
16
+ Style/IfUnlessModifier: {Enabled: false}
17
+ Style/FrozenStringLiteralComment: {Enabled: false}
18
+
19
+ Layout/SpaceBeforeBrackets: # (new in 1.7)
20
+ Enabled: true
21
+ Lint/AmbiguousAssignment: # (new in 1.7)
22
+ Enabled: true
23
+ Lint/DeprecatedConstants: # (new in 1.8)
24
+ Enabled: true
25
+ Lint/DuplicateBranch: # (new in 1.3)
26
+ Enabled: true
27
+ Lint/DuplicateRegexpCharacterClassElement: # (new in 1.1)
28
+ Enabled: true
29
+ Lint/EmptyBlock: # (new in 1.1)
30
+ Enabled: true
31
+ Lint/EmptyClass: # (new in 1.3)
32
+ Enabled: true
33
+ Lint/LambdaWithoutLiteralBlock: # (new in 1.8)
34
+ Enabled: true
35
+ Lint/NoReturnInBeginEndBlocks: # (new in 1.2)
36
+ Enabled: true
37
+ Lint/RedundantDirGlobSort: # (new in 1.8)
38
+ Enabled: true
39
+ Lint/ToEnumArguments: # (new in 1.1)
40
+ Enabled: true
41
+ Lint/UnexpectedBlockArity: # (new in 1.5)
42
+ Enabled: true
43
+ Lint/UnmodifiedReduceAccumulator: # (new in 1.1)
44
+ Enabled: true
45
+ Style/ArgumentsForwarding: # (new in 1.1)
46
+ Enabled: true
47
+ Style/CollectionCompact: # (new in 1.2)
48
+ Enabled: true
49
+ Style/DocumentDynamicEvalDefinition: # (new in 1.1)
50
+ Enabled: true
51
+ Style/EndlessMethod: # (new in 1.8)
52
+ Enabled: true
53
+ Style/HashExcept: # (new in 1.7)
54
+ Enabled: true
55
+ Style/NegatedIfElseCondition: # (new in 1.2)
56
+ Enabled: true
57
+ Style/NilLambda: # (new in 1.3)
58
+ Enabled: true
59
+ Style/RedundantArgument: # (new in 1.4)
60
+ Enabled: true
61
+ Style/SwapValues: # (new in 1.1)
62
+ Enabled: true
data/Gemfile CHANGED
@@ -5,4 +5,5 @@ group :guard do
5
5
  gem 'guard'
6
6
  gem 'guard-rspec'
7
7
  gem 'guard-rubocop'
8
+ gem 'rubocop', '~>1.0'
8
9
  end
@@ -121,8 +121,11 @@ module SNMP
121
121
  end # class CommandReader
122
122
 
123
123
  class CommandError < RuntimeError; end
124
+
124
125
  class CommandTimeoutError < CommandError; end
126
+
125
127
  class UnknownMIBError < CommandError; end
128
+
126
129
  class UnknownOIDError < CommandError; end
127
130
  end # class Open
128
131
  end # module SNMP
@@ -32,12 +32,12 @@ module SNMP
32
32
  mkdir(@directory, cmd.to_s) if @make_directories
33
33
  outfile = File.join(@directory, cmd.to_s, oid)
34
34
  File.read(outfile)
35
- rescue Errno::ENOENT => err
35
+ rescue Errno::ENOENT => e
36
36
  if @warnings
37
37
  warning = @warnings.call(@command_generator, cmd, oid, outfile)
38
38
  warn warning
39
39
  end
40
- raise err
40
+ raise e
41
41
  end
42
42
 
43
43
  def mkdir(base, cmd)
@@ -12,8 +12,10 @@ module SNMP
12
12
  'snmpbulkwalk' => '-Cc',
13
13
  'snmpwalk' => '-Cc'
14
14
  },
15
+ no_mib_name: '-Os',
15
16
  no_units: '-OU',
16
17
  non_symbolic: '-Oe',
18
+ non_symbolic_table_indexes: '-Ob',
17
19
  numeric: '-On',
18
20
  priv_password: '-X', # not recommended, see snmp.conf(5)
19
21
  priv_protocol: '-x',
@@ -24,9 +26,11 @@ module SNMP
24
26
  host: nil
25
27
  }.freeze
26
28
 
27
- # On some systems, SNMP command outputs will include symbolic values
28
- # and/or value units. The parser doesn't support these, so disable them.
29
+ # On some systems, SNMP command outputs will include symbolic values,
30
+ # table indexes, and/or value units. The parser doesn't support these, so
31
+ # disable them.
29
32
  REQUIRED_BY_PARSER = {
33
+ '-Ob' => nil,
30
34
  '-Oe' => nil,
31
35
  '-OU' => nil
32
36
  }.freeze
@@ -23,9 +23,11 @@ module SNMP
23
23
  class Bits < ValueParser
24
24
  def parse(tokens)
25
25
  return @parse if @parse
26
+
26
27
  bytes = []
27
28
  loop do
28
29
  break unless tokens.peek =~ /\A[0-9A-Za-z]{1,2}\z/
30
+
29
31
  bytes << tokens.next.to_i(16)
30
32
  end
31
33
  @parse = [@type, bytes]
@@ -50,9 +52,11 @@ module SNMP
50
52
  class HexString < ValueParser
51
53
  def parse(tokens)
52
54
  return @parse if @parse
55
+
53
56
  bytes = []
54
57
  loop do
55
58
  break unless tokens.peek =~ /\A[0-9A-Za-z]{2}\z/
59
+
56
60
  bytes << tokens.next
57
61
  end
58
62
  string = bytes.map { |b| b.to_i(16).chr }.join
@@ -72,6 +76,7 @@ module SNMP
72
76
  class Timeticks < ValueParser
73
77
  def parse(tokens)
74
78
  return @parse if @parse
79
+
75
80
  ticks = tokens.next.tr('()', '').to_i
76
81
 
77
82
  # consume tokens through one like 23:59:59.99
@@ -106,16 +111,16 @@ module SNMP
106
111
 
107
112
  KNOWN_TOKENS = {
108
113
  NOSUCHINSTANCE_STR => NoSuchInstance,
109
- NOSUCHOBJECT_STR => NoSuchObject,
114
+ NOSUCHOBJECT_STR => NoSuchObject,
110
115
  NOMOREVARIABLES_STR => Stop
111
116
  }.freeze
112
117
 
113
118
  KNOWN_TYPES = {
114
119
  nil => Default,
115
120
  'BITS' => Bits,
116
- 'INTEGER' => ValueParser::Integer,
117
- 'Gauge32' => ValueParser::Integer,
118
- 'Gauge64' => ValueParser::Integer,
121
+ 'INTEGER' => ValueParser::Integer,
122
+ 'Gauge32' => ValueParser::Integer,
123
+ 'Gauge64' => ValueParser::Integer,
119
124
  'Counter32' => ValueParser::Integer,
120
125
  'Counter64' => ValueParser::Integer,
121
126
  'Hex-STRING' => HexString,
@@ -14,7 +14,37 @@ module SNMP
14
14
  # convert SNMP command output into arrays
15
15
  class Parser
16
16
  include SNMP::Open::Parser::Constants
17
- OID_RE = Regexp.union(/\S+-MIB::\S+/, /[0-9\.]+/)
17
+ OID_RE = Regexp.union(/\S+-MIB::\S+/, /[0-9.]+/)
18
+
19
+ EMPTY_STRING_RE =
20
+ /^(#{OID_RE}) # capture group 1: OID
21
+ \s+=\s+
22
+ (Opaque|STRING) # capture group 2: Type
23
+ :\s*\n # value is always empty string
24
+ /x.freeze
25
+
26
+ STRING_RE =
27
+ /^(#{OID_RE}) # capture group 1: OID
28
+ \s+=\s+
29
+ (Opaque|STRING):\s+ # capture group 2: Type
30
+
31
+ ( # capture group 3: Value
32
+
33
+ (?!") # this pattern is for finding strings in need of
34
+ # quoting, so reject any strings that are already
35
+ # quoted
36
+
37
+ [^\n]* # first line of value
38
+
39
+ (\n # newline before each additional line of value
40
+ (?!
41
+ #{OID_RE} # additional lines of value are identified by not
42
+ \s+=\s+ # starting with "<OID> ="
43
+ )
44
+ [^\n]+ # additional lines of value
45
+ )*
46
+ )\n
47
+ /x.freeze
18
48
 
19
49
  def initialize(oids)
20
50
  @oids = oids
@@ -33,37 +63,34 @@ module SNMP
33
63
  private
34
64
 
35
65
  def align(columns)
36
- indexes = columns.first.map { |value| index_using_first_oid(value) }
66
+ indexes = indexes_from_columns(columns)
67
+ bases = bases_from_columns(columns)
37
68
  hash = columns.flat_map { |row| row.map { |v| [v.oid, v] } }.to_h
38
69
 
39
70
  indexes.map do |index|
40
- @oids.map do |base|
71
+ bases.map do |base, _|
41
72
  oid = [base, *index].join('.')
42
73
  hash.fetch(oid) { Value.new(oid, 'absent', nil) }
43
74
  end
44
75
  end
45
76
  end
46
77
 
78
+ def bases_from_columns(columns)
79
+ @oids
80
+ .zip(columns.map { |c| c&.first&.oid })
81
+ .map { |base, oid| base && oid && split_oid(base, oid) }
82
+ end
83
+
47
84
  def clean_input_text(text)
48
85
  text
49
86
  .gsub(/\r\n|\n\r|\r/, "\n")
50
- .gsub(/^(#{OID_RE})\s*=\s*(Opaque|STRING):\s*\n/,
51
- %(\\1 = \\2: ""\n))
52
- .gsub(/^(#{OID_RE}) = (Opaque|STRING): ((?!")[^\n]*)\n/,
53
- %(\\1 = \\2: "\\3"\n))
87
+ .gsub(EMPTY_STRING_RE, %(\\1 = \\2: ""\n))
88
+ .gsub(STRING_RE, %(\\1 = \\2: "\\3"\n))
54
89
  .gsub(Static::ANY_MESSAGE, Static::QUOTED_MESSAGES)
55
90
  end
56
91
 
57
- def index_using_first_oid(value)
58
- base = @oids.first
59
-
60
- if base == value.oid
61
- nil
62
- elsif value.oid.start_with?(base)
63
- value.oid.gsub(/\A#{base}\.?/, '')
64
- else
65
- raise "Received ID doesn't start with the given ID"
66
- end
92
+ def indexes_from_columns(columns)
93
+ columns.first.map { |value| split_oid(@oids.first, value.oid)[1] }
67
94
  end
68
95
 
69
96
  def parse_tokens(tokens)
@@ -82,8 +109,10 @@ module SNMP
82
109
  def parse_next_object(tokens)
83
110
  oid = tokens.next.sub(/\A\./, '')
84
111
  raise "Parse error at #{oid}" unless oid =~ OID_RE
112
+
85
113
  equals = tokens.next
86
114
  raise "Parse error after #{oid}" unless equals == '='
115
+
87
116
  type, value = parse_type(tokens)
88
117
  Value.new(oid, type, value)
89
118
  end
@@ -94,6 +123,21 @@ module SNMP
94
123
  ValueParser.find(type, token).parse(tokens)
95
124
  end
96
125
 
126
+ # split a complete OID into a base and index, given an expected base
127
+ # raises if the base isn't present
128
+ def split_oid(base, oid)
129
+ if base == oid
130
+ [base, nil]
131
+ elsif oid.start_with?(base)
132
+ [base, oid.sub(/\A#{base}\.?/, '')]
133
+ elsif base.include?('::') && !oid.include?('::')
134
+ alternate_base = base.sub(/\A[^:]+::/, '')
135
+ split_oid(alternate_base, oid)
136
+ else
137
+ raise "Received ID doesn't start with the given ID"
138
+ end
139
+ end
140
+
97
141
  def table(columns)
98
142
  if columns.size == 1 && columns.all? { |column| column.size == 1 }
99
143
  columns
@@ -1,5 +1,5 @@
1
1
  module SNMP
2
2
  class Open
3
- VERSION = '0.6.0'.freeze
3
+ VERSION = '0.7.1'.freeze
4
4
  end
5
5
  end
data/lib/snmp/open.rb CHANGED
@@ -27,16 +27,18 @@ module SNMP
27
27
  end
28
28
 
29
29
  # Perform an SNMP get using the "snmpget" command and parse the output
30
- def get(oids)
30
+ def get(oids, &block)
31
31
  return enum_for(:get, oids) unless block_given?
32
+
32
33
  texts = oids.map { |oid| reader.capture(:get, oid) }
33
- Parser.new(oids).parse(texts).fetch(0, []).each { |arg| yield(arg) }
34
+ Parser.new(oids).parse(texts).fetch(0, []).each(&block)
34
35
  end
35
36
 
36
37
  # Perform an SNMP walk using the "snmpwalk" or "snmpbulkwalk" commands and
37
38
  # parse the output
38
39
  def walk(oids, **kwargs)
39
40
  return enum_for(:walk, oids, **kwargs) unless block_given?
41
+
40
42
  bulk = kwargs.fetch(:bulk, true)
41
43
  options = walk_options(bulk, **kwargs)
42
44
  cmd = bulk ? :bulkwalk : :walk
data/snmp-open.gemspec CHANGED
@@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ['lib']
20
20
 
21
+ spec.required_ruby_version = '~> 2.4'
22
+
21
23
  spec.add_development_dependency 'bundler', '~> 2.2'
22
24
  spec.add_development_dependency 'rake', '~> 13.0'
23
25
  spec.add_development_dependency 'rspec', '~> 3.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snmp-open
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Miller
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-16 00:00:00.000000000 Z
11
+ date: 2022-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -105,16 +105,17 @@ require_paths:
105
105
  - lib
106
106
  required_ruby_version: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: '2.4'
111
111
  required_rubygems_version: !ruby/object:Gem::Requirement
112
112
  requirements:
113
113
  - - ">="
114
114
  - !ruby/object:Gem::Version
115
115
  version: '0'
116
116
  requirements: []
117
- rubygems_version: 3.1.2
117
+ rubyforge_project:
118
+ rubygems_version: 2.7.6.2
118
119
  signing_key:
119
120
  specification_version: 4
120
121
  summary: Wrapper for command-line SNMP utilities