oxidized 0.30.1 → 0.31.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/ruby.yml +2 -2
- data/.github/workflows/stale.yml +4 -2
- data/.rubocop.yml +18 -2
- data/.rubocop_todo.yml +5 -12
- data/CHANGELOG.md +61 -1
- data/CONTRIBUTING.md +5 -0
- data/Dockerfile +82 -21
- data/README.md +5 -21
- data/Rakefile +3 -2
- data/docs/Configuration.md +36 -12
- data/docs/Creating-Models.md +45 -4
- data/docs/Hooks.md +34 -0
- data/docs/Issues.md +91 -0
- data/docs/Model-Notes/Cumulus.md +5 -0
- data/docs/Model-Notes/FSOS.md +5 -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/Outputs.md +2 -0
- data/docs/Release.md +18 -15
- data/docs/Sources.md +21 -0
- data/docs/Supported-OS-Types.md +11 -5
- data/docs/Troubleshooting.md +35 -0
- data/examples/device-simulation/README.md +173 -0
- data/examples/device-simulation/cmdsets/aoscx +9 -0
- data/examples/device-simulation/cmdsets/arubainstant +5 -0
- data/examples/device-simulation/cmdsets/asa +7 -0
- data/examples/device-simulation/cmdsets/ios +7 -0
- data/examples/device-simulation/cmdsets/nxos +5 -0
- data/examples/device-simulation/cmdsets/routeros +5 -0
- data/examples/device-simulation/cmdsets/srosmd +11 -0
- data/examples/device-simulation/device2yaml.rb +225 -0
- data/examples/device-simulation/yaml/aoscx_R0X25A-6410_FL.10.10.1100.yaml +2281 -0
- data/examples/device-simulation/yaml/aoscx_R8N85A-C6000-48G-CL4_PL.10.08.1010.yaml +451 -0
- data/examples/device-simulation/yaml/arubainstant_IAP515_8.10.0.6_VWLC.yaml +213 -0
- data/examples/device-simulation/yaml/asa_5512_9.12-4-67_single-context.yaml +531 -0
- data/examples/device-simulation/yaml/asr920_16.8.1b.yaml +1122 -0
- data/examples/device-simulation/yaml/garderos_R7709_003_006_068.yaml +101 -0
- data/examples/device-simulation/yaml/iosxe_C9200L-24P-4G_17.09.04a.yaml +514 -0
- data/examples/device-simulation/yaml/iosxe_C9800-L-F-K9_17.06.05.yaml +417 -0
- data/examples/device-simulation/yaml/riverbed_915.yaml +123 -0
- data/examples/device-simulation/yaml/routeros_CHR_7.10.1.yaml +145 -0
- data/examples/device-simulation/yaml/routeros_CHR_7.16.yaml +79 -0
- data/examples/device-simulation/yaml/routeros_L009UiGS_7.15.2.yaml +353 -0
- data/examples/podman-compose/Makefile +60 -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/lib/oxidized/config.rb +7 -1
- 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/telnet.rb +1 -1
- data/lib/oxidized/manager.rb +17 -16
- data/lib/oxidized/model/aoscx.rb +16 -2
- data/lib/oxidized/model/aosw.rb +7 -1
- data/lib/oxidized/model/arubainstant.rb +90 -0
- data/lib/oxidized/model/audiocodes.rb +2 -2
- data/lib/oxidized/model/cnos.rb +13 -10
- data/lib/oxidized/model/cumulus.rb +3 -0
- 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/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/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/lenovonos.rb +2 -0
- data/lib/oxidized/model/linuxgeneric.rb +1 -1
- 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/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 +43 -18
- data/lib/oxidized/source/sql.rb +66 -59
- data/lib/oxidized/version.rb +2 -2
- data/oxidized.gemspec +22 -16
- metadata +111 -15
|
@@ -1,227 +1,229 @@
|
|
|
1
1
|
module Oxidized
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
attr_reader :commitref
|
|
2
|
+
module Output
|
|
3
|
+
class GitCrypt < Output
|
|
4
|
+
using Refinements
|
|
5
|
+
class GitCryptError < OxidizedError; end
|
|
6
|
+
begin
|
|
7
|
+
require 'git'
|
|
8
|
+
rescue LoadError
|
|
9
|
+
raise OxidizedError, 'git not found: sudo gem install git'
|
|
10
|
+
end
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
super
|
|
15
|
-
@cfg = Oxidized.config.output.gitcrypt
|
|
16
|
-
@gitcrypt_cmd = "/usr/bin/git-crypt"
|
|
17
|
-
@gitcrypt_init = @gitcrypt_cmd + " init"
|
|
18
|
-
@gitcrypt_unlock = @gitcrypt_cmd + " unlock"
|
|
19
|
-
@gitcrypt_lock = @gitcrypt_cmd + " lock"
|
|
20
|
-
@gitcrypt_adduser = @gitcrypt_cmd + " add-gpg-user --trusted "
|
|
21
|
-
end
|
|
12
|
+
attr_reader :commitref
|
|
22
13
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Oxidized.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
def initialize
|
|
15
|
+
super
|
|
16
|
+
@cfg = Oxidized.config.output.gitcrypt
|
|
17
|
+
@gitcrypt_cmd = "/usr/bin/git-crypt"
|
|
18
|
+
@gitcrypt_init = @gitcrypt_cmd + " init"
|
|
19
|
+
@gitcrypt_unlock = @gitcrypt_cmd + " unlock"
|
|
20
|
+
@gitcrypt_lock = @gitcrypt_cmd + " lock"
|
|
21
|
+
@gitcrypt_adduser = @gitcrypt_cmd + " add-gpg-user --trusted "
|
|
30
22
|
end
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
@cfg.
|
|
34
|
-
|
|
24
|
+
def setup
|
|
25
|
+
if @cfg.empty?
|
|
26
|
+
Oxidized.asetus.user.output.gitcrypt.user = 'Oxidized'
|
|
27
|
+
Oxidized.asetus.user.output.gitcrypt.email = 'o@example.com'
|
|
28
|
+
Oxidized.asetus.user.output.gitcrypt.repo = File.join(Config::ROOT, 'oxidized.git')
|
|
29
|
+
Oxidized.asetus.save :user
|
|
30
|
+
raise NoConfig, "no output git config, edit #{Oxidized::Config.configfile}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
if @cfg.repo.respond_to?(:each)
|
|
34
|
+
@cfg.repo.each do |group, repo|
|
|
35
|
+
@cfg.repo["#{group}="] = File.expand_path repo
|
|
36
|
+
end
|
|
37
|
+
else
|
|
38
|
+
@cfg.repo = File.expand_path @cfg.repo
|
|
35
39
|
end
|
|
36
|
-
else
|
|
37
|
-
@cfg.repo = File.expand_path @cfg.repo
|
|
38
40
|
end
|
|
39
|
-
end
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
def crypt_init(repo)
|
|
43
|
+
repo.chdir do
|
|
44
|
+
system(@gitcrypt_init)
|
|
45
|
+
@cfg.users.each do |user|
|
|
46
|
+
system("#{@gitcrypt_adduser} #{user}")
|
|
47
|
+
end
|
|
48
|
+
File.write(".gitattributes", "* filter=git-crypt diff=git-crypt\n.gitattributes !filter !diff")
|
|
49
|
+
repo.add(".gitattributes")
|
|
50
|
+
repo.commit("Initial commit: crypt all config files")
|
|
46
51
|
end
|
|
47
|
-
File.write(".gitattributes", "* filter=git-crypt diff=git-crypt\n.gitattributes !filter !diff")
|
|
48
|
-
repo.add(".gitattributes")
|
|
49
|
-
repo.commit("Initial commit: crypt all config files")
|
|
50
52
|
end
|
|
51
|
-
end
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
def lock(repo)
|
|
55
|
+
repo.chdir do
|
|
56
|
+
system(@gitcrypt_lock)
|
|
57
|
+
end
|
|
56
58
|
end
|
|
57
|
-
end
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
def unlock(repo)
|
|
61
|
+
repo.chdir do
|
|
62
|
+
system(@gitcrypt_unlock)
|
|
63
|
+
end
|
|
62
64
|
end
|
|
63
|
-
end
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
66
|
+
def store(file, outputs, opt = {})
|
|
67
|
+
@msg = opt[:msg]
|
|
68
|
+
@user = opt[:user] || @cfg.user
|
|
69
|
+
@email = opt[:email] || @cfg.email
|
|
70
|
+
@opt = opt
|
|
71
|
+
@commitref = nil
|
|
72
|
+
repo = @cfg.repo
|
|
73
|
+
|
|
74
|
+
outputs.types.each do |type|
|
|
75
|
+
type_cfg = ''
|
|
76
|
+
type_repo = File.join(File.dirname(repo), type + '.git')
|
|
77
|
+
outputs.type(type).each do |output|
|
|
78
|
+
(type_cfg << output; next) unless output.name # rubocop:disable Style/Semicolon
|
|
79
|
+
type_file = file + '--' + output.name
|
|
80
|
+
if @cfg.type_as_directory?
|
|
81
|
+
type_file = type + '/' + type_file
|
|
82
|
+
type_repo = repo
|
|
83
|
+
end
|
|
84
|
+
update type_repo, type_file, output
|
|
82
85
|
end
|
|
83
|
-
update type_repo,
|
|
86
|
+
update type_repo, file, type_cfg
|
|
84
87
|
end
|
|
85
|
-
update type_repo, file, type_cfg
|
|
86
|
-
end
|
|
87
88
|
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
update repo, file, outputs.to_cfg
|
|
90
|
+
end
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
def fetch(node, group)
|
|
93
|
+
repo, path = yield_repo_and_path(node, group)
|
|
94
|
+
repo = Git.open repo
|
|
95
|
+
unlock repo
|
|
96
|
+
index = repo.index
|
|
97
|
+
# Empty repo ?
|
|
98
|
+
raise 'Empty git repo' if File.exist?(index.path)
|
|
99
|
+
|
|
100
|
+
File.read path
|
|
101
|
+
lock repo
|
|
102
|
+
rescue StandardError
|
|
103
|
+
'node not found'
|
|
104
|
+
end
|
|
104
105
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
106
|
+
# give a hash of all oid revision for the given node, and the date of the commit
|
|
107
|
+
def version(node, group)
|
|
108
|
+
repo, path = yield_repo_and_path(node, group)
|
|
109
|
+
|
|
110
|
+
repo = Git.open repo
|
|
111
|
+
unlock repo
|
|
112
|
+
walker = repo.log.path(path)
|
|
113
|
+
i = -1
|
|
114
|
+
tab = []
|
|
115
|
+
walker.each do |commit|
|
|
116
|
+
hash = {}
|
|
117
|
+
hash[:date] = commit.date.to_s
|
|
118
|
+
hash[:oid] = commit.objectish
|
|
119
|
+
hash[:author] = commit.author
|
|
120
|
+
hash[:message] = commit.message
|
|
121
|
+
tab[i += 1] = hash
|
|
122
|
+
end
|
|
123
|
+
walker.reset
|
|
124
|
+
tab
|
|
125
|
+
rescue StandardError
|
|
126
|
+
'node not found'
|
|
121
127
|
end
|
|
122
|
-
walker.reset
|
|
123
|
-
tab
|
|
124
|
-
rescue StandardError
|
|
125
|
-
'node not found'
|
|
126
|
-
end
|
|
127
128
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
129
|
+
# give the blob of a specific revision
|
|
130
|
+
def get_version(node, group, oid)
|
|
131
|
+
repo, path = yield_repo_and_path(node, group)
|
|
132
|
+
repo = Git.open repo
|
|
133
|
+
unlock repo
|
|
134
|
+
repo.gtree(oid).files[path].contents
|
|
135
|
+
rescue StandardError
|
|
136
|
+
'version not found'
|
|
137
|
+
ensure
|
|
138
|
+
lock repo
|
|
139
|
+
end
|
|
139
140
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
141
|
+
# give a hash with the patch of a diff between 2 revision and the stats (added and deleted lines)
|
|
142
|
+
def get_diff(node, group, oid1, oid2)
|
|
143
|
+
diff_commits = nil
|
|
144
|
+
repo, _path = yield_repo_and_path(node, group)
|
|
145
|
+
repo = Git.open repo
|
|
146
|
+
unlock repo
|
|
147
|
+
commit = repo.gcommit(oid1)
|
|
148
|
+
|
|
149
|
+
if oid2
|
|
150
|
+
commit_old = repo.gcommit(oid2)
|
|
151
|
+
diff = repo.diff(commit_old, commit)
|
|
152
|
+
stats = [diff.stats[:files][node.name][:insertions], diff.stats[:files][node.name][:deletions]]
|
|
153
|
+
diff.each do |patch|
|
|
154
|
+
if /#{node.name}\s+/ =~ patch.patch.to_s.lines.first
|
|
155
|
+
diff_commits = { patch: patch.patch.to_s, stat: stats }
|
|
156
|
+
break
|
|
157
|
+
end
|
|
156
158
|
end
|
|
159
|
+
else
|
|
160
|
+
stat = commit.parents[0].diff(commit).stats
|
|
161
|
+
stat = [stat[:files][node.name][:insertions], stat[:files][node.name][:deletions]]
|
|
162
|
+
patch = commit.parents[0].diff(commit).patch
|
|
163
|
+
diff_commits = { patch: patch, stat: stat }
|
|
157
164
|
end
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
165
|
+
lock repo
|
|
166
|
+
diff_commits
|
|
167
|
+
rescue StandardError
|
|
168
|
+
'no diffs'
|
|
169
|
+
ensure
|
|
170
|
+
lock repo
|
|
163
171
|
end
|
|
164
|
-
lock repo
|
|
165
|
-
diff_commits
|
|
166
|
-
rescue StandardError
|
|
167
|
-
'no diffs'
|
|
168
|
-
ensure
|
|
169
|
-
lock repo
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
private
|
|
173
172
|
|
|
174
|
-
|
|
175
|
-
repo, path = node.repo, node.name
|
|
173
|
+
private
|
|
176
174
|
|
|
177
|
-
|
|
175
|
+
def yield_repo_and_path(node, group)
|
|
176
|
+
repo, path = node.repo, node.name
|
|
178
177
|
|
|
179
|
-
|
|
180
|
-
end
|
|
178
|
+
path = "#{group}/#{node.name}" if group && @cfg.single_repo?
|
|
181
179
|
|
|
182
|
-
|
|
183
|
-
|
|
180
|
+
[repo, path]
|
|
181
|
+
end
|
|
184
182
|
|
|
185
|
-
|
|
186
|
-
if
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
183
|
+
def update(repo, file, data)
|
|
184
|
+
return if data.empty?
|
|
185
|
+
|
|
186
|
+
if @opt[:group]
|
|
187
|
+
if @cfg.single_repo?
|
|
188
|
+
file = File.join @opt[:group], file
|
|
189
|
+
else
|
|
190
|
+
repo = if repo.is_a?(::String)
|
|
191
|
+
File.join File.dirname(repo), @opt[:group] + '.git'
|
|
192
|
+
else
|
|
193
|
+
repo[@opt[:group]]
|
|
194
|
+
end
|
|
195
|
+
end
|
|
194
196
|
end
|
|
195
|
-
end
|
|
196
197
|
|
|
197
|
-
begin
|
|
198
|
-
update_repo repo, file, data, @msg, @user, @email
|
|
199
|
-
rescue Git::GitExecuteError, ArgumentError => e
|
|
200
|
-
Oxidized.logger.debug "open_error #{e} #{file}"
|
|
201
198
|
begin
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
199
|
+
update_repo repo, file, data, @msg, @user, @email
|
|
200
|
+
rescue Git::GitExecuteError, ArgumentError => e
|
|
201
|
+
Oxidized.logger.debug "open_error #{e} #{file}"
|
|
202
|
+
begin
|
|
203
|
+
grepo = Git.init repo
|
|
204
|
+
crypt_init grepo
|
|
205
|
+
rescue StandardError => create_error
|
|
206
|
+
raise GitCryptError, "first '#{e.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo"
|
|
207
|
+
end
|
|
208
|
+
retry
|
|
206
209
|
end
|
|
207
|
-
retry
|
|
208
210
|
end
|
|
209
|
-
end
|
|
210
211
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
212
|
+
def update_repo(repo, file, data, msg, user, email)
|
|
213
|
+
grepo = Git.open repo
|
|
214
|
+
grepo.config('user.name', user)
|
|
215
|
+
grepo.config('user.email', email)
|
|
216
|
+
grepo.chdir do
|
|
217
|
+
unlock grepo
|
|
218
|
+
File.write(file, data)
|
|
219
|
+
grepo.add(file)
|
|
220
|
+
if grepo.status[file].nil? || !grepo.status[file].type.nil?
|
|
221
|
+
grepo.commit(msg)
|
|
222
|
+
@commitref = grepo.log(1).first.objectish
|
|
223
|
+
true
|
|
224
|
+
end
|
|
225
|
+
lock grepo
|
|
223
226
|
end
|
|
224
|
-
lock grepo
|
|
225
227
|
end
|
|
226
228
|
end
|
|
227
229
|
end
|
data/lib/oxidized/output/http.rb
CHANGED
|
@@ -1,61 +1,63 @@
|
|
|
1
1
|
module Oxidized
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
module Output
|
|
3
|
+
class Http < Output
|
|
4
|
+
attr_reader :commitref
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
def initialize
|
|
7
|
+
super
|
|
8
|
+
@cfg = Oxidized.config.output.http
|
|
9
|
+
end
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
def setup
|
|
12
|
+
return unless @cfg.empty?
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
Oxidized.asetus.user.output.http.user = 'Oxidized'
|
|
15
|
+
Oxidized.asetus.user.output.http.pasword = 'secret'
|
|
16
|
+
Oxidized.asetus.user.output.http.url = 'http://localhost/web-api/oxidized'
|
|
17
|
+
Oxidized.asetus.save :user
|
|
18
|
+
raise NoConfig, "no output http config, edit #{Oxidized::Config.configfile}"
|
|
19
|
+
end
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
21
|
+
require "net/http"
|
|
22
|
+
require "uri"
|
|
23
|
+
require "json"
|
|
24
|
+
|
|
25
|
+
def store(node, outputs, opt = {})
|
|
26
|
+
@commitref = nil
|
|
27
|
+
uri = URI.parse @cfg.url
|
|
28
|
+
http = Net::HTTP.new uri.host, uri.port
|
|
29
|
+
# http.use_ssl = true if uri.scheme = 'https'
|
|
30
|
+
req = Net::HTTP::Post.new(uri.request_uri, 'Content-Type' => 'application/json')
|
|
31
|
+
req.basic_auth @cfg.user, @cfg.password
|
|
32
|
+
req.body = generate_json(node, outputs, opt)
|
|
33
|
+
response = http.request req
|
|
34
|
+
|
|
35
|
+
case response.code.to_i
|
|
36
|
+
when 200 || 201
|
|
37
|
+
Oxidized.logger.info "Configuration http backup complete for #{node}"
|
|
38
|
+
p [:success]
|
|
39
|
+
when (400..499)
|
|
40
|
+
Oxidized.logger.info "Configuration http backup for #{node} failed status: #{response.body}"
|
|
41
|
+
p [:bad_request]
|
|
42
|
+
when (500..599)
|
|
43
|
+
p [:server_problems]
|
|
44
|
+
Oxidized.logger.info "Configuration http backup for #{node} failed status: #{response.body}"
|
|
45
|
+
end
|
|
44
46
|
end
|
|
45
|
-
end
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def generate_json(node, outputs, opt)
|
|
51
|
+
JSON.pretty_generate(
|
|
52
|
+
'msg' => opt[:msg],
|
|
53
|
+
'user' => opt[:user],
|
|
54
|
+
'email' => opt[:email],
|
|
55
|
+
'group' => opt[:group],
|
|
56
|
+
'node' => node,
|
|
57
|
+
'config' => outputs.to_cfg
|
|
58
|
+
# actually we need to also iterate outputs, for other types like in gitlab. But most people don't use 'type' functionality.
|
|
59
|
+
)
|
|
60
|
+
end
|
|
59
61
|
end
|
|
60
62
|
end
|
|
61
63
|
end
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
module Oxidized
|
|
2
|
-
|
|
3
|
-
class
|
|
2
|
+
module Output
|
|
3
|
+
class Output
|
|
4
|
+
class NoConfig < OxidizedError; end
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
def cfg_to_str(cfg)
|
|
7
|
+
cfg.select { |h| h[:type] == 'cfg' }.map { |h| h[:data] }.join
|
|
8
|
+
end
|
|
7
9
|
end
|
|
8
10
|
end
|
|
9
11
|
end
|
data/lib/oxidized/source/csv.rb
CHANGED
|
@@ -1,60 +1,55 @@
|
|
|
1
1
|
module Oxidized
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def setup
|
|
9
|
-
if @cfg.empty?
|
|
10
|
-
Oxidized.asetus.user.source.csv.file = File.join(Config::ROOT, 'router.db')
|
|
11
|
-
Oxidized.asetus.user.source.csv.delimiter = /:/
|
|
12
|
-
Oxidized.asetus.user.source.csv.map.name = 0
|
|
13
|
-
Oxidized.asetus.user.source.csv.map.model = 1
|
|
14
|
-
Oxidized.asetus.user.source.csv.gpg = false
|
|
15
|
-
Oxidized.asetus.save :user
|
|
16
|
-
raise NoConfig, 'no source csv config, edit ~/.config/oxidized/config'
|
|
2
|
+
module Source
|
|
3
|
+
class CSV < Source
|
|
4
|
+
def initialize
|
|
5
|
+
@cfg = Oxidized.config.source.csv
|
|
6
|
+
super
|
|
17
7
|
end
|
|
18
|
-
require 'gpgme' if @cfg.gpg?
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def load(_node_want = nil)
|
|
22
|
-
nodes = []
|
|
23
|
-
open_file.each_line do |line|
|
|
24
|
-
next if line =~ /^\s*#/
|
|
25
|
-
|
|
26
|
-
data = line.chomp.split(@cfg.delimiter, -1)
|
|
27
|
-
next if data.empty?
|
|
28
8
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
9
|
+
def setup
|
|
10
|
+
if @cfg.empty?
|
|
11
|
+
Oxidized.asetus.user.source.csv.file = File.join(Config::ROOT, 'router.db')
|
|
12
|
+
Oxidized.asetus.user.source.csv.delimiter = /:/
|
|
13
|
+
Oxidized.asetus.user.source.csv.map.name = 0
|
|
14
|
+
Oxidized.asetus.user.source.csv.map.model = 1
|
|
15
|
+
Oxidized.asetus.user.source.csv.gpg = false
|
|
16
|
+
Oxidized.asetus.save :user
|
|
17
|
+
raise NoConfig, "no source csv config, edit #{Oxidized::Config.configfile}"
|
|
33
18
|
end
|
|
34
|
-
|
|
35
|
-
keys[:group] = map_group keys[:group] if keys.has_key? :group
|
|
19
|
+
require 'gpgme' if @cfg.gpg?
|
|
36
20
|
|
|
37
|
-
# map
|
|
38
|
-
|
|
39
|
-
@cfg.vars_map.each do |key, position|
|
|
40
|
-
vars[key.to_sym] = node_var_interpolate data[position]
|
|
41
|
-
end
|
|
42
|
-
keys[:vars] = vars unless vars.empty?
|
|
21
|
+
# map.name is mandatory
|
|
22
|
+
return if @cfg.map.has_key?('name')
|
|
43
23
|
|
|
44
|
-
|
|
24
|
+
raise InvalidConfig, "map/name is a mandatory source attribute, edit #{Oxidized::Config.configfile}"
|
|
45
25
|
end
|
|
46
|
-
nodes
|
|
47
|
-
end
|
|
48
26
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
27
|
+
def load(_node_want = nil)
|
|
28
|
+
nodes = []
|
|
29
|
+
open_file.each_line do |line|
|
|
30
|
+
next if line =~ /^\s*#/
|
|
31
|
+
|
|
32
|
+
data = line.chomp.split(@cfg.delimiter, -1)
|
|
33
|
+
next if data.empty?
|
|
34
|
+
|
|
35
|
+
# map node parameters
|
|
36
|
+
keys = {}
|
|
37
|
+
@cfg.map.each do |key, position|
|
|
38
|
+
keys[key.to_sym] = node_var_interpolate data[position]
|
|
39
|
+
end
|
|
40
|
+
keys[:model] = map_model keys[:model] if keys.has_key? :model
|
|
41
|
+
keys[:group] = map_group keys[:group] if keys.has_key? :group
|
|
42
|
+
|
|
43
|
+
# map node specific vars
|
|
44
|
+
vars = {}
|
|
45
|
+
@cfg.vars_map.each do |key, position|
|
|
46
|
+
vars[key.to_sym] = node_var_interpolate data[position]
|
|
47
|
+
end
|
|
48
|
+
keys[:vars] = vars unless vars.empty?
|
|
49
|
+
|
|
50
|
+
nodes << keys
|
|
51
|
+
end
|
|
52
|
+
nodes
|
|
58
53
|
end
|
|
59
54
|
end
|
|
60
55
|
end
|