snmp_table_viewer 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +21 -0
- data/.gitignore +27 -0
- data/.rspec +3 -0
- data/.travis.yml +15 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +4 -0
- data/Guardfile +9 -0
- data/LICENSE.rdoc +39 -0
- data/README.md +83 -0
- data/Rakefile +16 -0
- data/bin/snmp-table-viewer +150 -0
- data/lib/snmp_table_viewer/converter/if_table.rb +296 -0
- data/lib/snmp_table_viewer/converter.rb +8 -0
- data/lib/snmp_table_viewer/fetcher.rb +24 -0
- data/lib/snmp_table_viewer/formatter/csv.rb +12 -0
- data/lib/snmp_table_viewer/formatter/json.rb +17 -0
- data/lib/snmp_table_viewer/formatter/raw.rb +12 -0
- data/lib/snmp_table_viewer/formatter/table.rb +30 -0
- data/lib/snmp_table_viewer/formatter.rb +30 -0
- data/lib/snmp_table_viewer.rb +14 -0
- data/snmp_table_viewer.gemspec +30 -0
- data/spec/snmp_table_viewer/converter/if_table_spec.rb +36 -0
- data/spec/snmp_table_viewer/converter_spec.rb +2 -0
- data/spec/snmp_table_viewer/fetcher_spec.rb +23 -0
- data/spec/snmp_table_viewer/formatter/csv_spec.rb +26 -0
- data/spec/snmp_table_viewer/formatter/json_spec.rb +26 -0
- data/spec/snmp_table_viewer/formatter/raw_spec.rb +26 -0
- data/spec/snmp_table_viewer/formatter/table_spec.rb +73 -0
- data/spec/snmp_table_viewer/formatter_spec.rb +42 -0
- data/spec/snmp_table_viewer_spec.rb +2 -0
- data/spec/spec_helper.rb +122 -0
- data/version.rb +3 -0
- metadata +202 -0
@@ -0,0 +1,296 @@
|
|
1
|
+
module SNMPTableViewer
|
2
|
+
|
3
|
+
# Converter for the interface table.
|
4
|
+
# Replaces type with "number (meaning)"
|
5
|
+
# Replaces admin state with "number (meaning)"
|
6
|
+
# Replaces oper state with "number (meaning)"
|
7
|
+
# Replaces last change with "Timeticks: (number) D days, H:M:S.ms"
|
8
|
+
class Converter::IfTable < Converter
|
9
|
+
def self.convert(data)
|
10
|
+
admin_states = ['up', 'down', 'testing']
|
11
|
+
oper_states = ['up', 'down', 'testing', 'unknown', 'dormant', 'notPresent', 'lowerLayerDown']
|
12
|
+
types = {
|
13
|
+
1 => 'other',
|
14
|
+
2 => 'regular1822',
|
15
|
+
3 => 'hdh1822',
|
16
|
+
4 => 'ddnX25',
|
17
|
+
5 => 'rfc877x25',
|
18
|
+
6 => 'ethernetCsmacd',
|
19
|
+
7 => 'iso88023Csmacd',
|
20
|
+
8 => 'iso88024TokenBus',
|
21
|
+
9 => 'iso88025TokenRing',
|
22
|
+
10 => 'iso88026Man',
|
23
|
+
11 => 'starLan',
|
24
|
+
12 => 'proteon10Mbit',
|
25
|
+
13 => 'proteon80Mbit',
|
26
|
+
14 => 'hyperchannel',
|
27
|
+
15 => 'fddi',
|
28
|
+
16 => 'lapb',
|
29
|
+
17 => 'sdlc',
|
30
|
+
18 => 'ds1',
|
31
|
+
19 => 'e1',
|
32
|
+
20 => 'basicISDN',
|
33
|
+
21 => 'primaryISDN',
|
34
|
+
22 => 'propPointToPointSerial',
|
35
|
+
23 => 'ppp',
|
36
|
+
24 => 'softwareLoopback',
|
37
|
+
25 => 'eon',
|
38
|
+
26 => 'ethernet3Mbit',
|
39
|
+
27 => 'nsip',
|
40
|
+
28 => 'slip',
|
41
|
+
29 => 'ultra',
|
42
|
+
30 => 'ds3',
|
43
|
+
31 => 'sip',
|
44
|
+
32 => 'frameRelay',
|
45
|
+
33 => 'rs232',
|
46
|
+
34 => 'para',
|
47
|
+
35 => 'arcnet',
|
48
|
+
36 => 'arcnetPlus',
|
49
|
+
37 => 'atm',
|
50
|
+
38 => 'miox25',
|
51
|
+
39 => 'sonet',
|
52
|
+
40 => 'x25ple',
|
53
|
+
41 => 'iso88022llc',
|
54
|
+
42 => 'localTalk',
|
55
|
+
43 => 'smdsDxi',
|
56
|
+
44 => 'frameRelayService',
|
57
|
+
45 => 'v35',
|
58
|
+
46 => 'hssi',
|
59
|
+
47 => 'hippi',
|
60
|
+
48 => 'modem',
|
61
|
+
49 => 'aal5',
|
62
|
+
50 => 'sonetPath',
|
63
|
+
51 => 'sonetVT',
|
64
|
+
52 => 'smdsIcip',
|
65
|
+
53 => 'propVirtual',
|
66
|
+
54 => 'propMultiplexor',
|
67
|
+
55 => 'ieee80212',
|
68
|
+
56 => 'fibreChannel',
|
69
|
+
57 => 'hippiInterface',
|
70
|
+
58 => 'frameRelayInterconnect',
|
71
|
+
59 => 'aflane8023',
|
72
|
+
60 => 'aflane8025',
|
73
|
+
61 => 'cctEmul',
|
74
|
+
62 => 'fastEther',
|
75
|
+
63 => 'isdn',
|
76
|
+
64 => 'v11',
|
77
|
+
65 => 'v36',
|
78
|
+
66 => 'g703at64k',
|
79
|
+
67 => 'g703at2mb',
|
80
|
+
68 => 'qllc',
|
81
|
+
69 => 'fastEtherFX',
|
82
|
+
70 => 'channel',
|
83
|
+
71 => 'ieee80211',
|
84
|
+
72 => 'ibm370parChan',
|
85
|
+
73 => 'escon',
|
86
|
+
74 => 'dlsw',
|
87
|
+
75 => 'isdns',
|
88
|
+
76 => 'isdnu',
|
89
|
+
77 => 'lapd',
|
90
|
+
78 => 'ipSwitch',
|
91
|
+
79 => 'rsrb',
|
92
|
+
80 => 'atmLogical',
|
93
|
+
81 => 'ds0',
|
94
|
+
82 => 'ds0Bundle',
|
95
|
+
83 => 'bsc',
|
96
|
+
84 => 'async',
|
97
|
+
85 => 'cnr',
|
98
|
+
86 => 'iso88025Dtr',
|
99
|
+
87 => 'eplrs',
|
100
|
+
88 => 'arap',
|
101
|
+
89 => 'propCnls',
|
102
|
+
90 => 'hostPad',
|
103
|
+
91 => 'termPad',
|
104
|
+
92 => 'frameRelayMPI',
|
105
|
+
93 => 'x213',
|
106
|
+
94 => 'adsl',
|
107
|
+
95 => 'radsl',
|
108
|
+
96 => 'sdsl',
|
109
|
+
97 => 'vdsl',
|
110
|
+
98 => 'iso88025CRFPInt',
|
111
|
+
99 => 'myrinet',
|
112
|
+
100 => 'voiceEM',
|
113
|
+
101 => 'voiceFXO',
|
114
|
+
102 => 'voiceFXS',
|
115
|
+
103 => 'voiceEncap',
|
116
|
+
104 => 'voiceOverIp',
|
117
|
+
105 => 'atmDxi',
|
118
|
+
106 => 'atmFuni',
|
119
|
+
107 => 'atmIma',
|
120
|
+
108 => 'pppMultilinkBundle',
|
121
|
+
109 => 'ipOverCdlc',
|
122
|
+
110 => 'ipOverClaw',
|
123
|
+
111 => 'stackToStack',
|
124
|
+
112 => 'virtualIpAddress',
|
125
|
+
113 => 'mpc',
|
126
|
+
114 => 'ipOverAtm',
|
127
|
+
115 => 'iso88025Fiber',
|
128
|
+
116 => 'tdlc',
|
129
|
+
117 => 'gigabitEthernet',
|
130
|
+
118 => 'hdlc',
|
131
|
+
119 => 'lapf',
|
132
|
+
120 => 'v37',
|
133
|
+
121 => 'x25mlp',
|
134
|
+
122 => 'x25huntGroup',
|
135
|
+
123 => 'transpHdlc',
|
136
|
+
124 => 'interleave',
|
137
|
+
125 => 'fast',
|
138
|
+
126 => 'ip',
|
139
|
+
127 => 'docsCableMaclayer',
|
140
|
+
128 => 'docsCableDownstream',
|
141
|
+
129 => 'docsCableUpstream',
|
142
|
+
130 => 'a12MppSwitch',
|
143
|
+
131 => 'tunnel',
|
144
|
+
132 => 'coffee',
|
145
|
+
133 => 'ces',
|
146
|
+
134 => 'atmSubInterface',
|
147
|
+
135 => 'l2vlan',
|
148
|
+
136 => 'l3ipvlan',
|
149
|
+
137 => 'l3ipxvlan',
|
150
|
+
138 => 'digitalPowerline',
|
151
|
+
139 => 'mediaMailOverIp',
|
152
|
+
140 => 'dtm',
|
153
|
+
141 => 'dcn',
|
154
|
+
142 => 'ipForward',
|
155
|
+
143 => 'msdsl',
|
156
|
+
144 => 'ieee1394',
|
157
|
+
145 => 'if-gsn',
|
158
|
+
146 => 'dvbRccMacLayer',
|
159
|
+
147 => 'dvbRccDownstream',
|
160
|
+
148 => 'dvbRccUpstream',
|
161
|
+
149 => 'atmVirtual',
|
162
|
+
150 => 'mplsTunnel',
|
163
|
+
151 => 'srp',
|
164
|
+
152 => 'voiceOverAtm',
|
165
|
+
153 => 'voiceOverFrameRelay',
|
166
|
+
154 => 'idsl',
|
167
|
+
155 => 'compositeLink',
|
168
|
+
156 => 'ss7SigLink',
|
169
|
+
157 => 'propWirelessP2P',
|
170
|
+
158 => 'frForward',
|
171
|
+
159 => 'rfc1483',
|
172
|
+
160 => 'usb',
|
173
|
+
161 => 'ieee8023adLag',
|
174
|
+
162 => 'bgppolicyaccounting',
|
175
|
+
163 => 'frf16MfrBundle',
|
176
|
+
164 => 'h323Gatekeeper',
|
177
|
+
165 => 'h323Proxy',
|
178
|
+
166 => 'mpls',
|
179
|
+
167 => 'mfSigLink',
|
180
|
+
168 => 'hdsl2',
|
181
|
+
169 => 'shdsl',
|
182
|
+
170 => 'ds1FDL',
|
183
|
+
171 => 'pos',
|
184
|
+
172 => 'dvbAsiIn',
|
185
|
+
173 => 'dvbAsiOut',
|
186
|
+
174 => 'plc',
|
187
|
+
175 => 'nfas',
|
188
|
+
176 => 'tr008',
|
189
|
+
177 => 'gr303RDT',
|
190
|
+
178 => 'gr303IDT',
|
191
|
+
179 => 'isup',
|
192
|
+
180 => 'propDocsWirelessMaclayer',
|
193
|
+
181 => 'propDocsWirelessDownstream',
|
194
|
+
182 => 'propDocsWirelessUpstream',
|
195
|
+
183 => 'hiperlan2',
|
196
|
+
184 => 'propBWAp2Mp',
|
197
|
+
185 => 'sonetOverheadChannel',
|
198
|
+
186 => 'digitalWrapperOverheadChannel',
|
199
|
+
187 => 'aal2',
|
200
|
+
188 => 'radioMAC',
|
201
|
+
189 => 'atmRadio',
|
202
|
+
190 => 'imt',
|
203
|
+
191 => 'mvl',
|
204
|
+
192 => 'reachDSL',
|
205
|
+
193 => 'frDlciEndPt',
|
206
|
+
194 => 'atmVciEndPt',
|
207
|
+
195 => 'opticalChannel',
|
208
|
+
196 => 'opticalTransport',
|
209
|
+
197 => 'propAtm',
|
210
|
+
198 => 'voiceOverCable',
|
211
|
+
199 => 'infiniband',
|
212
|
+
200 => 'teLink',
|
213
|
+
201 => 'q2931',
|
214
|
+
202 => 'virtualTg',
|
215
|
+
203 => 'sipTg',
|
216
|
+
204 => 'sipSig',
|
217
|
+
205 => 'docsCableUpstreamChannel',
|
218
|
+
206 => 'econet',
|
219
|
+
207 => 'pon155',
|
220
|
+
208 => 'pon622',
|
221
|
+
209 => 'bridge',
|
222
|
+
210 => 'linegroup',
|
223
|
+
211 => 'voiceEMFGD',
|
224
|
+
212 => 'voiceFGDEANA',
|
225
|
+
213 => 'voiceDID',
|
226
|
+
214 => 'mpegTransport',
|
227
|
+
215 => 'sixToFour',
|
228
|
+
216 => 'gtp',
|
229
|
+
217 => 'pdnEtherLoop1',
|
230
|
+
218 => 'pdnEtherLoop2',
|
231
|
+
219 => 'opticalChannelGroup',
|
232
|
+
220 => 'homepna',
|
233
|
+
221 => 'gfp',
|
234
|
+
222 => 'ciscoISLvlan',
|
235
|
+
223 => 'actelisMetaLOOP',
|
236
|
+
224 => 'fcipLink',
|
237
|
+
225 => 'rpr',
|
238
|
+
226 => 'qam',
|
239
|
+
227 => 'lmp',
|
240
|
+
228 => 'cblVectaStar',
|
241
|
+
229 => 'docsCableMCmtsDownstream',
|
242
|
+
230 => 'adsl2',
|
243
|
+
231 => 'macSecControlledIF',
|
244
|
+
232 => 'macSecUncontrolledIF',
|
245
|
+
233 => 'aviciOpticalEther',
|
246
|
+
234 => 'atmbond',
|
247
|
+
235 => 'voiceFGDOS',
|
248
|
+
236 => 'mocaVersion1',
|
249
|
+
237 => 'ieee80216WMAN',
|
250
|
+
238 => 'adsl2plus',
|
251
|
+
239 => 'dvbRcsMacLayer',
|
252
|
+
240 => 'dvbTdm',
|
253
|
+
241 => 'dvbRcsTdma',
|
254
|
+
242 => 'x86Laps',
|
255
|
+
243 => 'wwanPP',
|
256
|
+
244 => 'wwanPP2',
|
257
|
+
245 => 'voiceEBS',
|
258
|
+
246 => 'ifPwType',
|
259
|
+
247 => 'ilan',
|
260
|
+
248 => 'pip',
|
261
|
+
249 => 'aluELP',
|
262
|
+
250 => 'gpon',
|
263
|
+
251 => 'vdsl2',
|
264
|
+
252 => 'capwapDot11Profile',
|
265
|
+
253 => 'capwapDot11Bss',
|
266
|
+
254 => 'capwapWtpVirtualRadio',
|
267
|
+
255 => 'bits',
|
268
|
+
256 => 'docsCableUpstreamRfPort',
|
269
|
+
257 => 'cableDownstreamRfPort',
|
270
|
+
258 => 'vmwareVirtualNic',
|
271
|
+
259 => 'ieee802154',
|
272
|
+
260 => 'otnOdu',
|
273
|
+
261 => 'otnOtu',
|
274
|
+
262 => 'ifVfiType',
|
275
|
+
263 => 'g9981',
|
276
|
+
264 => 'g9982',
|
277
|
+
265 => 'g9983',
|
278
|
+
266 => 'aluEpon',
|
279
|
+
267 => 'aluEponOnu',
|
280
|
+
268 => 'aluEponPhysicalUni',
|
281
|
+
269 => 'aluEponLogicalLink',
|
282
|
+
270 => 'aluGponOnu',
|
283
|
+
271 => 'aluGponPhysicalUni',
|
284
|
+
272 => 'vmwareNicTeam',
|
285
|
+
}
|
286
|
+
data.map do |item|
|
287
|
+
item[2] = "#{item[2]} (#{types[item[2]]})"
|
288
|
+
item[6] = "#{item[6]} (#{admin_states[item[6]-1]})"
|
289
|
+
item[7] = "#{item[7]} (#{oper_states[item[7]-1]})"
|
290
|
+
item[8] = item[8].to_s # Timeticks for last change
|
291
|
+
item
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end # IfTable Converter
|
295
|
+
|
296
|
+
end # module SNMPTableViewer
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SNMPTableViewer
|
2
|
+
|
3
|
+
# Class to fetch the information from an SNMP host.
|
4
|
+
class Fetcher
|
5
|
+
|
6
|
+
# Fetch the data using SNMP.
|
7
|
+
# @param base_oid [String] The OID to start the SNMP walk from
|
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])
|
10
|
+
def self.from_snmp(base_oid:, **snmp_options)
|
11
|
+
data = Array.new
|
12
|
+
NETSNMP::Client.new(snmp_options) do |manager|
|
13
|
+
manager.walk(oid: base_oid).each do |oid, value|
|
14
|
+
col, row = oid.split('.')[-2..-1].map{ |i| i.to_i - 1}
|
15
|
+
data[row] ||= []
|
16
|
+
data[row][col] = value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
data
|
20
|
+
end
|
21
|
+
|
22
|
+
end # class Fetcher
|
23
|
+
|
24
|
+
end # module SNMPTableViewer
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module SNMPTableViewer
|
2
|
+
|
3
|
+
# Formatting class for CSV output.
|
4
|
+
class Formatter::CSV < Formatter
|
5
|
+
# Output the data (and headings if provided).
|
6
|
+
# @return [String] the CSV data
|
7
|
+
def output()
|
8
|
+
data_with_headings.map(&:to_csv).join
|
9
|
+
end
|
10
|
+
end # CSV Formatter
|
11
|
+
|
12
|
+
end # module SNMPTableViewer
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module SNMPTableViewer
|
2
|
+
|
3
|
+
# Formatting class for JSON output
|
4
|
+
class Formatter::JSON < Formatter
|
5
|
+
# Output the data. If no headings are provided you'll get an Array or Arrays. If headings are provided you'll get an Array of Hashes.
|
6
|
+
# @return [String] the JSON data
|
7
|
+
def output()
|
8
|
+
data = @data
|
9
|
+
if @headings.size > 0
|
10
|
+
# Convert inner arrays to hashes
|
11
|
+
data = data.map{ |row| Hash[row.map.with_index{ |value, index| [@headings[index] || '', value] }] }
|
12
|
+
end
|
13
|
+
::JSON.generate(data)
|
14
|
+
end
|
15
|
+
end # JSON Formatter
|
16
|
+
|
17
|
+
end # module SNMPTableViewer
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module SNMPTableViewer
|
2
|
+
|
3
|
+
# Formatting class for raw output.
|
4
|
+
class Formatter::Raw < Formatter
|
5
|
+
# Output the data (and headings if provided).
|
6
|
+
# @return [String] the raw data
|
7
|
+
def output()
|
8
|
+
data_with_headings.inspect
|
9
|
+
end
|
10
|
+
end # Raw Fromatter
|
11
|
+
|
12
|
+
end # module SNMPTableViewer
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module SNMPTableViewer
|
2
|
+
|
3
|
+
# Formatting class for Table output.
|
4
|
+
class Formatter::Table < Formatter
|
5
|
+
# Output the data (and headings if provided) as a table which can be displayed in the terminal.
|
6
|
+
# @param transpose [Boolean] Whether to swap rows and columns - useful for displaying a wide and short table
|
7
|
+
# @return [String] the text to display in order to draw the table
|
8
|
+
def output(transpose: false)
|
9
|
+
use_headings = @headings.size > 0
|
10
|
+
data = @data
|
11
|
+
|
12
|
+
if transpose
|
13
|
+
# transpose the data
|
14
|
+
if use_headings
|
15
|
+
data = [@headings, *data].transpose
|
16
|
+
use_headings = false # Don't add headings twice
|
17
|
+
else
|
18
|
+
data = data.transpose
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
if use_headings
|
23
|
+
Terminal::Table.new(rows: data, headings: @headings).to_s
|
24
|
+
else
|
25
|
+
Terminal::Table.new(rows: data).to_s
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end # Table Formatter
|
29
|
+
|
30
|
+
end # module SNMPTableViewer
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module SNMPTableViewer
|
2
|
+
|
3
|
+
# Parent class for formatters. Which take data and headings and output it in a given format.
|
4
|
+
# @abstract
|
5
|
+
class Formatter
|
6
|
+
|
7
|
+
# Create a new instance of Formatter.
|
8
|
+
# @param data [Array<Array<#to_s>>] A two dimensional array containing objects in each cell (at 'address' data[row][col])
|
9
|
+
# @param headings [Array<String, #to_s>] An array of headings for each column
|
10
|
+
# @return [Formatter]
|
11
|
+
def initialize(data:, headings: [])
|
12
|
+
@headings = headings
|
13
|
+
@data = data
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
# Get a two dimensioan array of headings prepended to the data or just the data (if no headings were provided).
|
18
|
+
# @return Array<Array<#to_s>>
|
19
|
+
def data_with_headings
|
20
|
+
has_headings? ? [@headings, *@data] : @data
|
21
|
+
end
|
22
|
+
# Determine if headings were passed.
|
23
|
+
# @return [Boolean]
|
24
|
+
def has_headings?
|
25
|
+
@headings.is_a?(Array) && @headings.size > 0
|
26
|
+
end
|
27
|
+
|
28
|
+
end # Formatter base class
|
29
|
+
|
30
|
+
end # module SNMPTableViewer
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Require gems
|
2
|
+
require 'netsnmp'
|
3
|
+
require 'terminal-table'
|
4
|
+
|
5
|
+
# Require from standard ruby libraries
|
6
|
+
require 'csv'
|
7
|
+
require 'json'
|
8
|
+
|
9
|
+
# Load the other files in the lib directory
|
10
|
+
require_relative '../version'
|
11
|
+
Dir["#{File.dirname(__FILE__)}/**/*.rb"].select{ |f| f != __FILE__}.sort.each { |f| load(f) }
|
12
|
+
|
13
|
+
module SNMPTableViewer
|
14
|
+
end # module SNMPTableViewer
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require File.join(File.dirname(__FILE__), 'version')
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "snmp_table_viewer"
|
7
|
+
s.license = 'BSD 3 clause'
|
8
|
+
s.version = SNMPTableViewer::VERSION
|
9
|
+
s.authors = ['Robert Gauld']
|
10
|
+
s.email = ['robert@robertgauld.co.uk']
|
11
|
+
s.homepage = 'https://github.com/robertgauld/snmp-table-viewer'
|
12
|
+
s.summary = %q{Easily view SNMP tables.}
|
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
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_runtime_dependency 'netsnmp', '~> 0.1.3'
|
21
|
+
s.add_runtime_dependency 'terminal-table', '~> 1.8.0'
|
22
|
+
|
23
|
+
s.add_development_dependency 'rake', '~> 12.0'
|
24
|
+
s.add_development_dependency 'rspec', '>= 2.14.1', '< 4'
|
25
|
+
s.add_development_dependency 'guard-rspec', '~> 4.2', '>= 4.2.5'
|
26
|
+
s.add_development_dependency 'rb-inotify', '~> 0.9'
|
27
|
+
s.add_development_dependency 'coveralls', '~> 0.7'
|
28
|
+
s.add_development_dependency 'simplecov', '~> 0.7'
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
describe SNMPTableViewer::Converter::IfTable do
|
2
|
+
|
3
|
+
describe '#convert' do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@input = [[1, "lo", 24, 65536, nil, "", 1, 2, NETSNMP::Timetick.new(100), 18985, 220, 0, 0, 0, 0, 18985, 220, 0, 0, 0, nil, "0.0"]]
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'Converts type' do
|
10
|
+
output = described_class.convert(@input)[0]
|
11
|
+
expect(output[2]).to eq '24 (softwareLoopback)'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'Converts admin state' do
|
15
|
+
output = described_class.convert(@input)[0]
|
16
|
+
expect(output[6]).to eq '1 (up)'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'Converts oper state' do
|
20
|
+
output = described_class.convert(@input)[0]
|
21
|
+
expect(output[7]).to eq '2 (down)'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'Converts last change' do
|
25
|
+
output = described_class.convert(@input)[0]
|
26
|
+
expect(output[8]).to eq 'Timeticks: (100) 0 days, 0:0:1.0'
|
27
|
+
end
|
28
|
+
|
29
|
+
end # describe #convert
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
# [1, "lo", 24, 65536, nil, "", 1, 1, NETSNMP::Timetick.new(100), 18985, 220, 0, 0, 0, 0, 18985, 220, 0, 0, 0, nil, "0.0"]
|
@@ -0,0 +1,23 @@
|
|
1
|
+
describe SNMPTableViewer::Fetcher do
|
2
|
+
|
3
|
+
it 'Fetches' do
|
4
|
+
snmp_options = {opt_a: :a}
|
5
|
+
manager = double("manager")
|
6
|
+
expect(manager).to receive(:walk).with(oid: '1.2.3.4.5').once.and_return([
|
7
|
+
['1.2.3.4.5.0.1.1', 1],
|
8
|
+
['1.2.3.4.5.0.1.2', 2],
|
9
|
+
['1.2.3.4.5.0.2.1', 'a'],
|
10
|
+
['1.2.3.4.5.0.2.2', 'b'],
|
11
|
+
['1.2.3.4.5.0.3.1', 'A'],
|
12
|
+
['1.2.3.4.5.0.3.2', 'B'],
|
13
|
+
]) # Array returned by manager doing the SNMP walk
|
14
|
+
expect(NETSNMP::Client).to receive(:new).with(snmp_options).once do |&block|
|
15
|
+
block.call(manager)
|
16
|
+
end # expect block
|
17
|
+
expect(described_class.from_snmp(base_oid: '1.2.3.4.5', **snmp_options)).to eq [
|
18
|
+
[1, 'a', 'A'],
|
19
|
+
[2, 'b', 'B']
|
20
|
+
]
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
describe SNMPTableViewer::Formatter::CSV do
|
2
|
+
|
3
|
+
describe '#output' do
|
4
|
+
|
5
|
+
it 'With headings' do
|
6
|
+
headings = ['heading1', 'heading2', 'heading3']
|
7
|
+
data = [
|
8
|
+
['row1col1', 'row1col2', 'a,b'],
|
9
|
+
['row2col1', 'row2col2', 'b,c']
|
10
|
+
]
|
11
|
+
formatter = described_class.new(data: data, headings: headings)
|
12
|
+
expect(formatter.output).to eq "heading1,heading2,heading3\nrow1col1,row1col2,\"a,b\"\nrow2col1,row2col2,\"b,c\"\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'Without headings' do
|
16
|
+
data = [
|
17
|
+
['row1col1', 'row1col2', 'a,b'],
|
18
|
+
['row2col1', 'row2col2', 'b,c']
|
19
|
+
]
|
20
|
+
formatter = described_class.new(data: data)
|
21
|
+
expect(formatter.output).to eq "row1col1,row1col2,\"a,b\"\nrow2col1,row2col2,\"b,c\"\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
end # describe #output
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
describe SNMPTableViewer::Formatter::JSON do
|
2
|
+
|
3
|
+
describe '#output' do
|
4
|
+
|
5
|
+
it 'With headings' do
|
6
|
+
headings = ['heading1', 'heading2', 'heading3']
|
7
|
+
data = [
|
8
|
+
['row1col1', 'row1col2', 'a,b'],
|
9
|
+
['row2col1', 'row2col2', 'b,c']
|
10
|
+
]
|
11
|
+
formatter = described_class.new(data: data, headings: headings)
|
12
|
+
expect(formatter.output).to eq '[{"heading1":"row1col1","heading2":"row1col2","heading3":"a,b"},{"heading1":"row2col1","heading2":"row2col2","heading3":"b,c"}]'
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'Without headings' do
|
16
|
+
data = [
|
17
|
+
['row1col1', 'row1col2', 'a,b'],
|
18
|
+
['row2col1', 'row2col2', 'b,c']
|
19
|
+
]
|
20
|
+
formatter = described_class.new(data: data)
|
21
|
+
expect(formatter.output).to eq '[["row1col1","row1col2","a,b"],["row2col1","row2col2","b,c"]]'
|
22
|
+
end
|
23
|
+
|
24
|
+
end # describe #output
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
describe SNMPTableViewer::Formatter::Raw do
|
2
|
+
|
3
|
+
describe '#output' do
|
4
|
+
|
5
|
+
it 'With headings' do
|
6
|
+
headings = ['heading1', 'heading2', 'heading3']
|
7
|
+
data = [
|
8
|
+
['row1col1', 'row1col2', 'a,b'],
|
9
|
+
['row2col1', 'row2col2', 'b,c']
|
10
|
+
]
|
11
|
+
formatter = described_class.new(data: data, headings: headings)
|
12
|
+
expect(formatter.output).to eq '[["heading1", "heading2", "heading3"], ["row1col1", "row1col2", "a,b"], ["row2col1", "row2col2", "b,c"]]'
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'Without headings' do
|
16
|
+
data = [
|
17
|
+
['row1col1', 'row1col2', 'a,b'],
|
18
|
+
['row2col1', 'row2col2', 'b,c']
|
19
|
+
]
|
20
|
+
formatter = described_class.new(data: data)
|
21
|
+
expect(formatter.output).to eq '[["row1col1", "row1col2", "a,b"], ["row2col1", "row2col2", "b,c"]]'
|
22
|
+
end
|
23
|
+
|
24
|
+
end # describe #output
|
25
|
+
|
26
|
+
end
|