snmp_table_viewer 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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: {}
|