snmp_table_viewer 0.0.4
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 +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
|