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