snmp_table_viewer 0.0.4 → 0.0.5
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/CHANGELOG.md +5 -0
- data/README.md +16 -2
- data/bin/{snmp-table-viewer → table-from-snmp} +9 -24
- data/bin/table-from-stdin +62 -0
- data/lib/snmp_table_viewer/fetcher.rb +46 -2
- data/lib/snmp_table_viewer.rb +20 -0
- data/snmp_table_viewer.gemspec +5 -4
- data/spec/snmp_table_viewer/fetcher_spec.rb +43 -1
- data/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b570ea16acd375c817335b0d61ac9479aa9ae944
|
4
|
+
data.tar.gz: 94133afd6edafe5d3a94292d3c15379e2b032c7d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d427c9f895295b1f22c0c604fd48b275ea93644a615169fdeead38ca0540a5041e5690a0888ebd1de2e913d22836559022e7641f287c0983976bc8a84ecf0bd3
|
7
|
+
data.tar.gz: 08fe2bd62489cad0a409b70c1ff45cb416aadf2b38b6b0813f4c707ff7835f0f63362eb627c82c38452f7c946e5b64204462647724f3529eeedccf8141bcc1d2
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -40,10 +40,11 @@ gem 'snmp_table_viewer', '~> 0.0'
|
|
40
40
|
```
|
41
41
|
|
42
42
|
|
43
|
-
##
|
43
|
+
## Executables
|
44
44
|
|
45
|
+
### Create table from doing an SNMP walk
|
45
46
|
```
|
46
|
-
Usage:
|
47
|
+
Usage: table-from-snmp [options]
|
47
48
|
-h, -?, --help Prints this help.
|
48
49
|
--headings HEADINGS Headings to use in the table (e.g. "A, Bc, D").
|
49
50
|
--headings-for TYPE Use headings for this table type (ifTable).
|
@@ -75,6 +76,19 @@ SNMP version 3 options:
|
|
75
76
|
Table formatter options:
|
76
77
|
--[no-]transpose-table Transpose the output table (swap rows and columns).
|
77
78
|
```
|
79
|
+
### Create table from piped in data
|
80
|
+
```
|
81
|
+
Usage: table-from-stdin [options]
|
82
|
+
-h, -?, --help Prints this help.
|
83
|
+
--headings HEADINGS Headings to use in the table (e.g. "A, Bc, D").
|
84
|
+
--headings-for TYPE Use headings for this table type (ifTable).
|
85
|
+
--format FORMAT How to format the output (table|csv|json|raw) (default table).
|
86
|
+
--converter CONVERTER A converter to run on the data before formatting (iftable).
|
87
|
+
|
88
|
+
Table formatter options:
|
89
|
+
--[no-]transpose-table Transpose the output table (swap rows and columns).
|
90
|
+
```
|
91
|
+
|
78
92
|
|
79
93
|
## Documentation & Versioning
|
80
94
|
|
@@ -29,25 +29,10 @@ def parse_command_line
|
|
29
29
|
headings: [],
|
30
30
|
formatter: SNMPTableViewer::Formatter::Table,
|
31
31
|
}
|
32
|
-
headings_for = {
|
33
|
-
'ifTable' => ['Index', 'Descr', 'Type', 'Mtu', 'Speed', 'PhysAddress', 'AdminStatus', 'OperStatus', 'LastChange', 'InOctets', 'InUcastPkts', 'InNUcastkts', 'InDiscards', 'InErrors', 'InUnknownPrortos', 'OutOctets', 'OutUcastPkts', 'OutNUcastPkts', 'OutDiscards', 'OutErrors', 'OutQLen', 'Specific'],
|
34
|
-
}
|
35
|
-
formatters = {
|
36
|
-
'table' => SNMPTableViewer::Formatter::Table,
|
37
|
-
'csv' => SNMPTableViewer::Formatter::CSV,
|
38
|
-
'json' => SNMPTableViewer::Formatter::JSON,
|
39
|
-
'raw' => SNMPTableViewer::Formatter::Raw,
|
40
|
-
}
|
41
|
-
converters = {
|
42
|
-
'iftable' => SNMPTableViewer::Converter::IfTable,
|
43
|
-
}
|
44
|
-
base_oids = {
|
45
|
-
'iftable' => '1.3.6.1.2.1.2.2',
|
46
|
-
}
|
47
32
|
snmp_version = 'v3'
|
48
33
|
|
49
34
|
parser = OptionParser.new do |opts|
|
50
|
-
opts.banner = "Usage:
|
35
|
+
opts.banner = "Usage: table-from-snmp [options]"
|
51
36
|
|
52
37
|
opts.on('-h', '--help', '-?', 'Prints this help.') do
|
53
38
|
puts opts
|
@@ -58,16 +43,16 @@ def parse_command_line
|
|
58
43
|
options[:headings] += v.map(&:strip)
|
59
44
|
end
|
60
45
|
|
61
|
-
opts.on('--headings-for TYPE', String, "Use headings for this table type (#{
|
62
|
-
options[:headings] +=
|
46
|
+
opts.on('--headings-for TYPE', String, "Use headings for this table type (#{SNMPTableViewer::HEADINGS_FOR.keys.join('|')}).") do |v|
|
47
|
+
options[:headings] += SNMPTableViewer::HEADINGS_FOR[v] || []
|
63
48
|
end
|
64
49
|
|
65
|
-
opts.on('--format FORMAT', String, "How to format the output (#{
|
66
|
-
options[:formatter] =
|
50
|
+
opts.on('--format FORMAT', String, "How to format the output (#{SNMPTableViewer::FORMATTERS.keys.join('|')}) (default table).") do |v|
|
51
|
+
options[:formatter] = SNMPTableViewer::FORMATTERS[v.downcase]
|
67
52
|
end
|
68
53
|
|
69
|
-
opts.on('--converter CONVERTER', String, "A converter to run on the data before formatting (#{
|
70
|
-
options[:converter] =
|
54
|
+
opts.on('--converter CONVERTER', String, "A converter to run on the data before formatting (#{SNMPTableViewer::CONVERTERS.keys.join('|')}).") do |v|
|
55
|
+
options[:converter] = SNMPTableViewer::CONVERTERS[v.downcase]
|
71
56
|
end
|
72
57
|
|
73
58
|
|
@@ -87,7 +72,7 @@ def parse_command_line
|
|
87
72
|
end
|
88
73
|
|
89
74
|
opts.on('--base-oid OID', 'The oid at the start of the table. Can by dotted numbers or ifTable') do |v|
|
90
|
-
options[:base_oid] =
|
75
|
+
options[:base_oid] = SNMPTableViewer::BASE_OIDS[v.downcase] || v
|
91
76
|
end
|
92
77
|
|
93
78
|
|
@@ -139,7 +124,7 @@ options = parse_command_line
|
|
139
124
|
snmp_options = options[:snmp][:common].clone
|
140
125
|
snmp_options.merge!(options[:snmp][snmp_options[:version]])
|
141
126
|
|
142
|
-
data = SNMPTableViewer::Fetcher.
|
127
|
+
data = SNMPTableViewer::Fetcher.from_snmp(base_oid: options[:base_oid], **snmp_options)
|
143
128
|
|
144
129
|
converter = options[:converter]
|
145
130
|
data = converter.convert(data) unless converter.nil?
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require_relative File.join('..', 'lib', 'snmp_table_viewer')
|
5
|
+
|
6
|
+
def parse_command_line
|
7
|
+
options = {
|
8
|
+
SNMPTableViewer::Formatter::Table => {
|
9
|
+
transpose: false,
|
10
|
+
},
|
11
|
+
headings: [],
|
12
|
+
formatter: SNMPTableViewer::Formatter::Table,
|
13
|
+
}
|
14
|
+
|
15
|
+
parser = OptionParser.new do |opts|
|
16
|
+
opts.banner = "Usage: table-from-stdin [options]"
|
17
|
+
|
18
|
+
opts.on('-h', '--help', '-?', 'Prints this help.') do
|
19
|
+
puts opts
|
20
|
+
exit
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on('--headings HEADINGS', Array, 'Headings to use in the table (e.g. "A, Bc, D").') do |v|
|
24
|
+
options[:headings] += v.map(&:strip)
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on('--headings-for TYPE', String, "Use headings for this table type (#{SNMPTableViewer::HEADINGS_FOR.keys.join('|')}).") do |v|
|
28
|
+
options[:headings] += SNMPTableViewer::HEADINGS_FOR[v] || []
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on('--format FORMAT', String, "How to format the output (#{SNMPTableViewer::FORMATTERS.keys.join('|')}) (default table).") do |v|
|
32
|
+
options[:formatter] = SNMPTableViewer::FORMATTERS[v.downcase]
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on('--converter CONVERTER', String, "A converter to run on the data before formatting (#{SNMPTableViewer::CONVERTERS.keys.join('|')}).") do |v|
|
36
|
+
options[:converter] = SNMPTableViewer::CONVERTERS[v.downcase]
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
opts.separator "\nTable formatter options:"
|
41
|
+
opts.on('--[no-]transpose-table', 'Transpose the output table (swap rows and columns).') do |v|
|
42
|
+
options[SNMPTableViewer::Formatter::Table][:transpose] = v
|
43
|
+
end
|
44
|
+
|
45
|
+
end # create parser
|
46
|
+
|
47
|
+
parser.parse!(ARGV)
|
48
|
+
options
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
options = parse_command_line
|
53
|
+
data = STDIN.readlines.map(&:strip)
|
54
|
+
data = SNMPTableViewer::Fetcher.from_array(data)
|
55
|
+
|
56
|
+
converter = options[:converter]
|
57
|
+
data = converter.convert(data) unless converter.nil?
|
58
|
+
|
59
|
+
formatter = options[:formatter]
|
60
|
+
formatter_options = options[formatter] || {}
|
61
|
+
formatter = formatter.new(data: data, headings: options[:headings])
|
62
|
+
puts formatter.output(**formatter_options)
|
@@ -6,19 +6,63 @@ module SNMPTableViewer
|
|
6
6
|
# Fetch the data using SNMP.
|
7
7
|
# @param base_oid [String] The OID to start the SNMP walk from
|
8
8
|
# @param **snmp_options [Hash] The options to pass to NETSNMP::Client.new
|
9
|
-
# @return [Array<Array<#to_s>>] A two dimensional array containing objects in each cell (at 'address' data[row][col])
|
9
|
+
# @return [Array<Array<#to_s>>] A two dimensional array containing objects in each cell (at 'address' data\[row\]\[col\])
|
10
10
|
def self.from_snmp(base_oid:, **snmp_options)
|
11
11
|
data = Array.new
|
12
12
|
NETSNMP::Client.new(snmp_options) do |manager|
|
13
13
|
manager.walk(oid: base_oid).each do |oid, value|
|
14
14
|
col, row = oid.split('.')[-2..-1].map{ |i| i.to_i - 1}
|
15
|
-
data[row] ||=
|
15
|
+
data[row] ||= Array.new
|
16
16
|
data[row][col] = value
|
17
17
|
end
|
18
18
|
end
|
19
19
|
data
|
20
20
|
end
|
21
21
|
|
22
|
+
# Build the data from an Array<String>.
|
23
|
+
# Each String of the format returned by the snmpwalk command ("<oid> = <type>: <value>").
|
24
|
+
# @param data [Array<String>] The Strings to get the data from
|
25
|
+
# @return [Array<Array<#to_s>>] A two dimensional array containing objects in each cell (at 'address' data\[row\]\[col\])
|
26
|
+
def self.from_array(data_in)
|
27
|
+
data_out = Array.new
|
28
|
+
regexp_general = Regexp.compile(/\A(?:iso)?[\.0-9]+\.([0-9]+)\.([0-9]+)\s+=\s+([A-Za-z0-9 \-]+):\s+(.+)\Z/)
|
29
|
+
regexp_nodata = Regexp.compile(/\A(?:iso)?[\.0-9]+\.([0-9]+)\.([0-9]+)\s+=\s+""\Z/)
|
30
|
+
data_in.each.with_index do |line, index|
|
31
|
+
# Try to get a match on the various valid frmats of line
|
32
|
+
match = line.match(regexp_general)
|
33
|
+
match ||= line.match(regexp_nodata)
|
34
|
+
if match.nil?
|
35
|
+
STDERR.puts "Could not parse data on line #{index+1}: #{line}"
|
36
|
+
next
|
37
|
+
end
|
38
|
+
|
39
|
+
col, row, type, value = match.captures
|
40
|
+
# Convert value
|
41
|
+
case type && type.downcase
|
42
|
+
when nil
|
43
|
+
when 'string'
|
44
|
+
value = value[1..-2] # Strip enclosing quotes
|
45
|
+
when 'oid', 'hex-string'
|
46
|
+
when 'integer', 'integer32', 'uinteger32', 'gauge32', 'counter32', 'counter64'
|
47
|
+
value = value.to_i
|
48
|
+
when 'ipaddress'
|
49
|
+
value = IPAddr.new(value)
|
50
|
+
when 'timeticks'
|
51
|
+
match = value.match(/\A\((\d+)\)/)
|
52
|
+
value = NETSNMP::Timetick.new(match.nil? ? 0 : match[1].to_i)
|
53
|
+
else
|
54
|
+
STDERR.puts "Unknown SNMP type (#{type}) on line #{index+1}: #{line}"
|
55
|
+
end
|
56
|
+
|
57
|
+
# Save value
|
58
|
+
row = row.to_i - 1
|
59
|
+
col = col.to_i - 1
|
60
|
+
data_out[row] ||= Array.new
|
61
|
+
data_out[row][col] = value
|
62
|
+
end # each line of data_in
|
63
|
+
data_out
|
64
|
+
end
|
65
|
+
|
22
66
|
end # class Fetcher
|
23
67
|
|
24
68
|
end # module SNMPTableViewer
|
data/lib/snmp_table_viewer.rb
CHANGED
@@ -11,4 +11,24 @@ require_relative '../version'
|
|
11
11
|
Dir["#{File.dirname(__FILE__)}/**/*.rb"].select{ |f| f != __FILE__}.sort.each { |f| load(f) }
|
12
12
|
|
13
13
|
module SNMPTableViewer
|
14
|
+
|
15
|
+
HEADINGS_FOR = {
|
16
|
+
'ifTable' => ['Index', 'Descr', 'Type', 'Mtu', 'Speed', 'PhysAddress', 'AdminStatus', 'OperStatus', 'LastChange', 'InOctets', 'InUcastPkts', 'InNUcastkts', 'InDiscards', 'InErrors', 'InUnknownPrortos', 'OutOctets', 'OutUcastPkts', 'OutNUcastPkts', 'OutDiscards', 'OutErrors', 'OutQLen', 'Specific'],
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
FORMATTERS = {
|
20
|
+
'table' => SNMPTableViewer::Formatter::Table,
|
21
|
+
'csv' => SNMPTableViewer::Formatter::CSV,
|
22
|
+
'json' => SNMPTableViewer::Formatter::JSON,
|
23
|
+
'raw' => SNMPTableViewer::Formatter::Raw,
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
CONVERTERS = {
|
27
|
+
'iftable' => SNMPTableViewer::Converter::IfTable,
|
28
|
+
}.freeze
|
29
|
+
|
30
|
+
BASE_OIDS = {
|
31
|
+
'iftable' => '1.3.6.1.2.1.2.2',
|
32
|
+
}.freeze
|
33
|
+
|
14
34
|
end # module SNMPTableViewer
|
data/snmp_table_viewer.gemspec
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path(
|
2
|
+
$:.push File.expand_path(File.join('..', 'lib'), __FILE__)
|
3
3
|
require File.join(File.dirname(__FILE__), 'version')
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
6
|
+
s.name = 'snmp_table_viewer'
|
7
7
|
s.license = 'BSD 3 clause'
|
8
8
|
s.version = SNMPTableViewer::VERSION
|
9
9
|
s.authors = ['Robert Gauld']
|
10
10
|
s.email = ['robert@robertgauld.co.uk']
|
11
|
-
s.homepage = 'https://github.com/robertgauld/
|
11
|
+
s.homepage = 'https://github.com/robertgauld/snmp_table_viewer'
|
12
12
|
s.summary = %q{Easily view SNMP tables.}
|
13
13
|
s.description = %q{Easily view SNMP tables in a variety of different formats including as a table in the terminal, json or csv.}
|
14
14
|
|
15
15
|
s.files = `git ls-files`.split("\n")
|
16
16
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
-
s.require_paths = [
|
18
|
+
s.require_paths = ['lib']
|
19
|
+
s.bindir = 'bin'
|
19
20
|
|
20
21
|
s.add_runtime_dependency 'netsnmp', '~> 0.1.3'
|
21
22
|
s.add_runtime_dependency 'terminal-table', '~> 1.8.0'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
describe SNMPTableViewer::Fetcher do
|
2
2
|
|
3
|
-
it '
|
3
|
+
it '#from_snmp' do
|
4
4
|
snmp_options = {opt_a: :a}
|
5
5
|
manager = double("manager")
|
6
6
|
expect(manager).to receive(:walk).with(oid: '1.2.3.4.5').once.and_return([
|
@@ -20,4 +20,46 @@ describe SNMPTableViewer::Fetcher do
|
|
20
20
|
]
|
21
21
|
end
|
22
22
|
|
23
|
+
describe '#from_array' do
|
24
|
+
it 'Given array of strings "<oid> = <type>: <value>"' do
|
25
|
+
data = [
|
26
|
+
'iso.3.6.1.2.1.2.2.1.1.1 = INTEGER: 1',
|
27
|
+
'iso.3.6.1.2.1.2.2.1.2.1 = STRING: "lo"',
|
28
|
+
'iso.3.6.1.2.1.2.2.1.3.1 = Gauge32: 2',
|
29
|
+
'iso.3.6.1.2.1.2.2.1.4.1 = Hex-STRING: 01 23 45 67 89 AB',
|
30
|
+
'iso.3.6.1.2.1.2.2.1.5.1 = Timeticks: (10) 0:00:10.00',
|
31
|
+
'iso.3.6.1.2.1.2.2.1.6.1 = Counter32: 3',
|
32
|
+
'iso.3.6.1.2.1.2.2.1.7.1 = OID: ccitt.0',
|
33
|
+
'iso.3.6.1.2.1.2.2.1.8.1 = IpAddress: 1.2.3.4',
|
34
|
+
'iso.3.6.1.2.1.2.2.1.10.1 = ""',
|
35
|
+
]
|
36
|
+
expect(described_class.from_array(data)).to eq [[
|
37
|
+
1,
|
38
|
+
'lo',
|
39
|
+
2,
|
40
|
+
'01 23 45 67 89 AB',
|
41
|
+
NETSNMP::Timetick.new(10),
|
42
|
+
3,
|
43
|
+
'ccitt.0',
|
44
|
+
IPAddr.new('1.2.3.4'),
|
45
|
+
nil,
|
46
|
+
nil
|
47
|
+
]]
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'Errors but survives on a bad line' do
|
51
|
+
data = ['This is a bad line', 'This is another bad line']
|
52
|
+
expect(STDERR).to receive(:puts).with('Could not parse data on line 1: This is a bad line').once
|
53
|
+
expect(STDERR).to receive(:puts).with('Could not parse data on line 2: This is another bad line').once
|
54
|
+
expect(described_class.from_array(data)).to eq []
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'Errors but survives on a bad type' do
|
58
|
+
data = ['1.2.3.4.0.1.1 = INTEGER: 1', '1.2.3.4.0.2.1 = invalid-type: 1']
|
59
|
+
expect(STDERR).to receive(:puts).with('Unknown SNMP type (invalid-type) on line 2: 1.2.3.4.0.2.1 = invalid-type: 1').once
|
60
|
+
expect(described_class.from_array(data)).to eq [[1, '1']]
|
61
|
+
end
|
62
|
+
|
63
|
+
end # describe #from_array
|
64
|
+
|
23
65
|
end
|
data/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: snmp_table_viewer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Gauld
|
@@ -139,7 +139,8 @@ description: Easily view SNMP tables in a variety of different formats including
|
|
139
139
|
email:
|
140
140
|
- robert@robertgauld.co.uk
|
141
141
|
executables:
|
142
|
-
-
|
142
|
+
- table-from-snmp
|
143
|
+
- table-from-stdin
|
143
144
|
extensions: []
|
144
145
|
extra_rdoc_files: []
|
145
146
|
files:
|
@@ -153,7 +154,8 @@ files:
|
|
153
154
|
- LICENSE.rdoc
|
154
155
|
- README.md
|
155
156
|
- Rakefile
|
156
|
-
- bin/
|
157
|
+
- bin/table-from-snmp
|
158
|
+
- bin/table-from-stdin
|
157
159
|
- lib/snmp_table_viewer.rb
|
158
160
|
- lib/snmp_table_viewer/converter.rb
|
159
161
|
- lib/snmp_table_viewer/converter/if_table.rb
|
@@ -175,7 +177,7 @@ files:
|
|
175
177
|
- spec/snmp_table_viewer_spec.rb
|
176
178
|
- spec/spec_helper.rb
|
177
179
|
- version.rb
|
178
|
-
homepage: https://github.com/robertgauld/
|
180
|
+
homepage: https://github.com/robertgauld/snmp_table_viewer
|
179
181
|
licenses:
|
180
182
|
- BSD 3 clause
|
181
183
|
metadata: {}
|