oxidized 0.35.0 → 0.36.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/.coderabbit.yaml +21 -0
- data/.github/workflows/publishdocker.yml +11 -9
- data/.github/workflows/ruby.yml +1 -3
- data/.rubocop.yml +13 -2
- data/.rubocop_todo.yml +21 -2
- data/CHANGELOG.md +50 -3
- data/README.md +2 -3
- data/docs/Configuration.md +30 -1
- data/docs/Creating-Models.md +128 -13
- data/docs/Docker.md +2 -1
- data/docs/Inputs.md +29 -0
- data/docs/Model-Notes/APC.md +72 -0
- data/docs/Model-Notes/ExaLink.md +43 -0
- data/docs/Model-Notes/Fortinet.md +75 -0
- data/docs/Model-Notes/IvantiConnectSecure.md +59 -0
- data/docs/Model-Notes/TrueNAS.md +19 -0
- data/docs/ModelUnitTests.md +23 -0
- data/docs/Outputs.md +18 -4
- data/docs/Release.md +1 -1
- data/docs/Ruby-API.md +86 -5
- data/docs/Supported-OS-Types.md +20 -9
- data/docs/Troubleshooting.md +1 -1
- data/extra/device2yaml.rb +2 -3
- data/extra/hooks/modelrules.rb +55 -0
- data/extra/hooks/modelrulesadvanced.rb +168 -0
- data/extra/hooks/srcipmap.rb +54 -0
- data/lib/oxidized/hook/githubrepo.rb +2 -1
- data/lib/oxidized/hook.rb +56 -8
- data/lib/oxidized/input/exec.rb +0 -4
- data/lib/oxidized/input/ftp.rb +0 -13
- data/lib/oxidized/input/http.rb +38 -13
- data/lib/oxidized/input/input.rb +33 -13
- data/lib/oxidized/input/scp.rb +10 -64
- data/lib/oxidized/input/ssh.rb +10 -60
- data/lib/oxidized/input/sshbase.rb +107 -0
- data/lib/oxidized/input/telnet.rb +0 -4
- data/lib/oxidized/input/tftp.rb +7 -3
- data/lib/oxidized/model/aoscx.rb +5 -3
- data/lib/oxidized/model/aosw.rb +10 -11
- data/lib/oxidized/model/apc_aos.rb +4 -0
- data/lib/oxidized/model/apcaos.rb +39 -0
- data/lib/oxidized/model/arubainstant.rb +11 -20
- data/lib/oxidized/model/asa.rb +7 -7
- data/lib/oxidized/model/comware.rb +3 -1
- data/lib/oxidized/model/defacto.rb +26 -0
- data/lib/oxidized/model/dslcommands.rb +93 -0
- data/lib/oxidized/model/dslsetup.rb +102 -0
- data/lib/oxidized/model/efos.rb +5 -5
- data/lib/oxidized/model/exalink.rb +36 -0
- data/lib/oxidized/model/fastiron.rb +2 -2
- data/lib/oxidized/model/firelinuxos.rb +1 -3
- data/lib/oxidized/model/fortigate.rb +160 -0
- data/lib/oxidized/model/fortios.rb +28 -69
- data/lib/oxidized/model/fsos.rb +1 -3
- data/lib/oxidized/model/h3c.rb +1 -1
- data/lib/oxidized/model/ios.rb +21 -15
- data/lib/oxidized/model/ironware.rb +5 -3
- data/lib/oxidized/model/ivanti.rb +54 -0
- data/lib/oxidized/model/macros.rb +60 -0
- data/lib/oxidized/model/mlnxos.rb +11 -7
- data/lib/oxidized/model/model.rb +28 -126
- data/lib/oxidized/model/ndms.rb +6 -0
- data/lib/oxidized/model/netgear.rb +5 -3
- data/lib/oxidized/model/nxos.rb +2 -2
- data/lib/oxidized/model/outputs.rb +5 -0
- data/lib/oxidized/model/perle.rb +14 -8
- data/lib/oxidized/model/smartbyte.rb +48 -0
- data/lib/oxidized/model/truenas.rb +10 -1
- data/lib/oxidized/model/voss.rb +3 -0
- data/lib/oxidized/model/vyos.rb +3 -1
- data/lib/oxidized/node.rb +25 -23
- data/lib/oxidized/nodes.rb +2 -0
- data/lib/oxidized/output/file.rb +7 -1
- data/lib/oxidized/output/git.rb +11 -1
- data/lib/oxidized/output/gitcrypt.rb +1 -1
- data/lib/oxidized/output/http.rb +12 -3
- data/lib/oxidized/source/csv.rb +5 -0
- data/lib/oxidized/source/jsonfile.rb +5 -0
- data/lib/oxidized/source/sql.rb +5 -0
- data/lib/oxidized/version.rb +2 -2
- data/lib/oxidized/worker.rb +36 -15
- data/lib/refinements.rb +18 -0
- data/oxidized.gemspec +28 -24
- metadata +98 -55
- data/docs/Model-Notes/APC_AOS.md +0 -65
- data/docs/Model-Notes/FortiOS.md +0 -44
data/lib/oxidized/model/model.rb
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
require 'strscan'
|
|
2
2
|
require_relative 'outputs'
|
|
3
|
+
require_relative 'dslsetup'
|
|
4
|
+
require_relative 'dslcommands'
|
|
5
|
+
require_relative 'macros'
|
|
3
6
|
|
|
4
7
|
module Oxidized
|
|
5
8
|
class Model
|
|
@@ -7,6 +10,11 @@ module Oxidized
|
|
|
7
10
|
|
|
8
11
|
using Refinements
|
|
9
12
|
|
|
13
|
+
# Domain Specific Language for models
|
|
14
|
+
extend Oxidized::Model::DSLSetup
|
|
15
|
+
extend Oxidized::Model::DSLCommands
|
|
16
|
+
extend Oxidized::Model::Macros
|
|
17
|
+
|
|
10
18
|
include Oxidized::Config::Vars
|
|
11
19
|
|
|
12
20
|
# rubocop:disable Style/FormatStringToken
|
|
@@ -25,6 +33,8 @@ module Oxidized
|
|
|
25
33
|
klass.instance_variable_set '@comment', nil
|
|
26
34
|
klass.instance_variable_set '@prompt', nil
|
|
27
35
|
klass.instance_variable_set '@metadata', {}
|
|
36
|
+
klass.instance_variable_set '@inputs', nil
|
|
37
|
+
|
|
28
38
|
else # we're subclassing some existing model, take its variables
|
|
29
39
|
instance_variables.each do |var|
|
|
30
40
|
iv = instance_variable_get(var)
|
|
@@ -33,136 +43,20 @@ module Oxidized
|
|
|
33
43
|
end
|
|
34
44
|
end
|
|
35
45
|
end
|
|
36
|
-
|
|
37
|
-
def comment(str = "# ")
|
|
38
|
-
@comment = if block_given?
|
|
39
|
-
yield
|
|
40
|
-
elsif not @comment
|
|
41
|
-
str
|
|
42
|
-
else
|
|
43
|
-
@comment
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def prompt(regex = nil)
|
|
48
|
-
@prompt = regex || @prompt
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def cfg(*methods, **args, &block)
|
|
52
|
-
[methods].flatten.each do |method|
|
|
53
|
-
process_args_block(@cfg[method.to_s], args, block)
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def cfgs
|
|
58
|
-
@cfg
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def cmd(cmd_arg = nil, **args, &block)
|
|
62
|
-
if cmd_arg.instance_of?(Symbol)
|
|
63
|
-
process_args_block(@cmd[cmd_arg], args, block)
|
|
64
|
-
else
|
|
65
|
-
# Normal command
|
|
66
|
-
process_args_block(@cmd[:cmd], args,
|
|
67
|
-
{ cmd: cmd_arg, args: args, block: block })
|
|
68
|
-
end
|
|
69
|
-
logger.debug "Added #{cmd_arg} to the commands list"
|
|
70
|
-
end
|
|
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
|
-
|
|
82
|
-
def cmds
|
|
83
|
-
@cmd
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def expect(regex, **args, &block)
|
|
87
|
-
process_args_block(@expect, args, [regex, block])
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def expects
|
|
91
|
-
@expect
|
|
92
|
-
end
|
|
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
|
-
|
|
118
|
-
# calls the block at the end of the model, prepending the output of the
|
|
119
|
-
# block to the output string
|
|
120
|
-
#
|
|
121
|
-
# @yield expects block which should return [String]
|
|
122
|
-
# @return [void]
|
|
123
|
-
def pre(**args, &block)
|
|
124
|
-
process_args_block(@procs[:pre], args, block)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# calls the block at the end of the model, adding the output of the block
|
|
128
|
-
# to the output string
|
|
129
|
-
#
|
|
130
|
-
# @yield expects block which should return [String]
|
|
131
|
-
# @return [void]
|
|
132
|
-
def post(**args, &block)
|
|
133
|
-
process_args_block(@procs[:post], args, block)
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
# @author Saku Ytti <saku@ytti.fi>
|
|
137
|
-
# @since 0.0.39
|
|
138
|
-
# @return [Hash] hash proc procs :pre+:post to be prepended/postfixed to output
|
|
139
|
-
attr_reader :procs
|
|
140
|
-
|
|
141
|
-
private
|
|
142
|
-
|
|
143
|
-
def process_args_block(target, args, block)
|
|
144
|
-
if args[:clear]
|
|
145
|
-
if block.instance_of?(Array)
|
|
146
|
-
target.reject! { |k, _| k == block[0] }
|
|
147
|
-
target.push(block)
|
|
148
|
-
elsif block.instance_of?(Hash)
|
|
149
|
-
target.reject! { |item| item[:cmd] == block[:cmd] }
|
|
150
|
-
target.push(block)
|
|
151
|
-
else
|
|
152
|
-
target.replace([block])
|
|
153
|
-
end
|
|
154
|
-
else
|
|
155
|
-
method = args[:prepend] ? :unshift : :push
|
|
156
|
-
target.send(method, block)
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
46
|
end
|
|
160
47
|
|
|
161
48
|
attr_accessor :input, :node
|
|
162
49
|
|
|
163
|
-
|
|
50
|
+
# input specifies to run this command only with this input type
|
|
51
|
+
# if input is not specified, always run the command
|
|
52
|
+
def cmd(string, input: nil, &block)
|
|
164
53
|
logger.debug "Executing #{string}"
|
|
165
|
-
out = @input.
|
|
54
|
+
out = if input.nil? || input.include?(@input.to_sym)
|
|
55
|
+
out = @input.cmd(string)
|
|
56
|
+
else
|
|
57
|
+
# Do not run this command
|
|
58
|
+
return ''
|
|
59
|
+
end
|
|
166
60
|
return false unless out
|
|
167
61
|
|
|
168
62
|
out = out.b unless Oxidized.config.input.utf8_encoded?
|
|
@@ -245,6 +139,7 @@ module Oxidized
|
|
|
245
139
|
data
|
|
246
140
|
end
|
|
247
141
|
|
|
142
|
+
# Get the commands from the model
|
|
248
143
|
def get
|
|
249
144
|
logger.debug 'Collecting commands\' outputs'
|
|
250
145
|
outputs = Outputs.new
|
|
@@ -255,7 +150,7 @@ module Oxidized
|
|
|
255
150
|
|
|
256
151
|
next if args.include?(:if) && !instance_exec(&args[:if])
|
|
257
152
|
|
|
258
|
-
out = cmd command, &block
|
|
153
|
+
out = cmd command, input: args[:input], &block
|
|
259
154
|
return false unless out
|
|
260
155
|
|
|
261
156
|
outputs << out
|
|
@@ -306,6 +201,13 @@ module Oxidized
|
|
|
306
201
|
@input.class.to_s.match(/Telnet/) || vars(:ssh_no_exec)
|
|
307
202
|
end
|
|
308
203
|
|
|
204
|
+
def significant_changes(config)
|
|
205
|
+
self.class.cmds[:significant_changes].each do |block|
|
|
206
|
+
config = instance_exec config, &block
|
|
207
|
+
end
|
|
208
|
+
config
|
|
209
|
+
end
|
|
210
|
+
|
|
309
211
|
private
|
|
310
212
|
|
|
311
213
|
def process_cmd_output(output, name)
|
data/lib/oxidized/model/ndms.rb
CHANGED
|
@@ -6,7 +6,7 @@ class Netgear < Oxidized::Model
|
|
|
6
6
|
clean :escape_codes
|
|
7
7
|
|
|
8
8
|
# Handle pager for "show version" on old Netgear models: #2394
|
|
9
|
-
expect /^--More-- or \(q\)uit
|
|
9
|
+
expect /^--More--(?: or \(q\)uit)?$/ do |data, re|
|
|
10
10
|
send ' '
|
|
11
11
|
data.sub re, ''
|
|
12
12
|
end
|
|
@@ -20,7 +20,7 @@ class Netgear < Oxidized::Model
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
cfg :telnet do
|
|
23
|
-
username /^(User:|Applying Interface configuration, please wait ...)/
|
|
23
|
+
username /^(Username:|User:|Applying Interface configuration, please wait ...)/
|
|
24
24
|
password /^Password:/i
|
|
25
25
|
end
|
|
26
26
|
|
|
@@ -58,9 +58,11 @@ class Netgear < Oxidized::Model
|
|
|
58
58
|
comment cfg
|
|
59
59
|
end
|
|
60
60
|
cmd 'show running-config' do |cfg|
|
|
61
|
-
cfg.gsub! /(System Up Time
|
|
61
|
+
cfg.gsub! /(System Up Time:?\s+).*/, '\\1 <removed>'
|
|
62
62
|
cfg.gsub! /(Current SNTP Synchronized Time:).*/, '\\1 <removed>'
|
|
63
63
|
cfg.gsub! /(Current System Time:).*/, '\\1 <removed>'
|
|
64
|
+
# Remove standalone backspace lines
|
|
65
|
+
cfg.gsub!(/(?:\r?\n)?\x08(?:\r?\n)?/, "\n")
|
|
64
66
|
cfg
|
|
65
67
|
end
|
|
66
68
|
end
|
data/lib/oxidized/model/nxos.rb
CHANGED
|
@@ -25,8 +25,8 @@ class NXOS < Oxidized::Model
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
cmd 'show inventory all' do |cfg|
|
|
28
|
-
if cfg.
|
|
29
|
-
# 'show inventory all' isn't supported on older versions (See
|
|
28
|
+
if cfg.match? /^% Invalid .* at '\^' marker\./
|
|
29
|
+
# 'show inventory all' isn't supported on older versions (See Issues #3657, #3779)
|
|
30
30
|
cfg = cmd 'show inventory'
|
|
31
31
|
end
|
|
32
32
|
comment cfg
|
data/lib/oxidized/model/perle.rb
CHANGED
|
@@ -5,7 +5,8 @@ class Perle < Oxidized::Model
|
|
|
5
5
|
comment '! '
|
|
6
6
|
|
|
7
7
|
cmd :all do |cfg|
|
|
8
|
-
cfg.cut_both
|
|
8
|
+
cfg = cfg.cut_both
|
|
9
|
+
cfg.delete "\r"
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
cmd 'show version verbose' do |cfg|
|
|
@@ -17,17 +18,22 @@ class Perle < Oxidized::Model
|
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
cmd 'show interfaces transceiver' do |cfg|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
comment out.join + "\n"
|
|
21
|
+
cfg = cfg.keep_lines [
|
|
22
|
+
'SFP Information',
|
|
23
|
+
'Vendor Name',
|
|
24
|
+
'Vendor Serial Number'
|
|
25
|
+
]
|
|
26
|
+
comment cfg + "\n"
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
cmd 'show running-config'
|
|
30
30
|
|
|
31
|
+
cmd :significant_changes do |cfg|
|
|
32
|
+
cfg.reject_lines [
|
|
33
|
+
/^tacacs-server key 7 \$0\$\S+==$/
|
|
34
|
+
]
|
|
35
|
+
end
|
|
36
|
+
|
|
31
37
|
cfg :ssh do
|
|
32
38
|
post_login 'terminal length 0'
|
|
33
39
|
pre_logout 'exit'
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
class SmartByte < Oxidized::Model
|
|
2
|
+
using Refinements
|
|
3
|
+
|
|
4
|
+
comment '! '
|
|
5
|
+
|
|
6
|
+
cmd :secret do |cfg|
|
|
7
|
+
cfg.gsub!(/group (\S+) v2c/, 'group <hidden> v2c')
|
|
8
|
+
cfg.gsub!(/community (\S+)/, 'community <hidden>')
|
|
9
|
+
cfg
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
cmd :all do |cfg|
|
|
13
|
+
cfg = cfg.delete("\r")
|
|
14
|
+
cfg.cut_tail
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
cmd 'show running-config'
|
|
18
|
+
|
|
19
|
+
cmd 'show version' do |cfg|
|
|
20
|
+
comment cfg
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
cmd 'show interface optical-transceiver info' do |cfg|
|
|
24
|
+
cfg.gsub! /^\|Transceiver current alarm information: \|\s+\+-------------------------------------------------\+.*?\s+\+-------------------------------------------------\+\s+/m, ''
|
|
25
|
+
comment cfg
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
cmd 'show power' do |cfg|
|
|
29
|
+
comment cfg
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
cfg :telnet do
|
|
33
|
+
username /^.*? login:/
|
|
34
|
+
password /^Password:/
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
cfg :telnet, :ssh do
|
|
38
|
+
post_login do
|
|
39
|
+
if vars(:enable)
|
|
40
|
+
cmd "enable", /^[pP]assword:/
|
|
41
|
+
cmd vars(:enable)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
post_login 'terminal length 0'
|
|
46
|
+
pre_logout 'exit'
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -5,7 +5,16 @@ class TrueNAS < Oxidized::Model
|
|
|
5
5
|
|
|
6
6
|
cmd('uname -a') { |cfg| comment cfg }
|
|
7
7
|
cmd('cat /etc/version') { |cfg| comment cfg }
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
# for TrueNAS SCALE machines, make sure the user you use to connect can run
|
|
10
|
+
# this command, or if needed, with passwordless sudo. Try putting this in
|
|
11
|
+
# /etc/sudoers
|
|
12
|
+
# oxidized ALL=(ALL) NOPASSWD: /usr/bin/sqlite3 file\:///data/freenas-v1.db?mode\=ro&immutable\=1 .dump
|
|
13
|
+
|
|
14
|
+
cmd("sqlite3 'file:///data/freenas-v1.db?mode=ro&immutable=1' .dump") do |cfg|
|
|
15
|
+
if cfg.include? "Error: unable to open database"
|
|
16
|
+
cfg = cmd("sudo sqlite3 'file:///data/freenas-v1.db?mode=ro&immutable=1' .dump")
|
|
17
|
+
end
|
|
9
18
|
cfg.lines.reject do |line|
|
|
10
19
|
line.match(/^INSERT INTO storage_replication /) ||
|
|
11
20
|
line.match(/^INSERT INTO system_alert /) || # ignore system alerts in db
|
data/lib/oxidized/model/voss.rb
CHANGED
|
@@ -23,6 +23,9 @@ class Voss < Oxidized::Model
|
|
|
23
23
|
cfg.gsub! /(^((.*)Last Vlan Change(.*):(.*))$)/, 'removed Last Vlan Change'
|
|
24
24
|
cfg.gsub! /(^((.*)Temperature(.*):(.*))$)/, 'removed Temperature'
|
|
25
25
|
cfg.gsub! /(^((.*)Total Power Usage(.*):(.*))$)/, 'removed Total Power Usage'
|
|
26
|
+
cfg.gsub! /(^((.*)(Tray \d+ Fan \d+)\s+(\w+)\s+(\w+)\s+(.*))$)/, '\3\4 \5 [removed RPM values]'
|
|
27
|
+
cfg.gsub! /(^((.*)Command Execution Time: (.*))$)/, 'Command Execution Time [removed]'
|
|
28
|
+
cfg.gsub! /(^((.*)(Ambient\s+\d+|CPU|INTERNAL\s+MAC|SODIMM)\s+\d+\s+\d+(.*))$)/, '\3\4 [removed temperature readings]'
|
|
26
29
|
comment "#{cfg}\n"
|
|
27
30
|
end
|
|
28
31
|
|
data/lib/oxidized/model/vyos.rb
CHANGED
|
@@ -15,8 +15,10 @@ class Vyos < Oxidized::Model
|
|
|
15
15
|
cmd :secret do |cfg|
|
|
16
16
|
cfg.gsub! /secret (\S+).*/, 'secret <secret removed>'
|
|
17
17
|
cfg.gsub! /password (\S+).*/, 'password <secret removed>'
|
|
18
|
-
cfg.gsub! /community (\S+)/, 'community <secret removed>'
|
|
18
|
+
cfg.gsub! /snmp community (\S+)/, 'snmp community <secret removed>'
|
|
19
|
+
cfg.gsub! /preshared-key (\S+).*/, 'preshared-key <secret removed>'
|
|
19
20
|
cfg.gsub! /private key (\S+).*/, 'private key <secret removed>'
|
|
21
|
+
cfg.gsub! /private-key (\S+).*/, 'private-key <secret removed>'
|
|
20
22
|
# password in URLs like protocol://user:password@domain.tld/
|
|
21
23
|
cfg.gsub! /([a-z]+:\/\/[^:\s]+:)\S+@/, '\1<secret removed>@'
|
|
22
24
|
cfg
|
data/lib/oxidized/node.rb
CHANGED
|
@@ -8,8 +8,9 @@ module Oxidized
|
|
|
8
8
|
include SemanticLogger::Loggable
|
|
9
9
|
|
|
10
10
|
attr_reader :name, :ip, :model, :input, :output, :group, :auth, :prompt, :timeout, :vars, :last, :repo
|
|
11
|
-
attr_accessor :running, :user, :email, :msg, :from, :stats, :retry, :err_type, :err_reason
|
|
11
|
+
attr_accessor :running, :user, :email, :msg, :from, :stats, :retry, :err_type, :err_reason, :nexted
|
|
12
12
|
alias running? running
|
|
13
|
+
alias nexted? nexted
|
|
13
14
|
|
|
14
15
|
# opt is a hash with the node parameters given in the source (:name, :group, :ip...)
|
|
15
16
|
def initialize(opt)
|
|
@@ -34,6 +35,7 @@ module Oxidized
|
|
|
34
35
|
@repo = resolve_repo opt
|
|
35
36
|
@err_type = nil
|
|
36
37
|
@err_reason = nil
|
|
38
|
+
@nexted = false
|
|
37
39
|
|
|
38
40
|
# model instance needs to access node instance
|
|
39
41
|
@model.node = self
|
|
@@ -41,37 +43,37 @@ module Oxidized
|
|
|
41
43
|
|
|
42
44
|
def run
|
|
43
45
|
status = :fail
|
|
44
|
-
config =
|
|
45
|
-
@
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
46
|
+
config = Oxidized::Model::Outputs.new
|
|
47
|
+
input_sequence = @model.class.input_sequence(@input)
|
|
48
|
+
|
|
49
|
+
input_sequence.each do |sequence|
|
|
50
|
+
status = :fail
|
|
51
|
+
sequence_config = nil
|
|
52
|
+
sequence.each do |input|
|
|
53
|
+
@model.input = input = input.new
|
|
54
|
+
if (sequence_config = run_input(input))
|
|
55
|
+
logger.debug "#{input.class.name} ran for #{name} successfully"
|
|
56
|
+
status = :success
|
|
57
|
+
break
|
|
58
|
+
else
|
|
59
|
+
logger.debug "#{input.class.name} failed for #{name}"
|
|
60
|
+
status = :no_connection
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
if status == :success
|
|
64
|
+
config.merge! sequence_config
|
|
55
65
|
else
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
config = nil
|
|
67
|
+
break
|
|
58
68
|
end
|
|
59
69
|
end
|
|
60
|
-
logger.error "No suitable input found for #{name}" unless @model.input
|
|
61
70
|
|
|
62
71
|
@model.input = nil
|
|
63
72
|
[status, config]
|
|
64
73
|
end
|
|
65
74
|
|
|
66
75
|
def run_input(input)
|
|
67
|
-
rescue_fail =
|
|
68
|
-
[input.class::RESCUE_FAIL, input.class.superclass::RESCUE_FAIL].each do |hash|
|
|
69
|
-
hash.each do |level, errors|
|
|
70
|
-
errors.each do |err|
|
|
71
|
-
rescue_fail[err] = level
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|
|
76
|
+
rescue_fail = input.class.rescue_fail
|
|
75
77
|
begin
|
|
76
78
|
input.connect(self) && input.get
|
|
77
79
|
rescue *rescue_fail.keys => err
|
data/lib/oxidized/nodes.rb
CHANGED
|
@@ -88,6 +88,8 @@ module Oxidized
|
|
|
88
88
|
n.from = opt['from']
|
|
89
89
|
# set last job to nil so that the node is picked for immediate update
|
|
90
90
|
n.last = nil
|
|
91
|
+
# set nexted to true so that the node will not be skipped with interval 0
|
|
92
|
+
n.nexted = true
|
|
91
93
|
put n
|
|
92
94
|
jobs.increment if Oxidized.config.next_adds_job?
|
|
93
95
|
end
|
data/lib/oxidized/output/file.rb
CHANGED
|
@@ -21,8 +21,14 @@ module Oxidized
|
|
|
21
21
|
|
|
22
22
|
# node: node name (String)
|
|
23
23
|
# outputs: Oxidized::Models::Outputs
|
|
24
|
-
# opts:
|
|
24
|
+
# opts: dict of optional parameters:
|
|
25
|
+
# - group: node group
|
|
26
|
+
# - significant_changes:
|
|
27
|
+
# nil / not set / true -> store as usual
|
|
28
|
+
# false -> do not store
|
|
25
29
|
def store(node, outputs, opt = {})
|
|
30
|
+
return false if opt[:significant_changes] == false
|
|
31
|
+
|
|
26
32
|
file = ::File.expand_path @cfg.directory
|
|
27
33
|
file = ::File.join ::File.dirname(file), opt[:group] if opt[:group]
|
|
28
34
|
FileUtils.mkdir_p file
|
data/lib/oxidized/output/git.rb
CHANGED
|
@@ -35,6 +35,16 @@ module Oxidized
|
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
# file: node name (String)
|
|
39
|
+
# outputs: Oxidized::Models::Outputs
|
|
40
|
+
# opts: dict of optional parameters:
|
|
41
|
+
# - msg: commit message
|
|
42
|
+
# - email: committer email
|
|
43
|
+
# - user: committer name
|
|
44
|
+
# - group: node group
|
|
45
|
+
# - significant_changes:
|
|
46
|
+
# nil / not set / true: store as usual
|
|
47
|
+
# false: skip general config, only store configs where type != nil
|
|
38
48
|
def store(file, outputs, opt = {})
|
|
39
49
|
@msg = opt[:msg]
|
|
40
50
|
@user = opt[:user] || @cfg.user
|
|
@@ -58,7 +68,7 @@ module Oxidized
|
|
|
58
68
|
update type_repo, file, type_cfg
|
|
59
69
|
end
|
|
60
70
|
|
|
61
|
-
update repo, file, outputs.to_cfg
|
|
71
|
+
update repo, file, outputs.to_cfg unless opt[:significant_changes] == false
|
|
62
72
|
end
|
|
63
73
|
|
|
64
74
|
# Returns the configuration of group/node_name
|
data/lib/oxidized/output/http.rb
CHANGED
|
@@ -26,9 +26,18 @@ module Oxidized
|
|
|
26
26
|
@commitref = nil
|
|
27
27
|
uri = URI.parse @cfg.url
|
|
28
28
|
http = Net::HTTP.new uri.host, uri.port
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
|
|
30
|
+
# if uri scheme is https, enable ssl and set verify mode
|
|
31
|
+
if uri.scheme == "https"
|
|
32
|
+
http.use_ssl = true
|
|
33
|
+
http.verify_mode = @cfg.ssl_verify? ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
headers = @cfg.headers? ? @cfg.headers : {}
|
|
37
|
+
|
|
38
|
+
req = Net::HTTP::Post.new(uri.request_uri, headers.merge('Content-Type' => 'application/json'))
|
|
39
|
+
req.basic_auth(@cfg.user, @cfg.password) if @cfg.user? && @cfg.password?
|
|
40
|
+
|
|
32
41
|
req.body = generate_json(node, outputs, opt)
|
|
33
42
|
response = http.request req
|
|
34
43
|
|
data/lib/oxidized/source/csv.rb
CHANGED
data/lib/oxidized/source/sql.rb
CHANGED
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.36.0'
|
|
5
|
+
VERSION_FULL = '0.36.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 ""
|