oxidized 0.30.1 → 0.32.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +3 -4
- data/.github/workflows/stale.yml +4 -2
- data/.rubocop.yml +18 -3
- data/.rubocop_todo.yml +4 -11
- data/CHANGELOG.md +93 -1
- data/CONTRIBUTING.md +5 -0
- data/Dockerfile +84 -20
- data/README.md +5 -21
- data/Rakefile +31 -2
- data/docs/Configuration.md +50 -14
- data/docs/Creating-Models.md +75 -4
- data/docs/DeviceSimulation.md +184 -0
- data/docs/Hooks.md +39 -5
- data/docs/Issues.md +97 -0
- data/docs/Model-Notes/APC_AOS.md +29 -16
- data/docs/Model-Notes/Cumulus.md +5 -0
- data/docs/Model-Notes/FSOS.md +6 -0
- data/docs/Model-Notes/FortiOS.md +21 -5
- data/docs/Model-Notes/HPEAruba.md +31 -0
- data/docs/Model-Notes/OS6.md +10 -0
- data/docs/Model-Notes/RouterOS.md +15 -0
- data/docs/Model-Notes/SikluMHTG.md +7 -0
- data/docs/ModelUnitTests.md +186 -0
- data/docs/Outputs.md +2 -0
- data/docs/Release.md +18 -15
- data/docs/Sources.md +21 -0
- data/docs/Supported-OS-Types.md +14 -7
- data/docs/Troubleshooting.md +35 -0
- data/examples/podman-compose/Makefile +59 -17
- data/examples/podman-compose/README.md +63 -27
- data/examples/podman-compose/docker-compose.yml +11 -2
- data/examples/podman-compose/gitserver/.gitignore +1 -0
- data/examples/podman-compose/gitserver/Dockerfile +14 -0
- data/examples/podman-compose/model-simulation/Dockerfile-model +1 -1
- data/examples/podman-compose/model-simulation/asternos.sh +2 -0
- data/examples/podman-compose/oxidized-config/.gitignore +2 -0
- data/examples/podman-compose/oxidized-config/config +1 -1
- data/examples/podman-compose/oxidized-config/config_csv-file +46 -0
- data/examples/podman-compose/oxidized-config/config_csv-gitserver +56 -0
- data/examples/podman-compose/oxidized-ssh/.gitignore +1 -0
- data/extra/device2yaml.rb +245 -0
- data/extra/gitdiff-msteams.sh +32 -5
- data/extra/nagios_check_failing_nodes.rb +1 -1
- data/extra/rest_client.rb +1 -1
- data/lib/oxidized/config.rb +8 -2
- data/lib/oxidized/hook/githubrepo.rb +37 -7
- data/lib/oxidized/hook/slackdiff.rb +29 -7
- data/lib/oxidized/input/http.rb +1 -0
- data/lib/oxidized/input/ssh.rb +13 -5
- data/lib/oxidized/input/telnet.rb +1 -1
- data/lib/oxidized/manager.rb +17 -16
- data/lib/oxidized/model/aos7.rb +2 -0
- data/lib/oxidized/model/aoscx.rb +16 -2
- data/lib/oxidized/model/aosw.rb +8 -2
- data/lib/oxidized/model/apc_aos.rb +1 -1
- data/lib/oxidized/model/arubainstant.rb +90 -0
- data/lib/oxidized/model/asa.rb +2 -1
- data/lib/oxidized/model/asyncos.rb +1 -1
- data/lib/oxidized/model/audiocodes.rb +2 -2
- data/lib/oxidized/model/cnos.rb +13 -10
- data/lib/oxidized/model/cumulus.rb +19 -2
- data/lib/oxidized/model/dlink.rb +1 -0
- data/lib/oxidized/model/dlinknextgen.rb +3 -0
- data/lib/oxidized/model/edgecos.rb +2 -1
- data/lib/oxidized/model/enterprise_sonic.rb +46 -0
- data/lib/oxidized/model/eos.rb +2 -0
- data/lib/oxidized/model/f5os.rb +17 -0
- data/lib/oxidized/model/firewareos.rb +10 -1
- data/lib/oxidized/model/fortios.rb +24 -1
- data/lib/oxidized/model/fsos.rb +5 -1
- data/lib/oxidized/model/garderos.rb +43 -0
- data/lib/oxidized/model/h3c.rb +1 -1
- data/lib/oxidized/model/ibos.rb +1 -0
- data/lib/oxidized/model/ios.rb +20 -12
- data/lib/oxidized/model/iosxr.rb +1 -1
- data/lib/oxidized/model/junos.rb +1 -1
- data/lib/oxidized/model/kornfeldos.rb +33 -0
- data/lib/oxidized/model/lenovonos.rb +2 -0
- data/lib/oxidized/model/linuxgeneric.rb +1 -1
- data/lib/oxidized/model/model.rb +2 -2
- data/lib/oxidized/model/netgear.rb +1 -1
- data/lib/oxidized/model/nodegrid.rb +1 -1
- data/lib/oxidized/model/nsxdfw.rb +30 -0
- data/lib/oxidized/model/nxos.rb +2 -1
- data/lib/oxidized/model/os6.rb +48 -0
- data/lib/oxidized/model/rgos.rb +1 -1
- data/lib/oxidized/model/riverbed.rb +104 -0
- data/lib/oxidized/model/routeros.rb +2 -2
- data/lib/oxidized/model/saos.rb +18 -1
- data/lib/oxidized/model/siklumhtg.rb +22 -0
- data/lib/oxidized/model/sonicos.rb +8 -2
- data/lib/oxidized/model/tplink.rb +1 -0
- data/lib/oxidized/model/uplinkolt.rb +46 -0
- data/lib/oxidized/model/vyatta.rb +2 -2
- data/lib/oxidized/model/xos.rb +7 -0
- data/lib/oxidized/node.rb +30 -18
- data/lib/oxidized/nodes.rb +13 -5
- data/lib/oxidized/output/file.rb +45 -42
- data/lib/oxidized/output/git.rb +185 -160
- data/lib/oxidized/output/gitcrypt.rb +188 -186
- data/lib/oxidized/output/http.rb +53 -51
- data/lib/oxidized/output/output.rb +6 -4
- data/lib/oxidized/source/csv.rb +44 -49
- data/lib/oxidized/source/http.rb +63 -81
- data/lib/oxidized/source/jsonfile.rb +63 -0
- data/lib/oxidized/source/source.rb +73 -18
- data/lib/oxidized/source/sql.rb +66 -59
- data/lib/oxidized/version.rb +2 -2
- data/oxidized.gemspec +25 -18
- metadata +115 -21
@@ -0,0 +1,104 @@
|
|
1
|
+
class Riverbed < Oxidized::Model
|
2
|
+
using Refinements
|
3
|
+
|
4
|
+
# Define the prompt
|
5
|
+
prompt /^.* *[\w-]+ *[#>] *$/
|
6
|
+
|
7
|
+
# Define comment character
|
8
|
+
comment '! '
|
9
|
+
|
10
|
+
# Remove sensitive information
|
11
|
+
cmd :secret do |cfg|
|
12
|
+
cfg.gsub! /^( *tacacs-server (.+ )?key) .+/, '\\1 <secret hidden>'
|
13
|
+
cfg.gsub! /^( *username .+ (password|secret) \d) .+/, '\\1 <secret hidden>'
|
14
|
+
cfg.gsub! /^( *ntp server .+ key) .+/, '\\1 <secret hidden>'
|
15
|
+
cfg.gsub! /^( *ntp peer .+ key) .+/, '\\1 <secret hidden>'
|
16
|
+
cfg.gsub! /^( *snmp-server community).*/, '\\1 <configuration removed>'
|
17
|
+
cfg.gsub! /^( *ip security shared secret).*/, '\\1 <secret hidden>'
|
18
|
+
cfg.gsub! /^( *service shared-secret secret client).*/, '\\1 <secret hidden>'
|
19
|
+
cfg.gsub! /^( *service shared-secret secret server).*/, '\\1 <secret hidden>'
|
20
|
+
cfg
|
21
|
+
end
|
22
|
+
|
23
|
+
# Get version information and output it as comments
|
24
|
+
cmd 'show version' do |cfg|
|
25
|
+
cfg = cfg.cut_both
|
26
|
+
|
27
|
+
output = ''
|
28
|
+
cfg.each_line do |line|
|
29
|
+
line.strip!
|
30
|
+
output << comment("Product name: #{Regexp.last_match(1)}\n") if line =~ /^Product name:\s+(.*)$/
|
31
|
+
output << comment("Product release: #{Regexp.last_match(1)}\n") if line =~ /^Product release:\s+(.*)$/
|
32
|
+
output << comment("Build ID: #{Regexp.last_match(1)}\n") if line =~ /^Build ID:\s+(.*)$/
|
33
|
+
output << comment("Build date: #{Regexp.last_match(1)}\n") if line =~ /^Build date:\s+(.*)$/
|
34
|
+
output << comment("Build arch: #{Regexp.last_match(1)}\n") if line =~ /^Build arch:\s+(.*)$/
|
35
|
+
output << comment("Built by: #{Regexp.last_match(1)}\n") if line =~ /^Built by:\s+(.*)$/
|
36
|
+
output << comment("Product model: #{Regexp.last_match(1)}\n") if line =~ /^Product model:\s+(.*)$/
|
37
|
+
output << comment("Number of CPUs: #{Regexp.last_match(1)}\n") if line =~ /^Number of CPUs:\s+(.*)$/
|
38
|
+
end
|
39
|
+
output + "\n"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get hardware information and output it as comments
|
43
|
+
cmd 'show hardware all' do |cfg|
|
44
|
+
cfg = cfg.cut_both
|
45
|
+
|
46
|
+
output = ''
|
47
|
+
cfg.each_line do |line|
|
48
|
+
line.strip!
|
49
|
+
output << comment("Hardware revision: #{Regexp.last_match(1)}\n") if line =~ /^Hardware revision:\s+(.*)$/
|
50
|
+
output << comment("Mainboard: #{Regexp.last_match(1)}\n") if line =~ /^Mainboard:\s+(.*)$/
|
51
|
+
if line =~ /^Slot (\d+):\s+\.*\s+(.*)$/
|
52
|
+
slot_number = Regexp.last_match(1)
|
53
|
+
slot_info = Regexp.last_match(2)
|
54
|
+
output << comment("Slot #{slot_number}: #{slot_info}\n")
|
55
|
+
end
|
56
|
+
output << comment("System led: #{Regexp.last_match(1)}\n") if line =~ /^System led:\s+(.*)$/
|
57
|
+
end
|
58
|
+
output + "\n"
|
59
|
+
end
|
60
|
+
|
61
|
+
# Get serial information and output it as comment
|
62
|
+
cmd 'show info' do |cfg|
|
63
|
+
cfg = cfg.cut_both
|
64
|
+
|
65
|
+
output = ''
|
66
|
+
cfg.each_line do |line|
|
67
|
+
line.strip!
|
68
|
+
output << comment("Serial: #{Regexp.last_match(1)}\n") if line =~ /^Serial:\s+(.*)$/
|
69
|
+
end
|
70
|
+
output + "\n"
|
71
|
+
end
|
72
|
+
|
73
|
+
# Get the running configuration
|
74
|
+
cmd 'show running-config' do |cfg|
|
75
|
+
cfg = cfg.cut_both
|
76
|
+
|
77
|
+
cfg = cfg.each_line.map do |line|
|
78
|
+
if line =~ /^(.*##.*?##)(.*)$/
|
79
|
+
comment_part = Regexp.last_match(1).strip
|
80
|
+
command_part = Regexp.last_match(2).strip
|
81
|
+
comment_line = comment(comment_part)
|
82
|
+
if command_part.empty?
|
83
|
+
comment_line + "\n"
|
84
|
+
else
|
85
|
+
comment_line + "\n" + command_part + "\n"
|
86
|
+
end
|
87
|
+
else
|
88
|
+
line
|
89
|
+
end
|
90
|
+
end.join
|
91
|
+
|
92
|
+
cfg
|
93
|
+
end
|
94
|
+
|
95
|
+
# SSH configuration
|
96
|
+
cfg :ssh do
|
97
|
+
post_login do
|
98
|
+
cmd 'enable'
|
99
|
+
cmd 'terminal length 0'
|
100
|
+
cmd 'terminal width 1024'
|
101
|
+
end
|
102
|
+
pre_logout 'exit'
|
103
|
+
end
|
104
|
+
end
|
@@ -14,8 +14,8 @@ class RouterOS < Oxidized::Model
|
|
14
14
|
cfg
|
15
15
|
end
|
16
16
|
|
17
|
-
cmd '/system
|
18
|
-
cfg = cfg.each_line.grep(/(
|
17
|
+
cmd '/system resource print' do |cfg|
|
18
|
+
cfg = cfg.each_line.grep(/(version|factory-software|total-memory|cpu|cpu-count|total-hdd-space|architecture-name|board-name|platform):/).join
|
19
19
|
comment cfg
|
20
20
|
end
|
21
21
|
|
data/lib/oxidized/model/saos.rb
CHANGED
@@ -4,12 +4,29 @@ class SAOS < Oxidized::Model
|
|
4
4
|
# Ciena SAOS switch
|
5
5
|
# used for 6.x devices
|
6
6
|
|
7
|
-
comment
|
7
|
+
comment '! '
|
8
|
+
prompt /^[\w-]+\*?>\s?/
|
8
9
|
|
9
10
|
cmd :all do |cfg|
|
11
|
+
cfg.gsub! /(Waiting for )(accounting|authorization).*\n/, '' # Remove TACACS errors
|
10
12
|
cfg.cut_both
|
11
13
|
end
|
12
14
|
|
15
|
+
cmd 'chassis show device-id power' do |cfg|
|
16
|
+
comment cfg
|
17
|
+
end
|
18
|
+
|
19
|
+
cmd 'software show' do |cfg|
|
20
|
+
cfg.gsub! /^\| Bank status.*/, '| Bank status : <removed> |'
|
21
|
+
comment cfg
|
22
|
+
end
|
23
|
+
|
24
|
+
cmd 'port xcvr show' do |cfg|
|
25
|
+
cfg.gsub! /^SHELL PARSER FAILURE.*/, '' # Ignore command failure
|
26
|
+
cfg.gsub! /(\s\|.{10}\|)(Ena\s\s|\s\sDis|UCTF\s)(.*)/, '\1 \3' # Remove transient operational state
|
27
|
+
comment cfg
|
28
|
+
end
|
29
|
+
|
13
30
|
cmd 'configuration show' do |cfg|
|
14
31
|
cfg.gsub! /^! Created: [^\n]*\n/, ''
|
15
32
|
cfg.gsub! /^! On terminal: [^\n]*\n/, ''
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class SikluMHTG < Oxidized::Model
|
2
|
+
using Refinements
|
3
|
+
|
4
|
+
# Siklu MultiHaul TG#
|
5
|
+
# Requires source to define the model as SikluMHTG #
|
6
|
+
|
7
|
+
prompt /^\r?MH-[TN]\d{3}[\@][\w]{2,8}>$/
|
8
|
+
|
9
|
+
expect /--More--/ do |data, re|
|
10
|
+
send ' '
|
11
|
+
data.sub re, ''
|
12
|
+
end
|
13
|
+
|
14
|
+
cmd 'show startup' do |cfg|
|
15
|
+
cfg.gsub! /[\b]|\e\[A|\e\[2K/, ''
|
16
|
+
cfg.cut_both
|
17
|
+
end
|
18
|
+
|
19
|
+
cfg :ssh do
|
20
|
+
pre_logout 'quit'
|
21
|
+
end
|
22
|
+
end
|
@@ -3,8 +3,14 @@ class SonicOS < Oxidized::Model
|
|
3
3
|
|
4
4
|
# Applies to Sonicwall NSA series firewalls
|
5
5
|
|
6
|
-
prompt /^\w
|
7
|
-
comment
|
6
|
+
prompt /^\w+@[\w\-]+[>]\(?.+\)?\s?/
|
7
|
+
comment '! '
|
8
|
+
|
9
|
+
# Accept policiy message (see Issue #3339). Tested on 6.5 and 7.1
|
10
|
+
expect /Accept The Policy Banner \(yes\)\?\r\nyes: $/ do |data, re|
|
11
|
+
send "yes\n"
|
12
|
+
data.sub re, ''
|
13
|
+
end
|
8
14
|
|
9
15
|
cmd :all do |cfg|
|
10
16
|
cfg.each_line.to_a[1..-2].join
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class UPLINKOLT < Oxidized::Model
|
2
|
+
prompt /^([\w.@()-]+[#>]\s?)$/
|
3
|
+
comment '! '
|
4
|
+
|
5
|
+
cmd :all do |cfg|
|
6
|
+
cfg.gsub! /^% Invalid input detected at '\^' marker\.$|^\s+\^$/, ''
|
7
|
+
cfg.gsub!(/^show running-config$/, '')
|
8
|
+
cfg.gsub!(/^.*\s*#\s*$/, '')
|
9
|
+
# Remove leading and trailing whitespace
|
10
|
+
cfg.strip!
|
11
|
+
# Remove empty lines
|
12
|
+
cfg.gsub!(/^\s*$/, '')
|
13
|
+
cfg
|
14
|
+
end
|
15
|
+
|
16
|
+
cmd 'configure terminal' do
|
17
|
+
# Enter configure terminal mode
|
18
|
+
cmd 'show version' do |cfg|
|
19
|
+
cfg.gsub! /^show version/, ''
|
20
|
+
comment cfg
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
cmd 'show running-config' do |cfg|
|
25
|
+
cfg.gsub! /^Current configuration:/, ''
|
26
|
+
cfg
|
27
|
+
end
|
28
|
+
|
29
|
+
cfg :telnet, :ssh do
|
30
|
+
username /^Login:/i
|
31
|
+
password /^Password:/i
|
32
|
+
# preferred way to handle additional passwords
|
33
|
+
post_login do
|
34
|
+
if vars(:enable) == true
|
35
|
+
cmd "enable"
|
36
|
+
elsif vars(:enable)
|
37
|
+
cmd "enable", /^[pP]assword:/
|
38
|
+
cmd vars(:enable)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
post_login 'terminal length 0'
|
42
|
+
pre_logout 'exit'
|
43
|
+
pre_logout 'disable'
|
44
|
+
pre_logout 'exit'
|
45
|
+
end
|
46
|
+
end
|
@@ -3,7 +3,7 @@ class Vyatta < Oxidized::Model
|
|
3
3
|
|
4
4
|
# Brocade Vyatta / VyOS model #
|
5
5
|
|
6
|
-
prompt
|
6
|
+
prompt /@.*(:~\$|>)\s/
|
7
7
|
|
8
8
|
cmd :all do |cfg|
|
9
9
|
cfg.lines.to_a[1..-2].join
|
@@ -14,7 +14,7 @@ class Vyatta < Oxidized::Model
|
|
14
14
|
cfg.gsub! /plaintext-password (\S+).*/, 'plaintext-password <secret removed>'
|
15
15
|
cfg.gsub! /password (\S+).*/, 'password <secret removed>'
|
16
16
|
cfg.gsub! /pre-shared-secret (\S+).*/, 'pre-shared-secret <secret removed>'
|
17
|
-
cfg.gsub! /community (\S+)
|
17
|
+
cfg.gsub! /community (\S+)/, 'community <hidden>'
|
18
18
|
cfg.gsub! /private-key (\S+).*/, 'private-key <secret removed>'
|
19
19
|
cfg.gsub! /preshared-key (\S+).*/, 'preshared-key <secret removed>'
|
20
20
|
cfg
|
data/lib/oxidized/model/xos.rb
CHANGED
@@ -12,6 +12,13 @@ class XOS < Oxidized::Model
|
|
12
12
|
cfg.each_line.to_a[1..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
|
13
13
|
end
|
14
14
|
|
15
|
+
cmd :secret do |cfg|
|
16
|
+
cfg.gsub! /^(configure (radius|radius-accounting) (netlogin|mgmt-access) (primary|secondary) shared-secret encrypted).+/, '\\1 <secret hidden>'
|
17
|
+
cfg.gsub! /^(configure account admin encrypted).+/, '\\1 <secret hidden>'
|
18
|
+
cfg.gsub! /^(create account (admin|user) (.+) encrypted).+/, '\\1 <secret hidden>'
|
19
|
+
cfg
|
20
|
+
end
|
21
|
+
|
15
22
|
cmd 'show version' do |cfg|
|
16
23
|
comment cfg
|
17
24
|
end
|
data/lib/oxidized/node.rb
CHANGED
@@ -80,6 +80,8 @@ module Oxidized
|
|
80
80
|
@err_reason = err.message.to_s
|
81
81
|
false
|
82
82
|
rescue StandardError => e
|
83
|
+
# Send a message in debug mode in case we are not able to create a crashfile
|
84
|
+
Oxidized.logger.send(:debug, '%s raised %s with msg "%s", creating crashfile' % [ip, e.class, e.message])
|
83
85
|
crashdir = Oxidized.config.crash.directory
|
84
86
|
crashfile = Oxidized.config.crash.hostnames? ? name : ip.to_s
|
85
87
|
FileUtils.mkdir_p(crashdir) unless File.directory?(crashdir)
|
@@ -198,33 +200,43 @@ module Oxidized
|
|
198
200
|
end
|
199
201
|
|
200
202
|
def resolve_key(key, opt, global = nil)
|
201
|
-
# resolve key
|
203
|
+
# resolve key: the priority is as follows: node -> group specific model -> group -> model -> global passed -> global
|
204
|
+
# where node has the highest priority (= if defined, overwrites other values)
|
202
205
|
key_sym = key.to_sym
|
203
206
|
key_str = key.to_s
|
204
|
-
|
205
|
-
Oxidized.logger.debug "node.rb: resolving node key '#{key}', with passed global value of '#{
|
207
|
+
model_name = @model.class.name.to_s.downcase
|
208
|
+
Oxidized.logger.debug "node.rb: resolving node key '#{key}', with passed global value of '#{global}' and node value '#{opt[key_sym]}'"
|
206
209
|
|
207
|
-
#
|
208
|
-
if
|
209
|
-
value =
|
210
|
-
Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from
|
211
|
-
end
|
210
|
+
# Node
|
211
|
+
if opt[key_sym]
|
212
|
+
value = opt[key_sym]
|
213
|
+
Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from node"
|
212
214
|
|
213
|
-
#
|
214
|
-
|
215
|
+
# Group specific model
|
216
|
+
elsif Oxidized.config.groups.has_key?(@group) && Oxidized.config.groups[@group].models.has_key?(model_name) && Oxidized.config.groups[@group].models[model_name].has_key?(key_str)
|
217
|
+
value = Oxidized.config.groups[@group].models[model_name][key_str]
|
218
|
+
Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from model in group"
|
219
|
+
|
220
|
+
# Group
|
221
|
+
elsif Oxidized.config.groups.has_key?(@group) && Oxidized.config.groups[@group].has_key?(key_str)
|
215
222
|
value = Oxidized.config.groups[@group][key_str]
|
216
223
|
Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from group"
|
217
|
-
end
|
218
224
|
|
219
|
-
#
|
220
|
-
|
221
|
-
value = Oxidized.config.models[
|
225
|
+
# Model
|
226
|
+
elsif Oxidized.config.models.has_key?(model_name) && Oxidized.config.models[model_name].has_key?(key_str)
|
227
|
+
value = Oxidized.config.models[model_name][key_str]
|
222
228
|
Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from model"
|
223
|
-
end
|
224
229
|
|
225
|
-
#
|
226
|
-
|
227
|
-
|
230
|
+
# Global passed
|
231
|
+
elsif global
|
232
|
+
value = global
|
233
|
+
Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from passed global value"
|
234
|
+
|
235
|
+
# Global
|
236
|
+
elsif Oxidized.config.has_key?(key_str)
|
237
|
+
value = Oxidized.config[key_str]
|
238
|
+
Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from global"
|
239
|
+
end
|
228
240
|
value
|
229
241
|
end
|
230
242
|
|
data/lib/oxidized/nodes.rb
CHANGED
@@ -61,6 +61,9 @@ module Oxidized
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
+
# Returns the configuration of group/node_name
|
65
|
+
#
|
66
|
+
# #fetch is called by oxidzed-web
|
64
67
|
def fetch(node_name, group)
|
65
68
|
yield_node_output(node_name) do |node, output|
|
66
69
|
output.fetch node, group
|
@@ -69,7 +72,7 @@ module Oxidized
|
|
69
72
|
|
70
73
|
# @param node [String] name of the node moved into the head of array
|
71
74
|
def next(node, opt = {})
|
72
|
-
return
|
75
|
+
return if running.find_index(node)
|
73
76
|
|
74
77
|
with_lock do
|
75
78
|
n = del node
|
@@ -98,6 +101,9 @@ module Oxidized
|
|
98
101
|
find_index(node) || raise(NodeNotFound, "unable to find '#{node}'")
|
99
102
|
end
|
100
103
|
|
104
|
+
# Returns all stored versions of group/node_name
|
105
|
+
#
|
106
|
+
# Called by oxidized-web
|
101
107
|
def version(node_name, group)
|
102
108
|
yield_node_output(node_name) do |node, output|
|
103
109
|
output.version node, group
|
@@ -116,6 +122,10 @@ module Oxidized
|
|
116
122
|
end
|
117
123
|
end
|
118
124
|
|
125
|
+
def find_index(node)
|
126
|
+
index { |e| [e.name, e.ip].include? node }
|
127
|
+
end
|
128
|
+
|
119
129
|
private
|
120
130
|
|
121
131
|
def initialize(opts = {})
|
@@ -133,10 +143,6 @@ module Oxidized
|
|
133
143
|
@mutex.synchronize(...)
|
134
144
|
end
|
135
145
|
|
136
|
-
def find_index(node)
|
137
|
-
index { |e| [e.name, e.ip].include? node }
|
138
|
-
end
|
139
|
-
|
140
146
|
# @param node node which is removed from nodes list
|
141
147
|
# @return [Node] deleted node
|
142
148
|
def del(node)
|
@@ -179,6 +185,8 @@ module Oxidized
|
|
179
185
|
def yield_node_output(node_name)
|
180
186
|
with_lock do
|
181
187
|
node = find { |n| n.name == node_name }
|
188
|
+
raise(NodeNotFound, "unable to find '#{node_name}'") if node.nil?
|
189
|
+
|
182
190
|
output = node.output.new
|
183
191
|
raise NotSupported unless output.respond_to? :fetch
|
184
192
|
|
data/lib/oxidized/output/file.rb
CHANGED
@@ -1,55 +1,58 @@
|
|
1
1
|
module Oxidized
|
2
|
-
|
3
|
-
|
2
|
+
module Output
|
3
|
+
# ruby's File class must be accessed with ::File to avoid name conflicts
|
4
|
+
class File < Output
|
5
|
+
require 'fileutils'
|
4
6
|
|
5
|
-
|
7
|
+
attr_reader :commitref
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def initialize
|
10
|
+
super
|
11
|
+
@cfg = Oxidized.config.output.file
|
12
|
+
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
def setup
|
15
|
+
return unless @cfg.empty?
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
Oxidized.asetus.user.output.file.directory = ::File.join(Config::ROOT, 'configs')
|
18
|
+
Oxidized.asetus.save :user
|
19
|
+
raise NoConfig, "no output file config, edit #{Oxidized::Config.configfile}"
|
20
|
+
end
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
def store(node, outputs, opt = {})
|
23
|
+
file = ::File.expand_path @cfg.directory
|
24
|
+
file = ::File.join ::File.dirname(file), opt[:group] if opt[:group]
|
25
|
+
FileUtils.mkdir_p file
|
26
|
+
file = ::File.join file, node
|
27
|
+
::File.write(file, outputs.to_cfg)
|
28
|
+
@commitref = file
|
29
|
+
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
31
|
+
def fetch(node, group)
|
32
|
+
cfg_dir = ::File.expand_path @cfg.directory
|
33
|
+
node_name = node.name
|
34
|
+
|
35
|
+
if group # group is explicitly defined by user
|
36
|
+
cfg_dir = ::File.join ::File.dirname(cfg_dir), group
|
37
|
+
::File.read ::File.join(cfg_dir, node_name)
|
38
|
+
elsif ::File.exist? ::File.join(cfg_dir, node_name) # node configuration file is stored on base directory
|
39
|
+
::File.read ::File.join(cfg_dir, node_name)
|
40
|
+
else
|
41
|
+
path = Dir.glob(::File.join(::File.dirname(cfg_dir), '**', node_name)).first # fetch node in all groups
|
42
|
+
::File.read path
|
43
|
+
end
|
44
|
+
rescue Errno::ENOENT
|
45
|
+
nil
|
41
46
|
end
|
42
|
-
rescue Errno::ENOENT
|
43
|
-
nil
|
44
|
-
end
|
45
47
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
def version(_node, _group)
|
49
|
+
# not supported
|
50
|
+
[]
|
51
|
+
end
|
50
52
|
|
51
|
-
|
52
|
-
|
53
|
+
def get_version(_node, _group, _oid)
|
54
|
+
'not supported'
|
55
|
+
end
|
53
56
|
end
|
54
57
|
end
|
55
58
|
end
|