snmp-open 0.6.0 → 0.7.1
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 +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/.rubocop.yml +60 -0
- data/Gemfile +1 -0
- data/lib/snmp/open/command_reader.rb +3 -0
- data/lib/snmp/open/file_reader.rb +2 -2
- data/lib/snmp/open/options.rb +6 -2
- data/lib/snmp/open/parser/value_parser.rb +9 -4
- data/lib/snmp/open/parser.rb +61 -17
- data/lib/snmp/open/version.rb +1 -1
- data/lib/snmp/open.rb +4 -2
- data/snmp-open.gemspec +2 -0
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c647ac12c0055f8f71908c27d5460e3b220d2c265751987d7a08ac1b1179efa
|
4
|
+
data.tar.gz: 74dfcf665582e2d23f093a6e67b83e9def03c1b8939d9772b7a645e884f95dbe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8bd115d0a86d384dc860191bbb045e4903ab739ef1581041b6e030134345a60a3481a4f75554ddaf527587db8e72d0b544949590638606fabe0ea2ada23a77d
|
7
|
+
data.tar.gz: d505743d70310b076a783e1cdad8ab95a1a5776c6e8f5caf467c827791216896d76db3baf5fc9c4ca25519de6bf6336a7c6e27c3bff308e8eb65235c68ecf597
|
data/.github/workflows/ruby.yml
CHANGED
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
@@ -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 =>
|
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
|
40
|
+
raise e
|
41
41
|
end
|
42
42
|
|
43
43
|
def mkdir(base, cmd)
|
data/lib/snmp/open/options.rb
CHANGED
@@ -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
|
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 =>
|
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'
|
117
|
-
'Gauge32'
|
118
|
-
'Gauge64'
|
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,
|
data/lib/snmp/open/parser.rb
CHANGED
@@ -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
|
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
|
-
|
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(
|
51
|
-
|
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
|
58
|
-
|
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
|
data/lib/snmp/open/version.rb
CHANGED
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
|
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.
|
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:
|
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: '
|
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
|
-
|
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
|