oxidized 0.34.3 → 0.35.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 +4 -4
- data/.github/workflows/codeql.yml +4 -4
- data/.github/workflows/publishdocker.yml +82 -11
- data/.github/workflows/ruby.yml +1 -1
- data/.github/workflows/stale.yml +1 -1
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +1 -1
- data/CHANGELOG.md +39 -1
- data/Dockerfile +74 -66
- data/README.md +2 -2
- data/Rakefile +21 -3
- data/docs/Configuration.md +92 -0
- data/docs/Creating-Models.md +85 -19
- data/docs/Ruby-API.md +52 -0
- data/docs/Supported-OS-Types.md +4 -1
- data/extra/oxidized.runit +1 -1
- data/lib/oxidized/core.rb +2 -1
- data/lib/oxidized/input/http.rb +9 -2
- data/lib/oxidized/input/scp.rb +3 -3
- data/lib/oxidized/input/ssh.rb +3 -3
- data/lib/oxidized/input/telnet.rb +2 -2
- data/lib/oxidized/model/adva.rb +1 -1
- data/lib/oxidized/model/airfiber.rb +1 -1
- data/lib/oxidized/model/aoscx.rb +29 -44
- data/lib/oxidized/model/aosw.rb +1 -1
- data/lib/oxidized/model/arubainstant.rb +18 -6
- data/lib/oxidized/model/asternos.rb +1 -1
- data/lib/oxidized/model/axos.rb +1 -1
- data/lib/oxidized/model/comtrol.rb +1 -1
- data/lib/oxidized/model/cumulus.rb +2 -7
- data/lib/oxidized/model/eatonnetwork.rb +5 -0
- data/lib/oxidized/model/eltex.rb +1 -1
- data/lib/oxidized/model/enterasys800.rb +1 -1
- data/lib/oxidized/model/fabricos.rb +1 -1
- data/lib/oxidized/model/fsos.rb +1 -1
- data/lib/oxidized/model/garderos.rb +1 -6
- data/lib/oxidized/model/ironware.rb +1 -1
- data/lib/oxidized/model/mlnxos.rb +3 -10
- data/lib/oxidized/model/model.rb +101 -12
- data/lib/oxidized/model/netgear.rb +1 -0
- data/lib/oxidized/model/netonix.rb +1 -1
- data/lib/oxidized/model/netscaler.rb +1 -1
- data/lib/oxidized/model/nxos.rb +9 -9
- data/lib/oxidized/model/onefinity.rb +1 -1
- data/lib/oxidized/model/opnsense.rb +8 -0
- data/lib/oxidized/model/perle.rb +35 -0
- data/lib/oxidized/model/pfsense.rb +8 -0
- data/lib/oxidized/model/saos10.rb +1 -1
- data/lib/oxidized/model/siklu.rb +1 -1
- data/lib/oxidized/model/siklumhtg.rb +1 -1
- data/lib/oxidized/model/sixwind.rb +1 -1
- data/lib/oxidized/model/slxos.rb +1 -1
- data/lib/oxidized/model/sonicos.rb +1 -1
- data/lib/oxidized/model/speedtouch.rb +1 -1
- data/lib/oxidized/model/telco.rb +1 -1
- data/lib/oxidized/model/tnsr.rb +7 -3
- data/lib/oxidized/model/trango.rb +1 -1
- data/lib/oxidized/model/ucs.rb +1 -1
- data/lib/oxidized/model/voltaire.rb +1 -1
- data/lib/oxidized/model/vyatta.rb +1 -1
- data/lib/oxidized/model/vyos.rb +34 -0
- data/lib/oxidized/model/zhoneolt.rb +1 -1
- data/lib/oxidized/model/zynoscli.rb +1 -1
- data/lib/oxidized/node.rb +6 -1
- data/lib/oxidized/source/http.rb +10 -2
- data/lib/oxidized/version.rb +2 -2
- data/oxidized.gemspec +4 -5
- metadata +13 -29
- data/lib/oxidized/model/timos.rb +0 -10
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
class MLNXOS < Oxidized::Model
|
|
2
2
|
using Refinements
|
|
3
3
|
|
|
4
|
-
prompt /^\r
|
|
4
|
+
prompt /^\r?\S* \[\S+: (master|standby)\] [#>] $/
|
|
5
5
|
comment '## '
|
|
6
|
+
clean :escape_codes
|
|
6
7
|
|
|
7
8
|
# Pager Handling
|
|
8
9
|
# "Normal" pager: "lines 183-204 "
|
|
9
10
|
# Last pager: "lines 256-269/269 (END) "
|
|
10
|
-
expect
|
|
11
|
+
expect /lines \d+-\d+( |\/\d+ \(END\) )/ do |data, re|
|
|
11
12
|
send ' '
|
|
12
13
|
data.sub re, ''
|
|
13
14
|
end
|
|
14
15
|
|
|
15
|
-
# Remove ANSI escape codes
|
|
16
|
-
expect /\e\[[0-?]*[ -\/]*[@-~]\r?/ do |data, re|
|
|
17
|
-
data.sub re, ''
|
|
18
|
-
end
|
|
19
|
-
|
|
20
16
|
cmd :all do |cfg|
|
|
21
|
-
cfg.gsub! "\e[m", '' # Remove reset formating
|
|
22
|
-
cfg.gsub! "\e[K", '' # Remove erase in line
|
|
23
17
|
cfg.gsub! /.\x08/, '' # Remove Backspace char
|
|
24
|
-
cfg.gsub! "\r", '' # Remove Cariage Return
|
|
25
18
|
cfg.gsub! /^CPU load averages:\s.+/, '' # Omit constantly changing CPU info
|
|
26
19
|
cfg.gsub! /^System memory:\s.+/, '' # Omit constantly changing memory info
|
|
27
20
|
cfg.gsub! /^Uptime:\s.+/, '' # Omit constantly changing uptime info
|
data/lib/oxidized/model/model.rb
CHANGED
|
@@ -9,18 +9,22 @@ module Oxidized
|
|
|
9
9
|
|
|
10
10
|
include Oxidized::Config::Vars
|
|
11
11
|
|
|
12
|
+
# rubocop:disable Style/FormatStringToken
|
|
13
|
+
METADATA_DEFAULT = "%{comment}Fetched by Oxidized with model %{model} " \
|
|
14
|
+
"from host %{name} [%{ip}]\n".freeze
|
|
15
|
+
# rubocop:enable Style/FormatStringToken
|
|
16
|
+
|
|
12
17
|
class << self
|
|
13
18
|
def inherited(klass)
|
|
14
19
|
super
|
|
15
20
|
if klass.superclass == Oxidized::Model
|
|
16
|
-
|
|
17
|
-
klass.instance_variable_set
|
|
18
|
-
klass.instance_variable_set
|
|
19
|
-
klass.instance_variable_set '@procs', (Hash.new { |h, k| h[k] = [] })
|
|
20
|
-
# rubocop:enable Style/RedundantParentheses
|
|
21
|
+
klass.instance_variable_set('@cmd', Hash.new { |h, k| h[k] = [] })
|
|
22
|
+
klass.instance_variable_set('@cfg', Hash.new { |h, k| h[k] = [] })
|
|
23
|
+
klass.instance_variable_set('@procs', Hash.new { |h, k| h[k] = [] })
|
|
21
24
|
klass.instance_variable_set '@expect', []
|
|
22
25
|
klass.instance_variable_set '@comment', nil
|
|
23
26
|
klass.instance_variable_set '@prompt', nil
|
|
27
|
+
klass.instance_variable_set '@metadata', {}
|
|
24
28
|
else # we're subclassing some existing model, take its variables
|
|
25
29
|
instance_variables.each do |var|
|
|
26
30
|
iv = instance_variable_get(var)
|
|
@@ -58,11 +62,23 @@ module Oxidized
|
|
|
58
62
|
if cmd_arg.instance_of?(Symbol)
|
|
59
63
|
process_args_block(@cmd[cmd_arg], args, block)
|
|
60
64
|
else
|
|
61
|
-
|
|
65
|
+
# Normal command
|
|
66
|
+
process_args_block(@cmd[:cmd], args,
|
|
67
|
+
{ cmd: cmd_arg, args: args, block: block })
|
|
62
68
|
end
|
|
63
69
|
logger.debug "Added #{cmd_arg} to the commands list"
|
|
64
70
|
end
|
|
65
71
|
|
|
72
|
+
def metadata(position, value = nil, &block)
|
|
73
|
+
return unless %i[top bottom].include? position
|
|
74
|
+
|
|
75
|
+
if block_given?
|
|
76
|
+
@metadata[position] = block
|
|
77
|
+
else
|
|
78
|
+
@metadata[position] = value
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
66
82
|
def cmds
|
|
67
83
|
@cmd
|
|
68
84
|
end
|
|
@@ -75,11 +91,33 @@ module Oxidized
|
|
|
75
91
|
@expect
|
|
76
92
|
end
|
|
77
93
|
|
|
94
|
+
def clean(what)
|
|
95
|
+
case what
|
|
96
|
+
when :escape_codes
|
|
97
|
+
ansi_escape_regex = /
|
|
98
|
+
\r? # Optional carriage return at start
|
|
99
|
+
\e # ESC character - starts escape sequence
|
|
100
|
+
(?: # Non-capturing group for different sequence types:
|
|
101
|
+
# Type 1: CSI (Control Sequence Introducer)
|
|
102
|
+
\[ # Literal '[' - starts CSI sequence
|
|
103
|
+
[0-?]* # Parameter bytes: digits (0-9), semicolon, colon, etc.
|
|
104
|
+
[ -\/]* # Intermediate bytes: space through slash characters
|
|
105
|
+
[@-~] # Final byte: determines the actual command
|
|
106
|
+
| # OR
|
|
107
|
+
# Type 2: Simple escape
|
|
108
|
+
[=>] # Single character commands after ESC
|
|
109
|
+
)
|
|
110
|
+
\r? # Optional carriage return at end
|
|
111
|
+
/x
|
|
112
|
+
expect ansi_escape_regex do |data, re|
|
|
113
|
+
data.gsub re, ''
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
78
118
|
# calls the block at the end of the model, prepending the output of the
|
|
79
119
|
# block to the output string
|
|
80
120
|
#
|
|
81
|
-
# @author Saku Ytti <saku@ytti.fi>
|
|
82
|
-
# @since 0.0.39
|
|
83
121
|
# @yield expects block which should return [String]
|
|
84
122
|
# @return [void]
|
|
85
123
|
def pre(**args, &block)
|
|
@@ -89,8 +127,6 @@ module Oxidized
|
|
|
89
127
|
# calls the block at the end of the model, adding the output of the block
|
|
90
128
|
# to the output string
|
|
91
129
|
#
|
|
92
|
-
# @author Saku Ytti <saku@ytti.fi>
|
|
93
|
-
# @since 0.0.39
|
|
94
130
|
# @yield expects block which should return [String]
|
|
95
131
|
# @return [void]
|
|
96
132
|
def post(**args, &block)
|
|
@@ -109,6 +145,9 @@ module Oxidized
|
|
|
109
145
|
if block.instance_of?(Array)
|
|
110
146
|
target.reject! { |k, _| k == block[0] }
|
|
111
147
|
target.push(block)
|
|
148
|
+
elsif block.instance_of?(Hash)
|
|
149
|
+
target.reject! { |item| item[:cmd] == block[:cmd] }
|
|
150
|
+
target.push(block)
|
|
112
151
|
else
|
|
113
152
|
target.replace([block])
|
|
114
153
|
end
|
|
@@ -139,6 +178,44 @@ module Oxidized
|
|
|
139
178
|
process_cmd_output out, string
|
|
140
179
|
end
|
|
141
180
|
|
|
181
|
+
def metadata(position)
|
|
182
|
+
return unless %i[top bottom].include? position
|
|
183
|
+
|
|
184
|
+
model_metadata = self.class.instance_variable_get(:@metadata)
|
|
185
|
+
var_position = { top: "metadata_top", bottom: "metadata_bottom" }
|
|
186
|
+
if model_metadata[:top] || model_metadata[:bottom]
|
|
187
|
+
# the model defines metadata at :top ot :bottom, use the model
|
|
188
|
+
value = model_metadata[position]
|
|
189
|
+
value.is_a?(Proc) ? instance_eval(&value) : interpolate_string(value)
|
|
190
|
+
elsif vars("metadata_top") || vars("metadata_bottom")
|
|
191
|
+
# vars defines metadata_top or metadata bottom, use the vars
|
|
192
|
+
interpolate_string(vars(var_position[position]))
|
|
193
|
+
elsif position == :top
|
|
194
|
+
# default: use METADATA_DEFAULT for top
|
|
195
|
+
interpolate_string(METADATA_DEFAULT)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def interpolate_string(template)
|
|
200
|
+
return nil unless template
|
|
201
|
+
|
|
202
|
+
time = Time.now
|
|
203
|
+
template_variables = {
|
|
204
|
+
model: self.class.name,
|
|
205
|
+
name: node.name,
|
|
206
|
+
ip: node.ip,
|
|
207
|
+
group: node.group,
|
|
208
|
+
comment: self.class.comment,
|
|
209
|
+
year: time.year,
|
|
210
|
+
month: "%02d" % time.month,
|
|
211
|
+
day: "%02d" % time.day,
|
|
212
|
+
hour: "%02d" % time.hour,
|
|
213
|
+
minute: "%02d" % time.min,
|
|
214
|
+
second: "%02d" % time.sec
|
|
215
|
+
}
|
|
216
|
+
template % template_variables
|
|
217
|
+
end
|
|
218
|
+
|
|
142
219
|
def output
|
|
143
220
|
@input.output
|
|
144
221
|
end
|
|
@@ -171,19 +248,31 @@ module Oxidized
|
|
|
171
248
|
def get
|
|
172
249
|
logger.debug 'Collecting commands\' outputs'
|
|
173
250
|
outputs = Outputs.new
|
|
174
|
-
|
|
175
|
-
|
|
251
|
+
self.class.cmds[:cmd].each do |data|
|
|
252
|
+
command = data[:cmd]
|
|
253
|
+
args = data[:args]
|
|
254
|
+
block = data[:block]
|
|
255
|
+
|
|
256
|
+
next if args.include?(:if) && !instance_exec(&args[:if])
|
|
257
|
+
|
|
176
258
|
out = cmd command, &block
|
|
177
259
|
return false unless out
|
|
178
260
|
|
|
179
261
|
outputs << out
|
|
180
262
|
end
|
|
263
|
+
procs = self.class.procs
|
|
181
264
|
procs[:pre].each do |pre_proc|
|
|
182
265
|
outputs.unshift process_cmd_output(instance_eval(&pre_proc), '')
|
|
183
266
|
end
|
|
184
267
|
procs[:post].each do |post_proc|
|
|
185
268
|
outputs << process_cmd_output(instance_eval(&post_proc), '')
|
|
186
269
|
end
|
|
270
|
+
if vars("metadata") == true
|
|
271
|
+
metadata_top = metadata(:top)
|
|
272
|
+
metadata_bottom = metadata(:bottom)
|
|
273
|
+
outputs.unshift metadata_top if metadata_top
|
|
274
|
+
outputs << metadata_bottom if metadata_bottom
|
|
275
|
+
end
|
|
187
276
|
outputs
|
|
188
277
|
end
|
|
189
278
|
|
data/lib/oxidized/model/nxos.rb
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
class NXOS < Oxidized::Model
|
|
2
2
|
using Refinements
|
|
3
3
|
|
|
4
|
-
prompt /^(\r?[\w.@_()-]
|
|
4
|
+
prompt /^(\r?[\w.@_()-]+\#\s?)$/
|
|
5
5
|
comment '! '
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
cfg.
|
|
9
|
-
cfg.gsub! prompt, ''
|
|
7
|
+
cmd :all do |cfg|
|
|
8
|
+
cfg.cut_both
|
|
10
9
|
end
|
|
11
10
|
|
|
12
11
|
cmd :secret do |cfg|
|
|
@@ -21,21 +20,22 @@ class NXOS < Oxidized::Model
|
|
|
21
20
|
end
|
|
22
21
|
|
|
23
22
|
cmd 'show version' do |cfg|
|
|
24
|
-
cfg = filter cfg
|
|
25
23
|
cfg = cfg.each_line.take_while { |line| not line.match(/uptime|bootflash:\s+\d+\skB|sysmgrcli_show_flash_size/i) }
|
|
26
|
-
comment cfg.join
|
|
24
|
+
comment cfg.join + "\n"
|
|
27
25
|
end
|
|
28
26
|
|
|
29
27
|
cmd 'show inventory all' do |cfg|
|
|
30
|
-
cfg
|
|
28
|
+
if cfg.include? "% Invalid parameter detected at '^' marker."
|
|
29
|
+
# 'show inventory all' isn't supported on older versions (See Issue #3657)
|
|
30
|
+
cfg = cmd 'show inventory'
|
|
31
|
+
end
|
|
31
32
|
comment cfg
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
cmd 'show running-config' do |cfg|
|
|
35
|
-
cfg = filter cfg
|
|
36
36
|
cfg.gsub! /^(show run.*)$/, '! \1'
|
|
37
37
|
cfg.gsub! /^!Time:[^\n]*\n/, ''
|
|
38
|
-
cfg.gsub! /^[\w.@_()-]
|
|
38
|
+
cfg.gsub! /^[\w.@_()-]+\#.*$/, ''
|
|
39
39
|
cfg
|
|
40
40
|
end
|
|
41
41
|
|
|
@@ -22,6 +22,14 @@ class OpnSense < Oxidized::Model
|
|
|
22
22
|
xmlcomment version
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
metadata :bottom do
|
|
26
|
+
xmlcomment interpolate_string(
|
|
27
|
+
vars("metadata_bottom") ||
|
|
28
|
+
vars("metadata_top") ||
|
|
29
|
+
Oxidized::Model::METADATA_DEFAULT
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
25
33
|
cfg :ssh do
|
|
26
34
|
exec true
|
|
27
35
|
pre_logout 'exit'
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
class Perle < Oxidized::Model
|
|
2
|
+
using Refinements
|
|
3
|
+
|
|
4
|
+
prompt /^[\w.-]+#/
|
|
5
|
+
comment '! '
|
|
6
|
+
|
|
7
|
+
cmd :all do |cfg|
|
|
8
|
+
cfg.cut_both
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
cmd 'show version verbose' do |cfg|
|
|
12
|
+
comment cfg
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
cmd 'show system hardware' do |cfg|
|
|
16
|
+
comment cfg + "\n"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
cmd 'show interfaces transceiver' do |cfg|
|
|
20
|
+
out = []
|
|
21
|
+
cfg.each_line do |line|
|
|
22
|
+
out << line if line =~ /SFP Information/
|
|
23
|
+
out << line if line =~ /Vendor Name/
|
|
24
|
+
out << line if line =~ /Vendor Serial Number/
|
|
25
|
+
end
|
|
26
|
+
comment out.join + "\n"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
cmd 'show running-config'
|
|
30
|
+
|
|
31
|
+
cfg :ssh do
|
|
32
|
+
post_login 'terminal length 0'
|
|
33
|
+
pre_logout 'exit'
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -26,6 +26,14 @@ class PfSense < Oxidized::Model
|
|
|
26
26
|
xmlcomment "PFsense #{version}"
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
metadata :bottom do
|
|
30
|
+
xmlcomment interpolate_string(
|
|
31
|
+
vars("metadata_bottom") ||
|
|
32
|
+
vars("metadata_top") ||
|
|
33
|
+
Oxidized::Model::METADATA_DEFAULT
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
|
|
29
37
|
cfg :ssh do
|
|
30
38
|
exec true
|
|
31
39
|
pre_logout 'exit'
|
data/lib/oxidized/model/siklu.rb
CHANGED
data/lib/oxidized/model/slxos.rb
CHANGED
|
@@ -16,7 +16,7 @@ class SLXOS < Oxidized::Model
|
|
|
16
16
|
cfg.gsub! /.*Power Usage.*/, '' # remove unwanted lines power usage
|
|
17
17
|
cfg.gsub! /^Update:.*$/, '' # remove unwanted current date
|
|
18
18
|
cfg.gsub! /Time A(live|wake).*/, '' # remove unwanted lines time alive/awake
|
|
19
|
-
cfg.gsub! /(
|
|
19
|
+
cfg.gsub! /(\[*)1(\]*)<->(\[*)2(\]*)(<->(\[*)3(\]*))*/, ''
|
|
20
20
|
|
|
21
21
|
comment cfg
|
|
22
22
|
end
|
data/lib/oxidized/model/telco.rb
CHANGED
data/lib/oxidized/model/tnsr.rb
CHANGED
|
@@ -13,14 +13,16 @@ class TNSR < Oxidized::Model
|
|
|
13
13
|
# received "\r\nVersion: 25.02-2\r\n\r\nFor information see 'show documentation'\r\n\r\n"
|
|
14
14
|
# received "\rbgp01 tnsr# "
|
|
15
15
|
# when the --More-- pager is the last line of paged output, the prompt contains \x08\x20\x08 orphans on the begin
|
|
16
|
+
# on older version (23.06) --More-- pager is sometimes misplaced
|
|
16
17
|
# you can look for context into spec simulation:
|
|
17
|
-
# spec/model/data/tnsr
|
|
18
|
-
# spec/model/data/tnsr
|
|
18
|
+
# spec/model/data/tnsr#TNSR_24.10-3_short-config#simulation.yaml
|
|
19
|
+
# spec/model/data/tnsr#TNSR_25.02-2_long-config-and-pager-at-last-line#simulation.yaml
|
|
20
|
+
# spec/model/data/tnsr#TNSR_23.06-3_with-misplaced-pager#simulation.yaml
|
|
19
21
|
prompt /^((\x08{8}\x20{8}\x08{8})?\r?[\w-]+\stnsr#\s?)$/
|
|
20
22
|
|
|
21
23
|
comment '! '
|
|
22
24
|
|
|
23
|
-
expect /^--More
|
|
25
|
+
expect /^--More--|--More--$/ do |data, re|
|
|
24
26
|
send ' '
|
|
25
27
|
data.sub re, ''
|
|
26
28
|
end
|
|
@@ -40,6 +42,8 @@ class TNSR < Oxidized::Model
|
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
cmd 'show version all' do |cfg|
|
|
45
|
+
# for older tnsr versions
|
|
46
|
+
cfg = cmd('show version') if cfg.to_s =~ /^CLI syntax error:.+Unknown command$/
|
|
43
47
|
comment cfg
|
|
44
48
|
end
|
|
45
49
|
|
|
@@ -14,7 +14,7 @@ class Trango < Oxidized::Model
|
|
|
14
14
|
out << ("opmode " + Regexp.last_match[1])
|
|
15
15
|
out << ("defaultopmode " + Regexp.last_match[2])
|
|
16
16
|
end
|
|
17
|
-
out << ("power " + Regexp.last_match[1]) if line =~ /\[Tx Power\] ([
|
|
17
|
+
out << ("power " + Regexp.last_match[1]) if line =~ /\[Tx Power\] ([-\d]+) dBm/
|
|
18
18
|
out << ("freq " + Regexp.last_match[1] + ' ' + Regexp.last_match[2]) if line =~ /\[Active Channel\] (\d+) (v|h)/
|
|
19
19
|
out << ("peerid " + Regexp.last_match[1]) if line =~ /\[Peer ID\] ([A-F0-9]+)/
|
|
20
20
|
out << ("utype " + Regexp.last_match[1]) if line =~ /\[Unit Type\] (\S+)/
|
data/lib/oxidized/model/ucs.rb
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class Vyos < Oxidized::Model
|
|
2
|
+
using Refinements
|
|
3
|
+
|
|
4
|
+
# VyOS model #
|
|
5
|
+
# Vyos is a Fork of Vyatta and is being actively developed.
|
|
6
|
+
# https://vyos.org/
|
|
7
|
+
|
|
8
|
+
prompt /^\S+@\S+(:~\$|>) $/
|
|
9
|
+
clean :escape_codes
|
|
10
|
+
|
|
11
|
+
cmd :all do |cfg|
|
|
12
|
+
cfg.lines.to_a[1..-2].join
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
cmd :secret do |cfg|
|
|
16
|
+
cfg.gsub! /secret (\S+).*/, 'secret <secret removed>'
|
|
17
|
+
cfg.gsub! /password (\S+).*/, 'password <secret removed>'
|
|
18
|
+
cfg.gsub! /community (\S+)/, 'community <secret removed>'
|
|
19
|
+
cfg.gsub! /private key (\S+).*/, 'private key <secret removed>'
|
|
20
|
+
# password in URLs like protocol://user:password@domain.tld/
|
|
21
|
+
cfg.gsub! /([a-z]+:\/\/[^:\s]+:)\S+@/, '\1<secret removed>@'
|
|
22
|
+
cfg
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
cmd 'show version' do |cfg|
|
|
26
|
+
comment cfg
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
cmd 'show configuration commands | no-more'
|
|
30
|
+
|
|
31
|
+
cfg :ssh do
|
|
32
|
+
pre_logout 'exit'
|
|
33
|
+
end
|
|
34
|
+
end
|
data/lib/oxidized/node.rb
CHANGED
|
@@ -7,7 +7,7 @@ module Oxidized
|
|
|
7
7
|
class Node
|
|
8
8
|
include SemanticLogger::Loggable
|
|
9
9
|
|
|
10
|
-
attr_reader :name, :ip, :model, :input, :output, :group, :auth, :prompt, :vars, :last, :repo
|
|
10
|
+
attr_reader :name, :ip, :model, :input, :output, :group, :auth, :prompt, :timeout, :vars, :last, :repo
|
|
11
11
|
attr_accessor :running, :user, :email, :msg, :from, :stats, :retry, :err_type, :err_reason
|
|
12
12
|
alias running? running
|
|
13
13
|
|
|
@@ -27,6 +27,7 @@ module Oxidized
|
|
|
27
27
|
@output = resolve_output opt
|
|
28
28
|
@auth = resolve_auth opt
|
|
29
29
|
@prompt = resolve_prompt opt
|
|
30
|
+
@timeout = resolve_timeout opt
|
|
30
31
|
@vars = opt[:vars] || {}
|
|
31
32
|
@stats = Stats.new
|
|
32
33
|
@retry = 0
|
|
@@ -156,6 +157,10 @@ module Oxidized
|
|
|
156
157
|
opt[:prompt] || @model.prompt || Oxidized.config.prompt
|
|
157
158
|
end
|
|
158
159
|
|
|
160
|
+
def resolve_timeout(opt)
|
|
161
|
+
resolve_key :timeout, opt, Oxidized.config.timeout
|
|
162
|
+
end
|
|
163
|
+
|
|
159
164
|
def resolve_auth(opt)
|
|
160
165
|
# Resolve configured username/password
|
|
161
166
|
{
|
data/lib/oxidized/source/http.rb
CHANGED
|
@@ -50,14 +50,22 @@ module Oxidized
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
next_key = @cfg.pagination_key_name
|
|
53
|
+
# Process the initial batch first
|
|
54
|
+
node_data += string_navigate_object(data, @cfg.hosts_location) if @cfg.hosts_location?
|
|
55
|
+
|
|
56
|
+
# Now loop only for subsequent pages
|
|
53
57
|
loop do
|
|
54
|
-
|
|
58
|
+
# Check for the next URL *before* trying to fetch/add
|
|
55
59
|
break if data[next_key].nil?
|
|
56
60
|
|
|
57
|
-
|
|
61
|
+
# Fetch the next page
|
|
62
|
+
new_uri = URI.parse(data[next_key]) # Safe to parse now
|
|
58
63
|
data = JSON.parse(read_http(new_uri, node_want))
|
|
64
|
+
|
|
65
|
+
# Add nodes from the *newly fetched* batch
|
|
59
66
|
node_data += string_navigate_object(data, @cfg.hosts_location) if @cfg.hosts_location?
|
|
60
67
|
end
|
|
68
|
+
|
|
61
69
|
node_data
|
|
62
70
|
end
|
|
63
71
|
|
data/lib/oxidized/version.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Oxidized
|
|
4
|
-
VERSION = '0.
|
|
5
|
-
VERSION_FULL = '0.
|
|
4
|
+
VERSION = '0.35.0'
|
|
5
|
+
VERSION_FULL = '0.35.0'
|
|
6
6
|
def self.version_set
|
|
7
7
|
version_full = %x(git describe --tags).chop rescue ""
|
|
8
8
|
version = %x(git describe --tags --abbrev=0).chop rescue ""
|
data/oxidized.gemspec
CHANGED
|
@@ -46,20 +46,19 @@ Gem::Specification.new do |s|
|
|
|
46
46
|
s.add_dependency 'syslog', '~> 0.3.0'
|
|
47
47
|
s.add_dependency 'syslog_protocol', '~> 0.9.2'
|
|
48
48
|
|
|
49
|
-
s.add_development_dependency 'bundler', '~> 2.2'
|
|
50
49
|
# ruby-git 4.0 requests ruby >= 3.2, we stick to ruby >= 3.1 (Ubuntu Noble/Debian Bookworm)
|
|
51
50
|
s.add_development_dependency 'git', '>= 2.0', '< 3.2.0'
|
|
52
|
-
s.add_development_dependency 'minitest', '~> 5.
|
|
51
|
+
s.add_development_dependency 'minitest', '~> 5.26.0'
|
|
53
52
|
s.add_development_dependency 'mocha', '~> 2.1'
|
|
54
53
|
s.add_development_dependency 'pry', '~> 0.15.0'
|
|
55
54
|
s.add_development_dependency 'rake', '~> 13.0'
|
|
56
|
-
s.add_development_dependency 'rubocop', '~> 1.
|
|
55
|
+
s.add_development_dependency 'rubocop', '~> 1.81.0'
|
|
57
56
|
s.add_development_dependency 'rubocop-minitest', '~> 0.38.0'
|
|
58
57
|
s.add_development_dependency 'rubocop-rake', '~> 0.7.0'
|
|
59
58
|
s.add_development_dependency 'rubocop-sequel', '~> 0.4.0'
|
|
60
59
|
s.add_development_dependency 'simplecov', '~> 0.22.0'
|
|
61
60
|
|
|
62
61
|
# Dependencies on optional libraries, used for unit tests & development
|
|
63
|
-
s.add_development_dependency 'oxidized-web', '
|
|
64
|
-
s.add_development_dependency 'sequel', '>= 5.63.0', '< 5.
|
|
62
|
+
s.add_development_dependency 'oxidized-web', '>= 0.17.1'
|
|
63
|
+
s.add_development_dependency 'sequel', '>= 5.63.0', '< 5.100.0'
|
|
65
64
|
end
|