snmp-open 0.3.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: '09dd63241e17dc715dc949d0b727f61e777cfade'
4
- data.tar.gz: a3bf4afbcb4debc166bbc04b0c67292d41a63a12
2
+ SHA256:
3
+ metadata.gz: 2778b6bac09136b98ff5bfcdf5313f470d8468d556353f4e5466479624291383
4
+ data.tar.gz: b2f2a13ad5ad75e79116e33e63f2462e768b5850887180e9b94e1ff369c17bac
5
5
  SHA512:
6
- metadata.gz: bdf0ce08cdc82f961165108a9ea267011cf65c84c34b9ff944d91650ea9ea13bdc413f83346115041b1e6797509a3bda4a823e34de8b02c912587d071b3856f4
7
- data.tar.gz: 402b3e552a7c41ffe6f33b48f8c62e42ab79a1775540068304579f3babcaf0309b7d17b8cb4a7b4c195ea0d35ba52d103259e37ec02c54ea6c4c04ea97d6eb8f
6
+ metadata.gz: f61f7cbd63437b97d260e8bee251cfe45ca02a706564de5ae293859c5ab8feb80c253fdd67ba0fe93fd78b1df49370adca9a12cecac6b545456efdeccf8f4553
7
+ data.tar.gz: 816aba2a56ded47b4dadbe0fee21e339bfa423bd76bc6a4e1a2e5979dfc2048fa62124c23447e4d7144d6da06f153b48b04ff3374b5647fd05d0d94a9e8d8ba7
@@ -0,0 +1,24 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ test:
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest]
15
+ ruby: [2.4, 2.5, 2.6, 2.7, jruby, truffleruby]
16
+ runs-on: ${{ matrix.os }}
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby }}
22
+ bundler-cache: true
23
+ - name: Run tests
24
+ run: bundle exec rake
@@ -0,0 +1,62 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.4
3
+
4
+ Style/CommentedKeyword:
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
@@ -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
@@ -1,39 +1,13 @@
1
1
  require 'open3'
2
+ require 'snmp/open/options'
2
3
 
3
4
  module SNMP
4
5
  class Open
5
6
  # Open3-based data source that executes an snmp* command and captures the
6
7
  # output
7
8
  class CommandReader
8
- # see snmpcmd(1) for explanation of options
9
- OPTIONS = {
10
- version: '-v',
11
- auth_password: '-A',
12
- auth_protocol: '-a',
13
- community: '-c',
14
- context: '-n',
15
- no_check_increasing: {
16
- 'snmpbulkwalk' => '-Cc',
17
- 'snmpwalk' => '-Cc'
18
- },
19
- numeric: '-On', # needed by parser, should always be enabled
20
- priv_password: '-X', # not recommended, see snmp.conf(5)
21
- priv_protocol: '-x',
22
- sec_level: '-l',
23
- sec_user: '-u',
24
- retries: '-r',
25
- timeout: '-t',
26
- host: nil
27
- }.freeze
28
-
29
- OPTION_VALUES = {
30
- no_check_increasing: {
31
- true => ''
32
- }.freeze
33
- }.freeze
34
-
35
9
  # +options+ accepts options dealing with making connections to the host,
36
- # including all of the options listed in the +OPTIONS+ constant hash.
10
+ # including all of the options listed in the +Options::MAP+ constant hash.
37
11
  # Other options can be given as strings (or any object with a suitable
38
12
  # +to_s+ method), e.g., these are equivalent:
39
13
  #
@@ -44,7 +18,9 @@ module SNMP
44
18
  @env = options.delete(:env)
45
19
  host = options.delete(:host) ||
46
20
  (raise ArgumentError, 'Host expected but not given')
47
- opts = merge_options(options).merge('-On' => nil, host => nil)
21
+ opts = Options::REQUIRED_BY_PARSER
22
+ .merge(merge_options(options))
23
+ .merge(host => nil)
48
24
  @command_options, @host_options = partition_options(opts)
49
25
  end
50
26
 
@@ -54,8 +30,7 @@ module SNMP
54
30
  else
55
31
  Open3.capture3(cli(cmd, oid, options))
56
32
  end
57
- raise CommandTimeoutError, err.chomp if err =~ /^timeout/i
58
- raise CommandError, err.chomp unless err.empty?
33
+ raise_capture_errors(err)
59
34
  out
60
35
  end
61
36
 
@@ -66,6 +41,7 @@ module SNMP
66
41
  [
67
42
  command,
68
43
  *options.map { |k, v| "#{k}#{v}" },
44
+ *oid_options(id),
69
45
  *@host_options.map { |k, v| "#{k}#{v}" },
70
46
  *@command_options.fetch(command, {}).map { |k, v| "#{k}#{v}" },
71
47
  *id
@@ -74,11 +50,24 @@ module SNMP
74
50
 
75
51
  private
76
52
 
53
+ def raise_capture_errors(err)
54
+ case err
55
+ when /^Cannot find module \(([^)]+)\)/
56
+ raise UnknownMIBError, "Unknown MIB: #{Regexp.last_match(1)}"
57
+ when /^(\S+): Unknown Object Identifier$/
58
+ raise UnknownOIDError, "Unknown OID: #{Regexp.last_match(1)}"
59
+ when /^timeout/i
60
+ raise CommandTimeoutError, err.chomp
61
+ when /./
62
+ raise CommandError, err.chomp
63
+ end
64
+ end
65
+
77
66
  def merge_options(options = {})
78
67
  options.each_pair.with_object({}) do |(key, value), opts|
79
- if OPTIONS.key?(key)
80
- opts[OPTIONS[key]] =
81
- (OPTION_VALUES.fetch(key, {}).fetch(value, value) || next)
68
+ if Options::MAP.key?(key)
69
+ opts[Options::MAP[key]] =
70
+ (Options::VALUES.fetch(key, {}).fetch(value, value) || next)
82
71
  elsif key.is_a?(String)
83
72
  opts[key] = value
84
73
  else
@@ -87,6 +76,15 @@ module SNMP
87
76
  end
88
77
  end
89
78
 
79
+ # if the request OID is all-numeric, force numeric OID in the output
80
+ def oid_options(id)
81
+ if id =~ /[^0-9.]/
82
+ []
83
+ else
84
+ ['-On']
85
+ end
86
+ end
87
+
90
88
  def normalize_command(command)
91
89
  case command
92
90
  when Symbol then "snmp#{command}"
@@ -123,6 +121,11 @@ module SNMP
123
121
  end # class CommandReader
124
122
 
125
123
  class CommandError < RuntimeError; end
124
+
126
125
  class CommandTimeoutError < CommandError; end
126
+
127
+ class UnknownMIBError < CommandError; end
128
+
129
+ class UnknownOIDError < CommandError; end
127
130
  end # class Open
128
131
  end # module SNMP
@@ -13,19 +13,36 @@ module SNMP
13
13
  # be used to generate a needed file, if the file is unavailable. Controlled
14
14
  # by the `warnings` option.
15
15
  class FileReader
16
+ DEFAULT_WARNING_FORMATTER = lambda { |gen, cmd, oid, outfile|
17
+ "#{gen.cli(cmd, oid)} > #{outfile}"
18
+ }
19
+
16
20
  def initialize(directory, options = {})
17
21
  @directory = directory
18
22
  @warnings = options.delete(:warnings)
19
- @command_generator =
20
- SNMP::Open::CommandReader.new(options.merge(host: '$OPTIONS'))
23
+ @make_directories = options.delete(:make_directories)
24
+ if @warnings && !@warnings.respond_to?(:call)
25
+ @warnings = DEFAULT_WARNING_FORMATTER
26
+ end
27
+ options[:host] ||= '$OPTIONS'
28
+ @command_generator = SNMP::Open::CommandReader.new(options)
21
29
  end
22
30
 
23
31
  def capture(cmd, oid, _options = {})
24
- outfile = File.join(cmd.to_s, oid)
25
- File.read(File.join(@directory, outfile))
26
- rescue Errno::ENOENT => err
27
- warn "#{@command_generator.cli(cmd, oid)} > #{outfile}" if @warnings
28
- raise err
32
+ mkdir(@directory, cmd.to_s) if @make_directories
33
+ outfile = File.join(@directory, cmd.to_s, oid)
34
+ File.read(outfile)
35
+ rescue Errno::ENOENT => e
36
+ if @warnings
37
+ warning = @warnings.call(@command_generator, cmd, oid, outfile)
38
+ warn warning
39
+ end
40
+ raise e
41
+ end
42
+
43
+ def mkdir(base, cmd)
44
+ Dir.mkdir(base) unless File.exist?(base)
45
+ Dir.mkdir(File.join(base, cmd)) unless File.exist?(File.join(base, cmd))
29
46
  end
30
47
  end # class FileReader
31
48
  end # class Open
@@ -0,0 +1,41 @@
1
+ module SNMP
2
+ class Open
3
+ class Options
4
+ # see snmpcmd(1) for explanation of options
5
+ MAP = {
6
+ version: '-v',
7
+ auth_password: '-A',
8
+ auth_protocol: '-a',
9
+ community: '-c',
10
+ context: '-n',
11
+ no_check_increasing: {
12
+ 'snmpbulkwalk' => '-Cc',
13
+ 'snmpwalk' => '-Cc'
14
+ },
15
+ no_units: '-OU',
16
+ non_symbolic: '-Oe',
17
+ numeric: '-On',
18
+ priv_password: '-X', # not recommended, see snmp.conf(5)
19
+ priv_protocol: '-x',
20
+ sec_level: '-l',
21
+ sec_user: '-u',
22
+ retries: '-r',
23
+ timeout: '-t',
24
+ host: nil
25
+ }.freeze
26
+
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
+ REQUIRED_BY_PARSER = {
30
+ '-Oe' => nil,
31
+ '-OU' => nil
32
+ }.freeze
33
+
34
+ VALUES = {
35
+ no_check_increasing: {
36
+ true => ''
37
+ }.freeze
38
+ }.freeze
39
+ end # class Options
40
+ end # class Open
41
+ end # module SNMP
@@ -1,5 +1,7 @@
1
1
  require 'set'
2
2
  require 'shellwords'
3
+ require 'snmp/open/parser/constants'
4
+ require 'snmp/open/parser/value_parser'
3
5
 
4
6
  module SNMP
5
7
  class Open
@@ -11,10 +13,38 @@ module SNMP
11
13
 
12
14
  # convert SNMP command output into arrays
13
15
  class Parser
14
- NOSUCHOBJECT_STR =
15
- 'No Such Object available on this agent at this OID'.freeze
16
- NOSUCHINSTANCE_STR =
17
- 'No Such Instance currently exists at this OID'.freeze
16
+ include SNMP::Open::Parser::Constants
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
@@ -22,11 +52,8 @@ module SNMP
22
52
 
23
53
  def parse(texts)
24
54
  columns = texts.map do |text|
25
- tokenized =
26
- text
27
- .gsub(NOSUCHOBJECT_STR, %("#{NOSUCHOBJECT_STR}"))
28
- .gsub(NOSUCHINSTANCE_STR, %("#{NOSUCHINSTANCE_STR}"))
29
- .shellsplit
55
+ clean = clean_input_text(text)
56
+ tokenized = clean.shellsplit
30
57
  parse_tokens(tokenized)
31
58
  end
32
59
 
@@ -35,7 +62,7 @@ module SNMP
35
62
 
36
63
  private
37
64
 
38
- def table(columns)
65
+ def align(columns)
39
66
  indexes = columns.first.map { |value| index_using_first_oid(value) }
40
67
  hash = columns.flat_map { |row| row.map { |v| [v.oid, v] } }.to_h
41
68
 
@@ -47,6 +74,14 @@ module SNMP
47
74
  end
48
75
  end
49
76
 
77
+ def clean_input_text(text)
78
+ text
79
+ .gsub(/\r\n|\n\r|\r/, "\n")
80
+ .gsub(EMPTY_STRING_RE, %(\\1 = \\2: ""\n))
81
+ .gsub(STRING_RE, %(\\1 = \\2: "\\3"\n))
82
+ .gsub(Static::ANY_MESSAGE, Static::QUOTED_MESSAGES)
83
+ end
84
+
50
85
  def index_using_first_oid(value)
51
86
  base = @oids.first
52
87
 
@@ -69,34 +104,31 @@ module SNMP
69
104
 
70
105
  objects
71
106
  rescue StopIteration
72
- return objects
107
+ objects
73
108
  end
74
109
 
75
110
  def parse_next_object(tokens)
76
111
  oid = tokens.next.sub(/\A\./, '')
77
- raise "Parse error at #{oid}" unless oid =~ /\A[0-9.]+\z/
112
+ raise "Parse error at #{oid}" unless oid =~ OID_RE
113
+
78
114
  equals = tokens.next
79
115
  raise "Parse error after #{oid}" unless equals == '='
116
+
80
117
  type, value = parse_type(tokens)
81
118
  Value.new(oid, type, value)
82
119
  end
83
120
 
84
121
  def parse_type(tokens)
85
- next_token = tokens.next
86
- type = next_token.match(/\A([A-Z]+):\z/) { |md| md[1] }
87
- type, value = parse_value(tokens, next_token, type)
88
- [type, Conversions.convert_value(type, value)]
122
+ token = tokens.next
123
+ type = token.match(/\A([-A-Za-z]+[0-9]*):\z/) { |md| md[1] }
124
+ ValueParser.find(type, token).parse(tokens)
89
125
  end
90
126
 
91
- def parse_value(tokens, token, type)
92
- if token == NOSUCHOBJECT_STR
93
- ['No Such Object', nil]
94
- elsif token == NOSUCHINSTANCE_STR
95
- ['No Such Instance', nil]
96
- elsif !type
97
- ['STRING', token]
127
+ def table(columns)
128
+ if columns.size == 1 && columns.all? { |column| column.size == 1 }
129
+ columns
98
130
  else
99
- [type, tokens.next]
131
+ align(columns)
100
132
  end
101
133
  end
102
134
 
@@ -116,25 +148,24 @@ module SNMP
116
148
  @oids.zip(columns).map do |oid, column|
117
149
  indexes.map do |index|
118
150
  id = (oid == index ? index : "#{oid}.#{index}")
119
- column.find { |o| o.oid == id } || Conversions.absent_value(id)
151
+ column.find { |o| o.oid == id } || Value.new(id, 'absent', nil)
120
152
  end
121
153
  end
122
154
  end
123
155
 
124
- # functions to generate value objects
125
- module Conversions
126
- module_function def convert_value(type, value)
127
- case type
128
- when 'INTEGER'
129
- value.to_i
130
- else
131
- value
132
- end
133
- end
156
+ # static messages from net-snmp commands
157
+ module Static
158
+ include SNMP::Open::Parser::Constants
134
159
 
135
- module_function def absent_value(id)
136
- Value.new(id, 'absent', nil)
137
- end
160
+ MESSAGES = [
161
+ NOSUCHOBJECT_STR,
162
+ NOSUCHINSTANCE_STR,
163
+ NOMOREVARIABLES_STR
164
+ ].freeze
165
+
166
+ ANY_MESSAGE = Regexp.union(*MESSAGES)
167
+
168
+ QUOTED_MESSAGES = MESSAGES.map { |v| [v, %("#{v}")] }.to_h.freeze
138
169
  end
139
170
  end # class Parser
140
171
  end # class Open
@@ -0,0 +1,15 @@
1
+ module SNMP
2
+ class Open
3
+ class Parser
4
+ module Constants
5
+ NOSUCHOBJECT_STR =
6
+ 'No Such Object available on this agent at this OID'.freeze
7
+ NOSUCHINSTANCE_STR =
8
+ 'No Such Instance currently exists at this OID'.freeze
9
+ NOMOREVARIABLES_STR =
10
+ 'No more variables left in this MIB View '\
11
+ '(It is past the end of the MIB tree)'.freeze
12
+ end # module Constants
13
+ end # class Parser
14
+ end # class Open
15
+ end # module SNMP
@@ -0,0 +1,132 @@
1
+ module SNMP
2
+ class Open
3
+ class Parser
4
+ # base class for value parsers
5
+ class ValueParser
6
+ include SNMP::Open::Parser::Constants
7
+
8
+ def self.find(type, token)
9
+ cls = KNOWN_TOKENS[token] || KNOWN_TYPES[type] || Other
10
+ cls.new(type, token)
11
+ end
12
+
13
+ def initialize(type, token)
14
+ @type = type
15
+ @token = token
16
+ end
17
+
18
+ def parse(*)
19
+ @parse
20
+ end
21
+
22
+ # parses BITS
23
+ class Bits < ValueParser
24
+ def parse(tokens)
25
+ return @parse if @parse
26
+
27
+ bytes = []
28
+ loop do
29
+ break unless tokens.peek =~ /\A[0-9A-Za-z]{1,2}\z/
30
+
31
+ bytes << tokens.next.to_i(16)
32
+ end
33
+ @parse = [@type, bytes]
34
+ end
35
+ end # class Bits < ValueParser
36
+
37
+ # parses objects with no explicit type
38
+ class Default < ValueParser
39
+ def initialize(_type, token)
40
+ @parse = ['STRING', token]
41
+ end
42
+ end # class Default
43
+
44
+ # parses integer-like objects
45
+ class Integer < ValueParser
46
+ def parse(tokens)
47
+ @parse ||= [@type, Integer(tokens.next)]
48
+ end
49
+ end
50
+
51
+ # parses objects identified like '= Hex-STRING:'
52
+ class HexString < ValueParser
53
+ def parse(tokens)
54
+ return @parse if @parse
55
+
56
+ bytes = []
57
+ loop do
58
+ break unless tokens.peek =~ /\A[0-9A-Za-z]{2}\z/
59
+
60
+ bytes << tokens.next
61
+ end
62
+ string = bytes.map { |b| b.to_i(16).chr }.join
63
+ @parse = [@type, string]
64
+ end
65
+ end # class HexString
66
+
67
+ # handles messages indicating the end of the response
68
+ class Stop < ValueParser
69
+ def parse(*)
70
+ raise StopIteration, @token
71
+ end
72
+ end
73
+
74
+ # parses objects identified like '= Timeticks:'
75
+ # note that 1 second = 100 ticks
76
+ class Timeticks < ValueParser
77
+ def parse(tokens)
78
+ return @parse if @parse
79
+
80
+ ticks = tokens.next.tr('()', '').to_i
81
+
82
+ # consume tokens through one like 23:59:59.99
83
+ loop do
84
+ break if tokens.next =~ /\A\d\d:\d\d:\d\d.\d\d\z/
85
+ end
86
+
87
+ @parse = [@type, ticks]
88
+ end
89
+ end # class Timeticks
90
+
91
+ # handles objects not handled by any other parser
92
+ class Other < ValueParser
93
+ def parse(tokens)
94
+ @parse ||= [@type, tokens.next]
95
+ end
96
+ end # class Other
97
+
98
+ # handles NoSuchInstance
99
+ class NoSuchInstance < ValueParser
100
+ def initialize(*)
101
+ @parse = ['No Such Instance', nil]
102
+ end
103
+ end # class NoSuchInstance < ValueParser
104
+
105
+ # handles NoSuchObject
106
+ class NoSuchObject < ValueParser
107
+ def initialize(*)
108
+ @parse = ['No Such Object', nil]
109
+ end
110
+ end # class NoSuchObject < ValueParser
111
+
112
+ KNOWN_TOKENS = {
113
+ NOSUCHINSTANCE_STR => NoSuchInstance,
114
+ NOSUCHOBJECT_STR => NoSuchObject,
115
+ NOMOREVARIABLES_STR => Stop
116
+ }.freeze
117
+
118
+ KNOWN_TYPES = {
119
+ nil => Default,
120
+ 'BITS' => Bits,
121
+ 'INTEGER' => ValueParser::Integer,
122
+ 'Gauge32' => ValueParser::Integer,
123
+ 'Gauge64' => ValueParser::Integer,
124
+ 'Counter32' => ValueParser::Integer,
125
+ 'Counter64' => ValueParser::Integer,
126
+ 'Hex-STRING' => HexString,
127
+ 'Timeticks' => Timeticks
128
+ }.freeze
129
+ end # class ValueParser
130
+ end # class Parser
131
+ end # class Open
132
+ end # module SNMP
@@ -1,5 +1,5 @@
1
- module Snmp
2
- module Open
3
- VERSION = '0.3.0'.freeze
1
+ module SNMP
2
+ class Open
3
+ VERSION = '0.6.1'.freeze
4
4
  end
5
5
  end
@@ -1,10 +1,10 @@
1
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
  require 'snmp/open/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'snmp-open'
7
- spec.version = Snmp::Open::VERSION
7
+ spec.version = SNMP::Open::VERSION
8
8
  spec.authors = ['Ben Miller']
9
9
  spec.email = ['bmiller@rackspace.com']
10
10
 
@@ -18,8 +18,10 @@ 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.add_development_dependency 'bundler', '~> 1.11'
22
- spec.add_development_dependency 'rake', '~> 10.0'
21
+ spec.required_ruby_version = '~> 2.4'
22
+
23
+ spec.add_development_dependency 'bundler', '~> 2.2'
24
+ spec.add_development_dependency 'rake', '~> 13.0'
23
25
  spec.add_development_dependency 'rspec', '~> 3.0'
24
26
  spec.add_development_dependency 'snmp'
25
27
  end
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.3.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Miller
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-09-05 00:00:00.000000000 Z
11
+ date: 2021-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.11'
19
+ version: '2.2'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.11'
26
+ version: '2.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -66,16 +66,17 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description:
69
+ description:
70
70
  email:
71
71
  - bmiller@rackspace.com
72
72
  executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
+ - ".github/workflows/ruby.yml"
76
77
  - ".gitignore"
77
78
  - ".rspec"
78
- - ".travis.yml"
79
+ - ".rubocop.yml"
79
80
  - CODE_OF_CONDUCT.md
80
81
  - Gemfile
81
82
  - Guardfile
@@ -89,30 +90,32 @@ files:
89
90
  - lib/snmp/open.rb
90
91
  - lib/snmp/open/command_reader.rb
91
92
  - lib/snmp/open/file_reader.rb
93
+ - lib/snmp/open/options.rb
92
94
  - lib/snmp/open/parser.rb
95
+ - lib/snmp/open/parser/constants.rb
96
+ - lib/snmp/open/parser/value_parser.rb
93
97
  - lib/snmp/open/version.rb
94
98
  - snmp-open.gemspec
95
99
  homepage: https://github.com/bjmllr/snmp-open
96
100
  licenses: []
97
101
  metadata: {}
98
- post_install_message:
102
+ post_install_message:
99
103
  rdoc_options: []
100
104
  require_paths:
101
105
  - lib
102
106
  required_ruby_version: !ruby/object:Gem::Requirement
103
107
  requirements:
104
- - - ">="
108
+ - - "~>"
105
109
  - !ruby/object:Gem::Version
106
- version: '0'
110
+ version: '2.4'
107
111
  required_rubygems_version: !ruby/object:Gem::Requirement
108
112
  requirements:
109
113
  - - ">="
110
114
  - !ruby/object:Gem::Version
111
115
  version: '0'
112
116
  requirements: []
113
- rubyforge_project:
114
- rubygems_version: 2.6.11
115
- signing_key:
117
+ rubygems_version: 3.1.2
118
+ signing_key:
116
119
  specification_version: 4
117
120
  summary: Wrapper for command-line SNMP utilities
118
121
  test_files: []
@@ -1,7 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.4.1
5
- - 2.3.4
6
- - 2.2.7
7
- before_install: gem install bundler -v 1.13.6