snmp-open 0.2.0 → 0.6.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
- SHA1:
3
- metadata.gz: eb1bfb86bae4239a253fa4528be54e46a30e770d
4
- data.tar.gz: 0574b00db365565c87e647314b00f34950ba8280
2
+ SHA256:
3
+ metadata.gz: 1362f32d8e43b509be4884b392c43689b9cba48c2e2d6f63c4912e645ba6fcc9
4
+ data.tar.gz: d751cce9e00204ae0b0d131120338ce3b7beaf1bbfb2e71f114c60f8c9bfdfa8
5
5
  SHA512:
6
- metadata.gz: db49e2407897332554aae593b909bb74db5878a6b2f5f72779bfe6fdd1be116c2579226811bca87814c5f2ae3f55678c4a9ccbfcebd0157ccc918a4b48bea0b4
7
- data.tar.gz: 98f0150f390faf0fe8f8cffb8e60c535aae051cda4bfa964900a4e2172449807c3e85fdcaccf9d2090c1a082084885a872d93402b423e6fa2abb94de797b086e
6
+ metadata.gz: 51603c2ee2b8d5077be2dcc8f26b74ad174d09a31fe6b6879343d98b33bba5f30f6246cf2ac3999f3a3aa46fda3b5cf7f849310016de5725cbdd0574741af99c
7
+ data.tar.gz: 2670576c9373c22e74e5bc7a118317ffdefb33d685ef654236e1ec5f369f9ac772d619ff7cfba3e8532ba52a5fc3b0d52bc67439cbeb96d84a08d6cc36f40819
@@ -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,2 @@
1
+ Style/CommentedKeyword:
2
+ Enabled: false
@@ -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,7 +30,7 @@ module SNMP
54
30
  else
55
31
  Open3.capture3(cli(cmd, oid, options))
56
32
  end
57
- raise CommandError, err.chomp unless err.empty?
33
+ raise_capture_errors(err)
58
34
  out
59
35
  end
60
36
 
@@ -65,6 +41,7 @@ module SNMP
65
41
  [
66
42
  command,
67
43
  *options.map { |k, v| "#{k}#{v}" },
44
+ *oid_options(id),
68
45
  *@host_options.map { |k, v| "#{k}#{v}" },
69
46
  *@command_options.fetch(command, {}).map { |k, v| "#{k}#{v}" },
70
47
  *id
@@ -73,11 +50,24 @@ module SNMP
73
50
 
74
51
  private
75
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
+
76
66
  def merge_options(options = {})
77
67
  options.each_pair.with_object({}) do |(key, value), opts|
78
- if OPTIONS.key?(key)
79
- opts[OPTIONS[key]] =
80
- (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)
81
71
  elsif key.is_a?(String)
82
72
  opts[key] = value
83
73
  else
@@ -86,6 +76,15 @@ module SNMP
86
76
  end
87
77
  end
88
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
+
89
88
  def normalize_command(command)
90
89
  case command
91
90
  when Symbol then "snmp#{command}"
@@ -122,5 +121,8 @@ module SNMP
122
121
  end # class CommandReader
123
122
 
124
123
  class CommandError < RuntimeError; end
124
+ class CommandTimeoutError < CommandError; end
125
+ class UnknownMIBError < CommandError; end
126
+ class UnknownOIDError < CommandError; end
125
127
  end # class Open
126
128
  end # module SNMP
@@ -13,20 +13,37 @@ 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))
32
+ mkdir(@directory, cmd.to_s) if @make_directories
33
+ outfile = File.join(@directory, cmd.to_s, oid)
34
+ File.read(outfile)
26
35
  rescue Errno::ENOENT => err
27
- warn "#{@command_generator.cli(cmd, oid)} > #{outfile}" if @warnings
36
+ if @warnings
37
+ warning = @warnings.call(@command_generator, cmd, oid, outfile)
38
+ warn warning
39
+ end
28
40
  raise err
29
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))
46
+ end
30
47
  end # class FileReader
31
48
  end # class Open
32
49
  end # module SNMP
@@ -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,8 @@ 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
18
 
19
19
  def initialize(oids)
20
20
  @oids = oids
@@ -22,11 +22,8 @@ module SNMP
22
22
 
23
23
  def parse(texts)
24
24
  columns = texts.map do |text|
25
- tokenized =
26
- text
27
- .gsub(NOSUCHOBJECT_STR, %("#{NOSUCHOBJECT_STR}"))
28
- .gsub(NOSUCHINSTANCE_STR, %("#{NOSUCHINSTANCE_STR}"))
29
- .shellsplit
25
+ clean = clean_input_text(text)
26
+ tokenized = clean.shellsplit
30
27
  parse_tokens(tokenized)
31
28
  end
32
29
 
@@ -35,7 +32,7 @@ module SNMP
35
32
 
36
33
  private
37
34
 
38
- def table(columns)
35
+ def align(columns)
39
36
  indexes = columns.first.map { |value| index_using_first_oid(value) }
40
37
  hash = columns.flat_map { |row| row.map { |v| [v.oid, v] } }.to_h
41
38
 
@@ -47,6 +44,16 @@ module SNMP
47
44
  end
48
45
  end
49
46
 
47
+ def clean_input_text(text)
48
+ text
49
+ .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))
54
+ .gsub(Static::ANY_MESSAGE, Static::QUOTED_MESSAGES)
55
+ end
56
+
50
57
  def index_using_first_oid(value)
51
58
  base = @oids.first
52
59
 
@@ -69,12 +76,12 @@ module SNMP
69
76
 
70
77
  objects
71
78
  rescue StopIteration
72
- return objects
79
+ objects
73
80
  end
74
81
 
75
82
  def parse_next_object(tokens)
76
83
  oid = tokens.next.sub(/\A\./, '')
77
- raise "Parse error at #{oid}" unless oid =~ /\A[0-9.]+\z/
84
+ raise "Parse error at #{oid}" unless oid =~ OID_RE
78
85
  equals = tokens.next
79
86
  raise "Parse error after #{oid}" unless equals == '='
80
87
  type, value = parse_type(tokens)
@@ -82,21 +89,16 @@ module SNMP
82
89
  end
83
90
 
84
91
  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)]
92
+ token = tokens.next
93
+ type = token.match(/\A([-A-Za-z]+[0-9]*):\z/) { |md| md[1] }
94
+ ValueParser.find(type, token).parse(tokens)
89
95
  end
90
96
 
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]
97
+ def table(columns)
98
+ if columns.size == 1 && columns.all? { |column| column.size == 1 }
99
+ columns
98
100
  else
99
- [type, tokens.next]
101
+ align(columns)
100
102
  end
101
103
  end
102
104
 
@@ -116,25 +118,24 @@ module SNMP
116
118
  @oids.zip(columns).map do |oid, column|
117
119
  indexes.map do |index|
118
120
  id = (oid == index ? index : "#{oid}.#{index}")
119
- column.find { |o| o.oid == id } || Conversions.absent_value(id)
121
+ column.find { |o| o.oid == id } || Value.new(id, 'absent', nil)
120
122
  end
121
123
  end
122
124
  end
123
125
 
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
126
+ # static messages from net-snmp commands
127
+ module Static
128
+ include SNMP::Open::Parser::Constants
134
129
 
135
- module_function def absent_value(id)
136
- Value.new(id, 'absent', nil)
137
- end
130
+ MESSAGES = [
131
+ NOSUCHOBJECT_STR,
132
+ NOSUCHINSTANCE_STR,
133
+ NOMOREVARIABLES_STR
134
+ ].freeze
135
+
136
+ ANY_MESSAGE = Regexp.union(*MESSAGES)
137
+
138
+ QUOTED_MESSAGES = MESSAGES.map { |v| [v, %("#{v}")] }.to_h.freeze
138
139
  end
139
140
  end # class Parser
140
141
  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,127 @@
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
+ bytes = []
27
+ loop do
28
+ break unless tokens.peek =~ /\A[0-9A-Za-z]{1,2}\z/
29
+ bytes << tokens.next.to_i(16)
30
+ end
31
+ @parse = [@type, bytes]
32
+ end
33
+ end # class Bits < ValueParser
34
+
35
+ # parses objects with no explicit type
36
+ class Default < ValueParser
37
+ def initialize(_type, token)
38
+ @parse = ['STRING', token]
39
+ end
40
+ end # class Default
41
+
42
+ # parses integer-like objects
43
+ class Integer < ValueParser
44
+ def parse(tokens)
45
+ @parse ||= [@type, Integer(tokens.next)]
46
+ end
47
+ end
48
+
49
+ # parses objects identified like '= Hex-STRING:'
50
+ class HexString < ValueParser
51
+ def parse(tokens)
52
+ return @parse if @parse
53
+ bytes = []
54
+ loop do
55
+ break unless tokens.peek =~ /\A[0-9A-Za-z]{2}\z/
56
+ bytes << tokens.next
57
+ end
58
+ string = bytes.map { |b| b.to_i(16).chr }.join
59
+ @parse = [@type, string]
60
+ end
61
+ end # class HexString
62
+
63
+ # handles messages indicating the end of the response
64
+ class Stop < ValueParser
65
+ def parse(*)
66
+ raise StopIteration, @token
67
+ end
68
+ end
69
+
70
+ # parses objects identified like '= Timeticks:'
71
+ # note that 1 second = 100 ticks
72
+ class Timeticks < ValueParser
73
+ def parse(tokens)
74
+ return @parse if @parse
75
+ ticks = tokens.next.tr('()', '').to_i
76
+
77
+ # consume tokens through one like 23:59:59.99
78
+ loop do
79
+ break if tokens.next =~ /\A\d\d:\d\d:\d\d.\d\d\z/
80
+ end
81
+
82
+ @parse = [@type, ticks]
83
+ end
84
+ end # class Timeticks
85
+
86
+ # handles objects not handled by any other parser
87
+ class Other < ValueParser
88
+ def parse(tokens)
89
+ @parse ||= [@type, tokens.next]
90
+ end
91
+ end # class Other
92
+
93
+ # handles NoSuchInstance
94
+ class NoSuchInstance < ValueParser
95
+ def initialize(*)
96
+ @parse = ['No Such Instance', nil]
97
+ end
98
+ end # class NoSuchInstance < ValueParser
99
+
100
+ # handles NoSuchObject
101
+ class NoSuchObject < ValueParser
102
+ def initialize(*)
103
+ @parse = ['No Such Object', nil]
104
+ end
105
+ end # class NoSuchObject < ValueParser
106
+
107
+ KNOWN_TOKENS = {
108
+ NOSUCHINSTANCE_STR => NoSuchInstance,
109
+ NOSUCHOBJECT_STR => NoSuchObject,
110
+ NOMOREVARIABLES_STR => Stop
111
+ }.freeze
112
+
113
+ KNOWN_TYPES = {
114
+ nil => Default,
115
+ 'BITS' => Bits,
116
+ 'INTEGER' => ValueParser::Integer,
117
+ 'Gauge32' => ValueParser::Integer,
118
+ 'Gauge64' => ValueParser::Integer,
119
+ 'Counter32' => ValueParser::Integer,
120
+ 'Counter64' => ValueParser::Integer,
121
+ 'Hex-STRING' => HexString,
122
+ 'Timeticks' => Timeticks
123
+ }.freeze
124
+ end # class ValueParser
125
+ end # class Parser
126
+ end # class Open
127
+ end # module SNMP
@@ -1,5 +1,5 @@
1
- module Snmp
2
- module Open
3
- VERSION = '0.2.0'.freeze
1
+ module SNMP
2
+ class Open
3
+ VERSION = '0.6.0'.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,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.add_development_dependency 'bundler', '~> 1.11'
22
- spec.add_development_dependency 'rake', '~> 10.0'
21
+ spec.add_development_dependency 'bundler', '~> 2.2'
22
+ spec.add_development_dependency 'rake', '~> 13.0'
23
23
  spec.add_development_dependency 'rspec', '~> 3.0'
24
24
  spec.add_development_dependency 'snmp'
25
25
  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.2.0
4
+ version: 0.6.0
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-05-06 00:00:00.000000000 Z
11
+ date: 2020-12-16 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,13 +90,16 @@ 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
@@ -110,9 +114,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
114
  - !ruby/object:Gem::Version
111
115
  version: '0'
112
116
  requirements: []
113
- rubyforge_project:
114
- rubygems_version: 2.5.2
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