oxidized 0.33.0 → 0.34.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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +4 -1
  3. data/.github/ISSUE_TEMPLATE/support-request.md +4 -1
  4. data/.github/workflows/ruby.yml +4 -2
  5. data/.gitignore +1 -0
  6. data/.rubocop.yml +29 -6
  7. data/.rubocop_todo.yml +2 -35
  8. data/CHANGELOG.md +49 -0
  9. data/CONTRIBUTING.md +10 -3
  10. data/Dockerfile +4 -4
  11. data/README.md +52 -55
  12. data/Rakefile +2 -3
  13. data/docs/Configuration.md +97 -0
  14. data/docs/DeviceSimulation.md +19 -7
  15. data/docs/Docker.md +9 -4
  16. data/docs/Issues.md +11 -2
  17. data/docs/ModelUnitTests.md +35 -25
  18. data/docs/Outputs.md +83 -2
  19. data/docs/Release.md +30 -22
  20. data/docs/Supported-OS-Types.md +4 -0
  21. data/docs/Troubleshooting.md +4 -18
  22. data/extra/device2yaml.rb +24 -9
  23. data/extra/rest_client.rb +2 -1
  24. data/extra/syslog.rb +8 -3
  25. data/lib/oxidized/cli.rb +7 -3
  26. data/lib/oxidized/config/vars.rb +7 -3
  27. data/lib/oxidized/config.rb +0 -1
  28. data/lib/oxidized/core.rb +5 -4
  29. data/lib/oxidized/hook/ciscosparkdiff.rb +11 -9
  30. data/lib/oxidized/hook/exec.rb +5 -4
  31. data/lib/oxidized/hook/githubrepo.rb +23 -17
  32. data/lib/oxidized/hook/noophook.rb +2 -2
  33. data/lib/oxidized/hook/slackdiff.rb +9 -8
  34. data/lib/oxidized/hook/xmppdiff.rb +9 -9
  35. data/lib/oxidized/hook.rb +10 -8
  36. data/lib/oxidized/input/cli.rb +8 -3
  37. data/lib/oxidized/input/exec.rb +1 -1
  38. data/lib/oxidized/input/ftp.rb +2 -2
  39. data/lib/oxidized/input/http.rb +5 -5
  40. data/lib/oxidized/input/input.rb +1 -0
  41. data/lib/oxidized/input/scp.rb +2 -2
  42. data/lib/oxidized/input/ssh.rb +21 -14
  43. data/lib/oxidized/input/telnet.rb +3 -3
  44. data/lib/oxidized/input/tftp.rb +1 -1
  45. data/lib/oxidized/job.rb +7 -4
  46. data/lib/oxidized/logger.rb +51 -0
  47. data/lib/oxidized/model/acos.rb +1 -0
  48. data/lib/oxidized/model/aos7.rb +6 -0
  49. data/lib/oxidized/model/aoscx.rb +2 -0
  50. data/lib/oxidized/model/aosw.rb +22 -17
  51. data/lib/oxidized/model/aricentiss.rb +2 -2
  52. data/lib/oxidized/model/asa.rb +3 -3
  53. data/lib/oxidized/model/awplus.rb +13 -10
  54. data/lib/oxidized/model/edgecos.rb +2 -1
  55. data/lib/oxidized/model/edgeos.rb +7 -6
  56. data/lib/oxidized/model/edgeswitch.rb +3 -1
  57. data/lib/oxidized/model/efos.rb +41 -0
  58. data/lib/oxidized/model/eltex.rb +1 -1
  59. data/lib/oxidized/model/fabricos.rb +1 -1
  60. data/lib/oxidized/model/fastiron.rb +3 -1
  61. data/lib/oxidized/model/firelinuxos.rb +12 -3
  62. data/lib/oxidized/model/fortios.rb +2 -1
  63. data/lib/oxidized/model/gaiaos.rb +4 -4
  64. data/lib/oxidized/model/ios.rb +15 -5
  65. data/lib/oxidized/model/ironware.rb +1 -1
  66. data/lib/oxidized/model/junos.rb +4 -0
  67. data/lib/oxidized/model/linksyssrw.rb +3 -3
  68. data/lib/oxidized/model/mlnxos.rb +14 -7
  69. data/lib/oxidized/model/model.rb +4 -3
  70. data/lib/oxidized/model/netgear.rb +2 -0
  71. data/lib/oxidized/model/nsxdfw.rb +2 -1
  72. data/lib/oxidized/model/nsxfirewall.rb +2 -1
  73. data/lib/oxidized/model/nxos.rb +2 -2
  74. data/lib/oxidized/model/openwrt.rb +6 -6
  75. data/lib/oxidized/model/procurve.rb +3 -1
  76. data/lib/oxidized/model/qtech.rb +3 -1
  77. data/lib/oxidized/model/quantaos.rb +8 -6
  78. data/lib/oxidized/model/routeros.rb +3 -2
  79. data/lib/oxidized/model/saos10.rb +38 -0
  80. data/lib/oxidized/model/sixwind.rb +28 -0
  81. data/lib/oxidized/model/sonicos.rb +1 -1
  82. data/lib/oxidized/model/supermicro.rb +1 -1
  83. data/lib/oxidized/model/timos.rb +1 -1
  84. data/lib/oxidized/model/tmos.rb +1 -0
  85. data/lib/oxidized/model/tnsr.rb +53 -0
  86. data/lib/oxidized/model/trango.rb +3 -1
  87. data/lib/oxidized/model/unifiap.rb +7 -5
  88. data/lib/oxidized/model/vrp.rb +3 -1
  89. data/lib/oxidized/model/xos.rb +3 -1
  90. data/lib/oxidized/model/zhoneolt.rb +3 -1
  91. data/lib/oxidized/model/zynos.rb +3 -3
  92. data/lib/oxidized/node.rb +44 -27
  93. data/lib/oxidized/nodes.rb +8 -4
  94. data/lib/oxidized/output/file.rb +28 -0
  95. data/lib/oxidized/output/git.rb +66 -9
  96. data/lib/oxidized/output/gitcrypt.rb +15 -13
  97. data/lib/oxidized/output/http.rb +5 -4
  98. data/lib/oxidized/output/output.rb +14 -0
  99. data/lib/oxidized/source/http.rb +4 -2
  100. data/lib/oxidized/version.rb +2 -2
  101. data/lib/oxidized/worker.rb +11 -8
  102. data/lib/oxidized.rb +3 -24
  103. data/oxidized.gemspec +8 -5
  104. metadata +54 -21
data/lib/oxidized/node.rb CHANGED
@@ -6,15 +6,18 @@ module Oxidized
6
6
  class ModelNotFound < OxidizedError; end
7
7
 
8
8
  class Node
9
+ include SemanticLogger::Loggable
10
+
9
11
  attr_reader :name, :ip, :model, :input, :output, :group, :auth, :prompt, :vars, :last, :repo
10
12
  attr_accessor :running, :user, :email, :msg, :from, :stats, :retry, :err_type, :err_reason
11
13
  alias running? running
12
14
 
15
+ # opt is a hash with the node parameters given in the source (:name, :group, :ip...)
13
16
  def initialize(opt)
14
- Oxidized.logger.debug 'resolving DNS for %s...' % opt[:name]
17
+ logger.debug 'resolving DNS for %s...' % opt[:name]
15
18
  # remove the prefix if an IP Address is provided with one as IPAddr converts it to a network address.
16
19
  ip_addr, = opt[:ip].to_s.split("/")
17
- Oxidized.logger.debug 'IPADDR %s' % ip_addr.to_s
20
+ logger.debug 'IPADDR %s' % ip_addr.to_s
18
21
  @name = opt[:name]
19
22
  @ip = IPAddr.new(ip_addr).to_s rescue nil
20
23
  @ip ||= Resolv.new.getaddress(@name) if Oxidized.config.resolve_dns?
@@ -37,7 +40,8 @@ module Oxidized
37
40
  end
38
41
 
39
42
  def run
40
- status, config = :fail, nil
43
+ status = :fail
44
+ config = nil
41
45
  @input.each do |input|
42
46
  # don't try input if model is missing config block, we may need strong config to class_name map
43
47
  cfg_name = input.to_s.split('::').last.downcase
@@ -45,14 +49,16 @@ module Oxidized
45
49
 
46
50
  @model.input = input = input.new
47
51
  if (config = run_input(input))
48
- Oxidized.logger.debug "lib/oxidized/node.rb: #{input.class.name} ran for #{name} successfully"
52
+ logger.debug "#{input.class.name} ran for #{name} successfully"
49
53
  status = :success
50
54
  break
51
55
  else
52
- Oxidized.logger.debug "lib/oxidized/node.rb: #{input.class.name} failed for #{name}"
56
+ logger.debug "#{input.class.name} failed for #{name}"
53
57
  status = :no_connection
54
58
  end
55
59
  end
60
+ logger.error "No suitable input found for #{name}" unless @model.input
61
+
56
62
  @model.input = nil
57
63
  [status, config]
58
64
  end
@@ -75,13 +81,18 @@ module Oxidized
75
81
  level = rescue_fail[resc]
76
82
  resc = " (rescued #{resc})"
77
83
  end
78
- Oxidized.logger.send(level, '%s raised %s%s with msg "%s"' % [ip, err.class, resc, err.message])
84
+ logger.send(level, '%s raised %s%s with msg "%s"' % [ip, err.class, resc, err.message])
79
85
  @err_type = err.class.to_s
80
86
  @err_reason = err.message.to_s
81
87
  false
82
88
  rescue StandardError => e
83
89
  # 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])
90
+ logger.error "#{ip} raised #{e.class} with msg #{e.message}, creating crashfile"
91
+ unless Oxidized.config.crash.directory?
92
+ logger.error "Cannot create crashfile for exception", e
93
+ return false
94
+ end
95
+
85
96
  crashdir = Oxidized.config.crash.directory
86
97
  crashfile = Oxidized.config.crash.hostnames? ? name : ip.to_s
87
98
  FileUtils.mkdir_p(crashdir) unless File.directory?(crashdir)
@@ -92,7 +103,7 @@ module Oxidized
92
103
  fh.puts '-' * 50
93
104
  fh.puts e.backtrace
94
105
  end
95
- Oxidized.logger.error '%s raised %s with msg "%s", %s saved' % [ip, e.class, e.message, crashfile]
106
+ logger.error '%s raised %s with msg "%s", %s saved' % [ip, e.class, e.message, crashfile]
96
107
  @err_type = e.class.to_s
97
108
  @err_reason = e.message.to_s
98
109
  false
@@ -122,14 +133,10 @@ module Oxidized
122
133
  h
123
134
  end
124
135
 
136
+ JobStruct = Struct.new(:start, :end, :status, :time)
125
137
  def last=(job)
126
138
  if job
127
- ostruct = OpenStruct.new
128
- ostruct.start = job.start
129
- ostruct.end = job.end
130
- ostruct.status = job.status
131
- ostruct.time = job.time
132
- @last = ostruct
139
+ @last = JobStruct.new(job.start, job.end, job.status, job.time)
133
140
  else
134
141
  @last = nil
135
142
  end
@@ -160,8 +167,11 @@ module Oxidized
160
167
 
161
168
  def resolve_input(opt)
162
169
  inputs = resolve_key :input, opt, Oxidized.config.input.default
163
- inputs.split(/\s*,\s*/).map do |input|
164
- Oxidized.mgr.add_input(input) || raise(MethodNotFound, "#{input} not found for node #{ip}") unless Oxidized.mgr.input[input]
170
+ inputs.split(',').map do |input|
171
+ input.strip!
172
+ unless Oxidized.mgr.input[input]
173
+ Oxidized.mgr.add_input(input) || raise(MethodNotFound, "#{input} not found for node #{ip}")
174
+ end
165
175
 
166
176
  Oxidized.mgr.input[input]
167
177
  end
@@ -169,7 +179,10 @@ module Oxidized
169
179
 
170
180
  def resolve_output(opt)
171
181
  output = resolve_key :output, opt, Oxidized.config.output.default
172
- Oxidized.mgr.add_output(output) || raise(MethodNotFound, "#{output} not found for node #{ip}") unless Oxidized.mgr.output[output]
182
+ unless Oxidized.mgr.output[output]
183
+ Oxidized.mgr.add_output(output) || raise(MethodNotFound,
184
+ "#{output} not found for node #{ip}")
185
+ end
173
186
 
174
187
  Oxidized.mgr.output[output]
175
188
  end
@@ -177,7 +190,7 @@ module Oxidized
177
190
  def resolve_model(opt)
178
191
  model = resolve_key :model, opt
179
192
  unless Oxidized.mgr.model[model]
180
- Oxidized.logger.debug "lib/oxidized/node.rb: Loading model #{model.inspect}"
193
+ logger.debug "Loading model #{model.inspect}"
181
194
  Oxidized.mgr.add_model(model) || raise(ModelNotFound, "#{model} not found for node #{ip}")
182
195
  end
183
196
  Oxidized.mgr.model[model].new
@@ -200,42 +213,46 @@ module Oxidized
200
213
  end
201
214
 
202
215
  def resolve_key(key, opt, global = nil)
203
- # resolve key: the priority is as follows: node -> group specific model -> group -> model -> global passed -> global
216
+ # resolve key: the priority is as follows:
217
+ # node -> group specific model -> group -> model -> global passed -> global
204
218
  # where node has the highest priority (= if defined, overwrites other values)
205
219
  key_sym = key.to_sym
206
220
  key_str = key.to_s
207
221
  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]}'"
222
+ logger.debug "resolving node key '#{key}', with passed global value of '#{global}' " \
223
+ "and node value '#{opt[key_sym]}'"
209
224
 
210
225
  # Node
211
226
  if opt[key_sym]
212
227
  value = opt[key_sym]
213
- Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from node"
228
+ logger.debug "setting node key '#{key}' to value '#{value}' from node"
214
229
 
215
230
  # 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)
231
+ elsif Oxidized.config.groups.has_key?(@group) &&
232
+ Oxidized.config.groups[@group].models.has_key?(model_name) &&
233
+ Oxidized.config.groups[@group].models[model_name].has_key?(key_str)
217
234
  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"
235
+ logger.debug "setting node key '#{key}' to value '#{value}' from model in group"
219
236
 
220
237
  # Group
221
238
  elsif Oxidized.config.groups.has_key?(@group) && Oxidized.config.groups[@group].has_key?(key_str)
222
239
  value = Oxidized.config.groups[@group][key_str]
223
- Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from group"
240
+ logger.debug "setting node key '#{key}' to value '#{value}' from group"
224
241
 
225
242
  # Model
226
243
  elsif Oxidized.config.models.has_key?(model_name) && Oxidized.config.models[model_name].has_key?(key_str)
227
244
  value = Oxidized.config.models[model_name][key_str]
228
- Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from model"
245
+ logger.debug "setting node key '#{key}' to value '#{value}' from model"
229
246
 
230
247
  # Global passed
231
248
  elsif global
232
249
  value = global
233
- Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from passed global value"
250
+ logger.debug "setting node key '#{key}' to value '#{value}' from passed global value"
234
251
 
235
252
  # Global
236
253
  elsif Oxidized.config.has_key?(key_str)
237
254
  value = Oxidized.config[key_str]
238
- Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from global"
255
+ logger.debug "setting node key '#{key}' to value '#{value}' from global"
239
256
  end
240
257
  value
241
258
  end
@@ -5,6 +5,8 @@ module Oxidized
5
5
  class NodeNotFound < OxidizedError; end
6
6
 
7
7
  class Nodes < Array
8
+ include SemanticLogger::Loggable
9
+
8
10
  attr_accessor :source, :jobs
9
11
  alias put unshift
10
12
  def load(node_want = nil)
@@ -12,7 +14,7 @@ module Oxidized
12
14
  new = []
13
15
  @source = Oxidized.config.source.default
14
16
  Oxidized.mgr.add_source(@source) || raise(MethodNotFound, "cannot load node source '#{@source}', not found")
15
- Oxidized.logger.info "lib/oxidized/nodes.rb: Loading nodes"
17
+ logger.info "Loading nodes"
16
18
  nodes = Oxidized.mgr.source[@source].new.load node_want
17
19
  nodes.each do |node|
18
20
  # we want to load specific node(s), not all of them
@@ -22,13 +24,14 @@ module Oxidized
22
24
  node_obj = Node.new node
23
25
  new.push node_obj
24
26
  rescue ModelNotFound => e
25
- Oxidized.logger.error "node %s raised %s with message '%s'" % [node, e.class, e.message]
27
+ logger.error "node %s raised %s with message '%s'" % [node, e.class, e.message]
26
28
  rescue Resolv::ResolvError => e
27
- Oxidized.logger.error "node %s is not resolvable, raised %s with message '%s'" % [node, e.class, e.message]
29
+ logger.error "node %s is not resolvable, raised %s with message '%s'" % [node, e.class, e.message]
28
30
  end
29
31
  end
30
32
  size.zero? ? replace(new) : update_nodes(new)
31
- Oxidized.logger.info "lib/oxidized/nodes.rb: Loaded #{size} nodes"
33
+ Output.clean_obsolete_nodes(self) if node_want.nil?
34
+ logger.info "Loaded #{size} nodes"
32
35
  end
33
36
  end
34
37
 
@@ -74,6 +77,7 @@ module Oxidized
74
77
  def next(node, opt = {})
75
78
  return if running.find_index(node)
76
79
 
80
+ logger.info "Add node #{node} to running jobs"
77
81
  with_lock do
78
82
  n = del node
79
83
  n.user = opt['user']
@@ -19,6 +19,9 @@ module Oxidized
19
19
  raise NoConfig, "no output file config, edit #{Oxidized::Config.configfile}"
20
20
  end
21
21
 
22
+ # node: node name (String)
23
+ # outputs: Oxidized::Models::Outputs
24
+ # opts: hash of node vars
22
25
  def store(node, outputs, opt = {})
23
26
  file = ::File.expand_path @cfg.directory
24
27
  file = ::File.join ::File.dirname(file), opt[:group] if opt[:group]
@@ -53,6 +56,31 @@ module Oxidized
53
56
  def get_version(_node, _group, _oid)
54
57
  'not supported'
55
58
  end
59
+
60
+ def self.node_path(node_name, group_name = nil)
61
+ cfg_dir = ::File.expand_path Oxidized.config.output.file.directory
62
+
63
+ if group_name
64
+ ::File.join ::File.dirname(cfg_dir), group_name, node_name
65
+ else
66
+ ::File.join cfg_dir, node_name
67
+ end
68
+ end
69
+
70
+ def self.clean_obsolete_nodes(active_nodes)
71
+ cfg_dir = ::File.expand_path Oxidized.config.output.file.directory
72
+ dir_base = ::File.dirname(cfg_dir)
73
+ default_dir = ::File.basename(cfg_dir)
74
+
75
+ keep_files = active_nodes.map { |n| node_path(n.name, n.group) }
76
+ active_groups = active_nodes.map(&:group).compact.uniq
77
+
78
+ [default_dir, *active_groups].each do |group|
79
+ Dir.glob(::File.join(dir_base, group, "*")).each do |file|
80
+ ::File.delete(file) if ::File.file?(file) && !keep_files.include?(file)
81
+ end
82
+ end
83
+ end
56
84
  end
57
85
  end
58
86
  end
@@ -21,17 +21,17 @@ module Oxidized
21
21
  if @cfg.empty?
22
22
  Oxidized.asetus.user.output.git.user = 'Oxidized'
23
23
  Oxidized.asetus.user.output.git.email = 'o@example.com'
24
- Oxidized.asetus.user.output.git.repo = File.join(Config::ROOT, 'oxidized.git')
24
+ Oxidized.asetus.user.output.git.repo = ::File.join(Config::ROOT, 'oxidized.git')
25
25
  Oxidized.asetus.save :user
26
26
  raise NoConfig, "no output git config, edit #{Oxidized::Config.configfile}"
27
27
  end
28
28
 
29
29
  if @cfg.repo.respond_to?(:each)
30
30
  @cfg.repo.each do |group, repo|
31
- @cfg.repo["#{group}="] = File.expand_path repo
31
+ @cfg.repo["#{group}="] = ::File.expand_path repo
32
32
  end
33
33
  else
34
- @cfg.repo = File.expand_path @cfg.repo
34
+ @cfg.repo = ::File.expand_path @cfg.repo
35
35
  end
36
36
  end
37
37
 
@@ -45,7 +45,7 @@ module Oxidized
45
45
 
46
46
  outputs.types.each do |type|
47
47
  type_cfg = ''
48
- type_repo = File.join(File.dirname(repo), type + '.git')
48
+ type_repo = ::File.join(::File.dirname(repo), type + '.git')
49
49
  outputs.type(type).each do |output|
50
50
  (type_cfg << output; next) unless output.name # rubocop:disable Style/Semicolon
51
51
  type_file = file + '--' + output.name
@@ -200,10 +200,66 @@ module Oxidized
200
200
  @gitcache = nil
201
201
  end
202
202
 
203
+ def self.clean_obsolete_nodes(active_nodes)
204
+ git_config = Oxidized.config.output.git
205
+ repo_path = git_config.repo
206
+
207
+ unless git_config.single_repo?
208
+ logger.warn "clean_obsolete_nodes is not implemented for " \
209
+ "multiple git repositories"
210
+ return
211
+ end
212
+
213
+ if git_config.type_as_directory?
214
+ logger.warn "clean_obsolete_nodes is not implemented for output " \
215
+ "types as a directory within the git repository"
216
+ return
217
+ end
218
+
219
+ # The repo might not exist on the first run
220
+ return unless ::File.directory?(repo_path)
221
+
222
+ repo = Rugged::Repository.new repo_path
223
+ return if repo.empty?
224
+
225
+ keep_files = active_nodes.map do |n|
226
+ n.group ? ::File.join(n.group, n.name) : n.name
227
+ end
228
+
229
+ tree = repo.last_commit.tree
230
+ files_to_delete = []
231
+
232
+ tree.walk_blobs do |root, entry|
233
+ file_path = root.empty? ? entry[:name] : ::File.join(root, entry[:name])
234
+ files_to_delete << file_path unless keep_files.include?(file_path)
235
+ end
236
+
237
+ return if files_to_delete.empty?
238
+
239
+ logger.info "clean_obsolete_nodes: removing " \
240
+ "#{files_to_delete.size} obsolete configs"
241
+ index = repo.index
242
+
243
+ files_to_delete.each { |file_path| index.remove(file_path) }
244
+
245
+ repo.config['user.name'] = git_config.user
246
+ repo.config['user.email'] = git_config.email
247
+ Rugged::Commit.create(
248
+ repo,
249
+ tree: index.write_tree(repo),
250
+ message: "Removing #{files_to_delete.size} obsolete configs",
251
+ parents: [repo.head.target].compact,
252
+ update_ref: 'HEAD'
253
+ )
254
+
255
+ index.write
256
+ end
257
+
203
258
  private
204
259
 
205
260
  def yield_repo_and_path(node, group)
206
- repo, path = node.repo, node.name
261
+ repo = node.repo
262
+ path = node.name
207
263
 
208
264
  path = "#{group}/#{node.name}" if group && !group.empty? && @cfg.single_repo?
209
265
 
@@ -215,10 +271,10 @@ module Oxidized
215
271
 
216
272
  if @opt[:group]
217
273
  if @cfg.single_repo?
218
- file = File.join @opt[:group], file
274
+ file = ::File.join @opt[:group], file
219
275
  else
220
276
  repo = if repo.is_a?(::String)
221
- File.join File.dirname(repo), @opt[:group] + '.git'
277
+ ::File.join ::File.dirname(repo), @opt[:group] + '.git'
222
278
  else
223
279
  repo[@opt[:group]]
224
280
  end
@@ -232,7 +288,8 @@ module Oxidized
232
288
  begin
233
289
  Rugged::Repository.init_at repo, :bare
234
290
  rescue StandardError => create_error
235
- raise GitError, "first '#{e.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo"
291
+ raise GitError, "first '#{e.message}' was raised while opening git repo, then '#{create_error.message}' " \
292
+ "was while trying to create git repo"
236
293
  end
237
294
  retry
238
295
  end
@@ -245,7 +302,7 @@ module Oxidized
245
302
  # The alternative would be to rebuild the index each time, which a little
246
303
  # time consuming. Caching the index in memory is difficult because a new
247
304
  # Output object is created each time #store is called.
248
- def update_repo(repo, file, data)
305
+ def update_repo(repo, file, data) # rubocop:disable Naming/PredicateMethod
249
306
  oid_old = repo.blob_at(repo.head.target_id, file) rescue nil
250
307
  return false if oid_old && (oid_old.content.b == data.b)
251
308
 
@@ -25,17 +25,17 @@ module Oxidized
25
25
  if @cfg.empty?
26
26
  Oxidized.asetus.user.output.gitcrypt.user = 'Oxidized'
27
27
  Oxidized.asetus.user.output.gitcrypt.email = 'o@example.com'
28
- Oxidized.asetus.user.output.gitcrypt.repo = File.join(Config::ROOT, 'oxidized.git')
28
+ Oxidized.asetus.user.output.gitcrypt.repo = ::File.join(Config::ROOT, 'oxidized.git')
29
29
  Oxidized.asetus.save :user
30
30
  raise NoConfig, "no output git config, edit #{Oxidized::Config.configfile}"
31
31
  end
32
32
 
33
33
  if @cfg.repo.respond_to?(:each)
34
34
  @cfg.repo.each do |group, repo|
35
- @cfg.repo["#{group}="] = File.expand_path repo
35
+ @cfg.repo["#{group}="] = ::File.expand_path repo
36
36
  end
37
37
  else
38
- @cfg.repo = File.expand_path @cfg.repo
38
+ @cfg.repo = ::File.expand_path @cfg.repo
39
39
  end
40
40
  end
41
41
 
@@ -45,7 +45,7 @@ module Oxidized
45
45
  @cfg.users.each do |user|
46
46
  system("#{@gitcrypt_adduser} #{user}")
47
47
  end
48
- File.write(".gitattributes", "* filter=git-crypt diff=git-crypt\n.gitattributes !filter !diff")
48
+ ::File.write(".gitattributes", "* filter=git-crypt diff=git-crypt\n.gitattributes !filter !diff")
49
49
  repo.add(".gitattributes")
50
50
  repo.commit("Initial commit: crypt all config files")
51
51
  end
@@ -73,7 +73,7 @@ module Oxidized
73
73
 
74
74
  outputs.types.each do |type|
75
75
  type_cfg = ''
76
- type_repo = File.join(File.dirname(repo), type + '.git')
76
+ type_repo = ::File.join(::File.dirname(repo), type + '.git')
77
77
  outputs.type(type).each do |output|
78
78
  (type_cfg << output; next) unless output.name # rubocop:disable Style/Semicolon
79
79
  type_file = file + '--' + output.name
@@ -95,9 +95,9 @@ module Oxidized
95
95
  unlock repo
96
96
  index = repo.index
97
97
  # Empty repo ?
98
- raise 'Empty git repo' if File.exist?(index.path)
98
+ raise 'Empty git repo' if ::File.exist?(index.path)
99
99
 
100
- File.read path
100
+ ::File.read path
101
101
  lock repo
102
102
  rescue StandardError
103
103
  'node not found'
@@ -176,7 +176,8 @@ module Oxidized
176
176
  private
177
177
 
178
178
  def yield_repo_and_path(node, group)
179
- repo, path = node.repo, node.name
179
+ repo = node.repo
180
+ path = node.name
180
181
 
181
182
  path = "#{group}/#{node.name}" if group && @cfg.single_repo?
182
183
 
@@ -188,10 +189,10 @@ module Oxidized
188
189
 
189
190
  if @opt[:group]
190
191
  if @cfg.single_repo?
191
- file = File.join @opt[:group], file
192
+ file = ::File.join @opt[:group], file
192
193
  else
193
194
  repo = if repo.is_a?(::String)
194
- File.join File.dirname(repo), @opt[:group] + '.git'
195
+ ::File.join ::File.dirname(repo), @opt[:group] + '.git'
195
196
  else
196
197
  repo[@opt[:group]]
197
198
  end
@@ -201,12 +202,13 @@ module Oxidized
201
202
  begin
202
203
  update_repo repo, file, data, @msg, @user, @email
203
204
  rescue Git::GitExecuteError, ArgumentError => e
204
- Oxidized.logger.debug "open_error #{e} #{file}"
205
+ logger.debug "open_error #{e} #{file}"
205
206
  begin
206
207
  grepo = Git.init repo
207
208
  crypt_init grepo
208
209
  rescue StandardError => create_error
209
- raise GitCryptError, "first '#{e.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo"
210
+ raise GitCryptError, "first '#{e.message}' was raised while opening git repo, then " \
211
+ "'#{create_error.message}' was while trying to create git repo"
210
212
  end
211
213
  retry
212
214
  end
@@ -218,7 +220,7 @@ module Oxidized
218
220
  grepo.config('user.email', email)
219
221
  grepo.chdir do
220
222
  unlock grepo
221
- File.write(file, data)
223
+ ::File.write(file, data)
222
224
  grepo.add(file)
223
225
  if grepo.status[file].nil? || !grepo.status[file].type.nil?
224
226
  grepo.commit(msg)
@@ -34,14 +34,14 @@ module Oxidized
34
34
 
35
35
  case response.code.to_i
36
36
  when 200 || 201
37
- Oxidized.logger.info "Configuration http backup complete for #{node}"
37
+ logger.info "Configuration http backup complete for #{node}"
38
38
  p [:success]
39
39
  when (400..499)
40
- Oxidized.logger.info "Configuration http backup for #{node} failed status: #{response.body}"
40
+ logger.info "Configuration http backup for #{node} failed status: #{response.body}"
41
41
  p [:bad_request]
42
42
  when (500..599)
43
43
  p [:server_problems]
44
- Oxidized.logger.info "Configuration http backup for #{node} failed status: #{response.body}"
44
+ logger.info "Configuration http backup for #{node} failed status: #{response.body}"
45
45
  end
46
46
  end
47
47
 
@@ -55,7 +55,8 @@ module Oxidized
55
55
  'group' => opt[:group],
56
56
  'node' => node,
57
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.
58
+ # actually we need to also iterate outputs, for other types like in gitlab.
59
+ # But most people don't use 'type' functionality.
59
60
  )
60
61
  end
61
62
  end
@@ -1,11 +1,25 @@
1
1
  module Oxidized
2
2
  module Output
3
+ def self.clean_obsolete_nodes(active_nodes)
4
+ return unless Oxidized.config.output.clean_obsolete_nodes?
5
+
6
+ output_name = Oxidized.config.output.default
7
+ output = Oxidized.mgr.add_output output_name
8
+ output[output_name].clean_obsolete_nodes(active_nodes)
9
+ end
10
+
3
11
  class Output
12
+ include SemanticLogger::Loggable
13
+
4
14
  class NoConfig < OxidizedError; end
5
15
 
6
16
  def cfg_to_str(cfg)
7
17
  cfg.select { |h| h[:type] == 'cfg' }.map { |h| h[:data] }.join
8
18
  end
19
+
20
+ def self.clean_obsolete_nodes(_active_nodes)
21
+ logger.warn "clean_obsolete_nodes is not implemented for #{name}"
22
+ end
9
23
  end
10
24
  end
11
25
  end
@@ -8,7 +8,6 @@ module Oxidized
8
8
  end
9
9
 
10
10
  def setup
11
- Oxidized.setup_logger
12
11
  if @cfg.empty?
13
12
  Oxidized.asetus.user.source.http.url = 'https://url/api'
14
13
  Oxidized.asetus.user.source.http.map.name = 'name'
@@ -45,7 +44,10 @@ module Oxidized
45
44
 
46
45
  def pagination(data, node_want)
47
46
  node_data = []
48
- raise Oxidized::OxidizedError, "if using pagination, 'pagination_key_name' setting must be set" unless @cfg.pagination_key_name?
47
+ unless @cfg.pagination_key_name?
48
+ raise Oxidized::OxidizedError,
49
+ "if using pagination, 'pagination_key_name' setting must be set"
50
+ end
49
51
 
50
52
  next_key = @cfg.pagination_key_name
51
53
  loop do
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Oxidized
4
- VERSION = '0.33.0'
5
- VERSION_FULL = '0.33.0'
4
+ VERSION = '0.34.0'
5
+ VERSION_FULL = '0.34.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 ""
@@ -2,6 +2,8 @@ module Oxidized
2
2
  require 'oxidized/job'
3
3
  require 'oxidized/jobs'
4
4
  class Worker
5
+ include SemanticLogger::Loggable
6
+
5
7
  def initialize(nodes)
6
8
  @jobs_done = 0
7
9
  @nodes = nodes
@@ -17,7 +19,8 @@ module Oxidized
17
19
  @jobs.work
18
20
 
19
21
  while @jobs.size < @jobs.want
20
- Oxidized.logger.debug "lib/oxidized/worker.rb: Jobs running: #{@jobs.size} of #{@jobs.want} - ended: #{@jobs_done} of #{@nodes.size}"
22
+ logger.debug "Jobs running: #{@jobs.size} of #{@jobs.want} - ended: " \
23
+ "#{@jobs_done} of #{@nodes.size}"
21
24
  # ask for next node in queue non destructive way
22
25
  nextnode = @nodes.first
23
26
  unless nextnode.last.nil?
@@ -30,14 +33,14 @@ module Oxidized
30
33
  node.running? ? next : node.running = true
31
34
 
32
35
  @jobs.push Job.new node
33
- Oxidized.logger.debug "lib/oxidized/worker.rb: Added #{node.group}/#{node.name} to the job queue"
36
+ logger.debug "Added #{node.group}/#{node.name} to the job queue"
34
37
  end
35
38
 
36
39
  if cycle_finished?
37
40
  run_done_hook
38
41
  exit 0 if Oxidized.config.run_once
39
42
  end
40
- Oxidized.logger.debug("lib/oxidized/worker.rb: #{@jobs.size} jobs running in parallel") unless @jobs.empty?
43
+ logger.debug("#{@jobs.size} jobs running in parallel") unless @jobs.empty?
41
44
  end
42
45
 
43
46
  def process(job)
@@ -52,7 +55,7 @@ module Oxidized
52
55
  process_failure node, job
53
56
  end
54
57
  rescue NodeNotFound
55
- Oxidized.logger.warn "#{node.group}/#{node.name} not found, removed while collecting?"
58
+ logger.warn "#{node.group}/#{node.name} not found, removed while collecting?"
56
59
  end
57
60
 
58
61
  def reload
@@ -72,7 +75,7 @@ module Oxidized
72
75
  if output.store node.name, job.config,
73
76
  msg: msg, email: node.email, user: node.user, group: node.group
74
77
  node.modified
75
- Oxidized.logger.info "Configuration updated for #{node.group}/#{node.name}"
78
+ logger.info "Configuration updated for #{node.group}/#{node.name}"
76
79
  Oxidized.hooks.handle :post_store, node: node,
77
80
  job: job,
78
81
  commitref: output.commitref
@@ -97,7 +100,7 @@ module Oxidized
97
100
  Oxidized.hooks.handle :node_fail, node: node,
98
101
  job: job
99
102
  end
100
- Oxidized.logger.warn msg
103
+ logger.warn msg
101
104
  end
102
105
 
103
106
  def cycle_finished?
@@ -106,11 +109,11 @@ module Oxidized
106
109
  end
107
110
 
108
111
  def run_done_hook
109
- Oxidized.logger.debug "lib/oxidized/worker.rb: Running :nodes_done hook"
112
+ logger.debug "Running :nodes_done hook"
110
113
  Oxidized.hooks.handle :nodes_done
111
114
  rescue StandardError => e
112
115
  # swallow the hook erros and continue as normal
113
- Oxidized.logger.error "lib/oxidized/worker.rb: #{e.message}"
116
+ logger.error e.message
114
117
  ensure
115
118
  @jobs_done = 0
116
119
  end