oxidized 0.28.0 → 0.29.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 (140) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/publishdocker.yml +8 -1
  3. data/.github/workflows/ruby.yml +42 -0
  4. data/.rubocop.yml +30 -10
  5. data/.rubocop_todo.yml +95 -41
  6. data/CHANGELOG.md +139 -2
  7. data/Dockerfile +13 -9
  8. data/README.md +66 -32
  9. data/Rakefile +2 -0
  10. data/docs/Configuration.md +49 -7
  11. data/docs/Creating-Models.md +10 -4
  12. data/docs/Hooks.md +35 -6
  13. data/docs/Model-Notes/ADVA.md +12 -0
  14. data/docs/Model-Notes/Cumulus.md +7 -1
  15. data/docs/Model-Notes/IOS.md +36 -0
  16. data/docs/Model-Notes/JunOS.md +3 -3
  17. data/docs/Model-Notes/LenovoNOS.md +29 -0
  18. data/docs/Model-Notes/LinksysSRW.md +15 -0
  19. data/docs/Model-Notes/Nokia.md +3 -0
  20. data/docs/Model-Notes/OS10.md +33 -0
  21. data/docs/Model-Notes/PanOS_API.md +28 -0
  22. data/docs/Model-Notes/README.md +2 -0
  23. data/docs/Sources.md +18 -0
  24. data/docs/Supported-OS-Types.md +51 -6
  25. data/docs/Troubleshooting.md +1 -1
  26. data/extra/gitdiff-msteams.sh +91 -0
  27. data/extra/nagios_check_failing_nodes.rb +6 -9
  28. data/extra/oxidized-report-git-commits +71 -14
  29. data/extra/oxidized.init +2 -5
  30. data/extra/oxidized.logrotate +1 -0
  31. data/extra/oxidized.runit +4 -1
  32. data/extra/oxidized.service +5 -8
  33. data/extra/rest_client.rb +1 -1
  34. data/extra/syslog.rb +2 -2
  35. data/lib/oxidized/cli.rb +1 -1
  36. data/lib/oxidized/config/vars.rb +5 -2
  37. data/lib/oxidized/config.rb +6 -3
  38. data/lib/oxidized/core.rb +1 -1
  39. data/lib/oxidized/hook/exec.rb +6 -6
  40. data/lib/oxidized/hook/githubrepo.rb +42 -11
  41. data/lib/oxidized/hook/slackdiff.rb +2 -2
  42. data/lib/oxidized/hook/xmppdiff.rb +45 -25
  43. data/lib/oxidized/hook.rb +4 -8
  44. data/lib/oxidized/input/exec.rb +1 -1
  45. data/lib/oxidized/input/input.rb +1 -0
  46. data/lib/oxidized/input/ssh.rb +23 -20
  47. data/lib/oxidized/input/telnet.rb +52 -44
  48. data/lib/oxidized/job.rb +1 -0
  49. data/lib/oxidized/jobs.rb +11 -6
  50. data/lib/oxidized/manager.rb +1 -0
  51. data/lib/oxidized/model/acmepacket.rb +38 -0
  52. data/lib/oxidized/model/adtran.rb +5 -3
  53. data/lib/oxidized/model/adva.rb +66 -0
  54. data/lib/oxidized/model/airfiber.rb +1 -1
  55. data/lib/oxidized/model/aoscx.rb +96 -0
  56. data/lib/oxidized/model/aosw.rb +1 -1
  57. data/lib/oxidized/model/asa.rb +2 -0
  58. data/lib/oxidized/model/awplus.rb +1 -1
  59. data/lib/oxidized/model/bdcom.rb +49 -0
  60. data/lib/oxidized/model/cambiumepmp.rb +17 -0
  61. data/lib/oxidized/model/casa.rb +4 -1
  62. data/lib/oxidized/model/ciscoce.rb +12 -0
  63. data/lib/oxidized/model/ciscosmb.rb +2 -0
  64. data/lib/oxidized/model/comware.rb +16 -1
  65. data/lib/oxidized/model/cumulus.rb +58 -44
  66. data/lib/oxidized/model/dellx.rb +1 -3
  67. data/lib/oxidized/model/dlink.rb +2 -1
  68. data/lib/oxidized/model/edgecos.rb +22 -2
  69. data/lib/oxidized/model/edgeswitch.rb +4 -4
  70. data/lib/oxidized/model/eltex.rb +48 -0
  71. data/lib/oxidized/model/enterasys.rb +18 -3
  72. data/lib/oxidized/model/enterasys800.rb +29 -0
  73. data/lib/oxidized/model/eos.rb +2 -1
  74. data/lib/oxidized/model/fabricos.rb +1 -1
  75. data/lib/oxidized/model/fastiron.rb +3 -2
  76. data/lib/oxidized/model/fortios.rb +24 -11
  77. data/lib/oxidized/model/fortiwlc.rb +24 -0
  78. data/lib/oxidized/model/gaiaos.rb +40 -3
  79. data/lib/oxidized/model/h3c.rb +40 -0
  80. data/lib/oxidized/model/hatteras.rb +2 -2
  81. data/lib/oxidized/model/hios.rb +38 -0
  82. data/lib/oxidized/model/hpebladesystem.rb +1 -1
  83. data/lib/oxidized/model/ios.rb +13 -10
  84. data/lib/oxidized/model/iosxe.rb +1 -1
  85. data/lib/oxidized/model/ironware.rb +8 -4
  86. data/lib/oxidized/model/junos.rb +5 -1
  87. data/lib/oxidized/model/lancom.rb +23 -0
  88. data/lib/oxidized/model/lenovonos.rb +82 -0
  89. data/lib/oxidized/model/linksyssrw.rb +71 -0
  90. data/lib/oxidized/model/mlnxos.rb +2 -0
  91. data/lib/oxidized/model/model.rb +29 -3
  92. data/lib/oxidized/model/necix.rb +30 -0
  93. data/lib/oxidized/model/netgear.rb +5 -2
  94. data/lib/oxidized/model/netscaler.rb +38 -1
  95. data/lib/oxidized/model/nodegrid.rb +23 -0
  96. data/lib/oxidized/model/nxos.rb +3 -2
  97. data/lib/oxidized/model/openbsd.rb +9 -0
  98. data/lib/oxidized/model/opengear.rb +1 -1
  99. data/lib/oxidized/model/opnsense.rb +12 -4
  100. data/lib/oxidized/model/panos_api.rb +71 -0
  101. data/lib/oxidized/model/pfsense.rb +12 -7
  102. data/lib/oxidized/model/powerconnect.rb +1 -3
  103. data/lib/oxidized/model/procurve.rb +2 -2
  104. data/lib/oxidized/model/purityos.rb +8 -1
  105. data/lib/oxidized/model/quantaos.rb +1 -5
  106. data/lib/oxidized/model/routeros.rb +15 -2
  107. data/lib/oxidized/model/slxos.rb +1 -0
  108. data/lib/oxidized/model/smartcs.rb +40 -0
  109. data/lib/oxidized/model/sonicos.rb +9 -1
  110. data/lib/oxidized/model/srosmd.rb +97 -0
  111. data/lib/oxidized/model/stoneos.rb +6 -2
  112. data/lib/oxidized/model/supermicro.rb +1 -1
  113. data/lib/oxidized/model/swos.rb +9 -0
  114. data/lib/oxidized/model/timos.rb +1 -1
  115. data/lib/oxidized/model/tmos.rb +2 -1
  116. data/lib/oxidized/model/tplink.rb +2 -0
  117. data/lib/oxidized/model/trango.rb +11 -11
  118. data/lib/oxidized/model/truenas.rb +20 -0
  119. data/lib/oxidized/model/vrp.rb +1 -1
  120. data/lib/oxidized/model/xos.rb +4 -3
  121. data/lib/oxidized/model/yamaha.rb +57 -0
  122. data/lib/oxidized/model/zteolt.rb +52 -0
  123. data/lib/oxidized/model/zy1308.rb +11 -0
  124. data/lib/oxidized/node/stats.rb +1 -0
  125. data/lib/oxidized/node.rb +16 -11
  126. data/lib/oxidized/nodes.rb +7 -6
  127. data/lib/oxidized/output/file.rb +2 -1
  128. data/lib/oxidized/output/git.rb +4 -3
  129. data/lib/oxidized/output/gitcrypt.rb +5 -8
  130. data/lib/oxidized/output/http.rb +2 -0
  131. data/lib/oxidized/source/csv.rb +1 -0
  132. data/lib/oxidized/source/http.rb +4 -0
  133. data/lib/oxidized/source/source.rb +7 -2
  134. data/lib/oxidized/source/sql.rb +15 -5
  135. data/lib/oxidized/string.rb +9 -3
  136. data/lib/oxidized/version.rb +2 -2
  137. data/lib/oxidized/worker.rb +5 -5
  138. data/oxidized.gemspec +22 -16
  139. metadata +116 -29
  140. data/.travis.yml +0 -10
@@ -0,0 +1,20 @@
1
+ class TrueNAS < Oxidized::Model
2
+ comment '# '
3
+
4
+ cmd('uname -a') { |cfg| comment cfg }
5
+ cmd('cat /etc/version') { |cfg| comment cfg }
6
+ cmd('sqlite3 "file:///data/freenas-v1.db?mode=ro&immutable=1" .dump') do |cfg|
7
+ cfg.lines.reject do |line|
8
+ line.match(/^INSERT INTO storage_replication /) ||
9
+ line.match(/^INSERT INTO system_alert /)
10
+ end.join
11
+ end
12
+
13
+ cfg :ssh do
14
+ exec true # don't run shell, run each command in exec channel
15
+ end
16
+
17
+ cfg :ssh do
18
+ pre_logout 'exit'
19
+ end
20
+ end
@@ -1,7 +1,7 @@
1
1
  class VRP < Oxidized::Model
2
2
  # Huawei VRP
3
3
 
4
- prompt /^(<[\w.-]+>)$/
4
+ prompt /^.*(<[\w.-]+>)$/
5
5
  comment '# '
6
6
 
7
7
  cmd :secret do |cfg|
@@ -1,7 +1,7 @@
1
1
  class XOS < Oxidized::Model
2
2
  # Extreme Networks XOS
3
3
 
4
- prompt /^\*?\s?[-\w.~]+(:\d+)? [#>] $/
4
+ prompt /^\s?\*?\s?[-\w]+\s?[-\w.~]+(:\d+)? [#>] $/
5
5
  comment '# '
6
6
 
7
7
  cmd :all do |cfg|
@@ -23,7 +23,8 @@ class XOS < Oxidized::Model
23
23
  end
24
24
 
25
25
  cmd 'show switch' do |cfg|
26
- comment cfg.each_line.reject { |line| line.match(/Time:/) || line.match(/boot/i) }.join
26
+ cfg.gsub! /Next periodic save on.*/, ''
27
+ comment cfg.each_line.reject { |line| line.match(/Time:/) || line.match(/boot/i) || line.match(/Next periodic/) }.join
27
28
  end
28
29
 
29
30
  cmd 'show configuration' do |cfg|
@@ -43,7 +44,7 @@ class XOS < Oxidized::Model
43
44
  cfg :telnet, :ssh do
44
45
  post_login do
45
46
  data = cmd 'disable clipaging session'
46
- match = data.match /^disable clipaging session\n\*?[\w .-]+(:\d+)? [#>] $/m
47
+ match = data.match /^disable clipaging session\n\r?\*?\s?[-\w]+\s?[-\w.~]+(:\d+)? [#>] $/m
47
48
  next if match
48
49
 
49
50
  cmd 'disable clipaging'
@@ -0,0 +1,57 @@
1
+ class Yamaha < Oxidized::Model
2
+ prompt /^([\w.@()-]+[#>]\s?)$/
3
+ comment '# '
4
+
5
+ expect /^---more---$/ do |data, re|
6
+ send ' '
7
+ data.sub re, ''
8
+ end
9
+
10
+ # non-preferred way to handle additional PW prompt
11
+ # expect /^[\w.]+>$/ do |data|
12
+ # send "enable\n"
13
+ # send vars(:enable) + "\n"
14
+ # data
15
+ # end
16
+
17
+ expect /^Save new configuration/ do |data, re|
18
+ send "N\n"
19
+ data.sub re, ''
20
+ end
21
+
22
+ cmd :all do |cfg|
23
+ # cfg.gsub! /\cH+\s{8}/, '' # example how to handle pager
24
+ # cfg.gsub! /\cH+/, '' # example how to handle pager
25
+ # get rid of errors for commands that don't work on some devices
26
+ cfg.gsub! /^Error: Invalid command name$|^\s+\^$/, ''
27
+ cfg.cut_both
28
+ end
29
+
30
+ cmd 'show config' do |cfg|
31
+ cfg.gsub! /^(# Reporting Date:\s+)(.*)$/, '\1<stripped>'
32
+ cfg
33
+ end
34
+
35
+ cfg :telnet do
36
+ password /^Password:/i
37
+ end
38
+
39
+ cfg :telnet, :ssh do
40
+ # preferred way to handle additional passwords
41
+ post_login 'console lines infinity'
42
+ post_login 'console columns 200'
43
+ post_login 'console character ascii'
44
+ post_login do
45
+ if vars(:enable) == true
46
+ cmd "administrator"
47
+ elsif vars(:enable)
48
+ cmd "administrator", /^[pP]assword:/
49
+ cmd vars(:enable)
50
+ end
51
+ end
52
+ pre_logout do
53
+ cmd 'exit'
54
+ end
55
+ pre_logout 'exit'
56
+ end
57
+ end
@@ -0,0 +1,52 @@
1
+ class ZTEOLT < Oxidized::Model
2
+ # Tested with C320 and C300 olt, firware 1.2.5P3 and 2.1.0
3
+
4
+ prompt /^([\w.@()-]+[#>]\s?)$/
5
+ comment '! '
6
+
7
+ cmd :all do |cfg|
8
+ cfg.gsub! /^% Invalid input detected at '\^' marker\.$|^\s+\^$/, ''
9
+ cfg.cut_both
10
+ end
11
+
12
+ cmd :secret do |cfg|
13
+ cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
14
+ cfg.gsub! /^(tacacs-server (.+ )?key) .+/, '\\1 <secret hidden>'
15
+ cfg.gsub! /^username (\S+) privilege (\d+) (\S+).*/, '<secret hidden>'
16
+ cfg.gsub! /^(enable (password|secret)( level \d+)? \d) .+/, '\\1 <secret hidden>'
17
+ cfg
18
+ end
19
+
20
+ cmd 'show version-running' do |cfg|
21
+ comment cfg
22
+ end
23
+
24
+ cmd 'show patch-running' do |cfg|
25
+ comment cfg
26
+ end
27
+
28
+ cmd 'show running-config' do |cfg|
29
+ cfg.gsub! /^timestamp_write: .*\n/, ''
30
+ cfg
31
+ end
32
+
33
+ cfg :telnet do
34
+ username /^Username:/i
35
+ password /^Password:/i
36
+ end
37
+
38
+ cfg :telnet, :ssh do
39
+ # preferred way to handle additional passwords
40
+ post_login do
41
+ if vars(:enable) == true
42
+ cmd "enable"
43
+ elsif vars(:enable)
44
+ cmd "enable", /^[pP]assword:/
45
+ cmd vars(:enable)
46
+ end
47
+ end
48
+ post_login 'terminal length 0'
49
+ pre_logout 'disable'
50
+ pre_logout 'exit'
51
+ end
52
+ end
@@ -0,0 +1,11 @@
1
+ # For Zyxel OLTs series 1308
2
+ class Zy1308 < Oxidized::Model
3
+ # For Zyxel OLTs series 1308
4
+
5
+ cmd '/config_OLT-1308S-22.log'
6
+ cfg :http do
7
+ @username = @node.auth[:username]
8
+ @password = @node.auth[:password]
9
+ @secure = false
10
+ end
11
+ end
@@ -2,6 +2,7 @@ module Oxidized
2
2
  class Node
3
3
  class Stats
4
4
  attr_reader :mtimes
5
+
5
6
  MAX_STAT = 10
6
7
 
7
8
  # @param [Job] job job whose information add to stats
data/lib/oxidized/node.rb CHANGED
@@ -4,9 +4,10 @@ module Oxidized
4
4
  require_relative 'node/stats'
5
5
  class MethodNotFound < OxidizedError; end
6
6
  class ModelNotFound < OxidizedError; end
7
+
7
8
  class Node
8
9
  attr_reader :name, :ip, :model, :input, :output, :group, :auth, :prompt, :vars, :last, :repo
9
- attr_accessor :running, :user, :email, :msg, :from, :stats, :retry
10
+ attr_accessor :running, :user, :email, :msg, :from, :stats, :retry, :err_type, :err_reason
10
11
  alias running? running
11
12
 
12
13
  def initialize(opt)
@@ -28,6 +29,8 @@ module Oxidized
28
29
  @stats = Stats.new
29
30
  @retry = 0
30
31
  @repo = resolve_repo opt
32
+ @err_type = nil
33
+ @err_reason = nil
31
34
 
32
35
  # model instance needs to access node instance
33
36
  @model.node = self
@@ -73,6 +76,8 @@ module Oxidized
73
76
  resc = " (rescued #{resc})"
74
77
  end
75
78
  Oxidized.logger.send(level, '%s raised %s%s with msg "%s"' % [ip, err.class, resc, err.message])
79
+ @err_type = err.class.to_s
80
+ @err_reason = err.message.to_s
76
81
  false
77
82
  rescue StandardError => err
78
83
  crashdir = Oxidized.config.crash.directory
@@ -86,6 +91,8 @@ module Oxidized
86
91
  fh.puts err.backtrace
87
92
  end
88
93
  Oxidized.logger.error '%s raised %s with msg "%s", %s saved' % [ip, err.class, err.message, crashfile]
94
+ @err_type = err.class.to_s
95
+ @err_reason = err.message.to_s
89
96
  false
90
97
  end
91
98
  end
@@ -153,6 +160,7 @@ module Oxidized
153
160
  inputs = resolve_key :input, opt, Oxidized.config.input.default
154
161
  inputs.split(/\s*,\s*/).map do |input|
155
162
  Oxidized.mgr.add_input(input) || raise(MethodNotFound, "#{input} not found for node #{ip}") unless Oxidized.mgr.input[input]
163
+
156
164
  Oxidized.mgr.input[input]
157
165
  end
158
166
  end
@@ -160,6 +168,7 @@ module Oxidized
160
168
  def resolve_output(opt)
161
169
  output = resolve_key :output, opt, Oxidized.config.output.default
162
170
  Oxidized.mgr.add_output(output) || raise(MethodNotFound, "#{output} not found for node #{ip}") unless Oxidized.mgr.output[output]
171
+
163
172
  Oxidized.mgr.output[output]
164
173
  end
165
174
 
@@ -202,19 +211,15 @@ module Oxidized
202
211
  end
203
212
 
204
213
  # group
205
- if Oxidized.config.groups.has_key?(@group)
206
- if Oxidized.config.groups[@group].has_key?(key_str)
207
- value = Oxidized.config.groups[@group][key_str]
208
- Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from group"
209
- end
214
+ if Oxidized.config.groups.has_key?(@group) && Oxidized.config.groups[@group].has_key?(key_str)
215
+ value = Oxidized.config.groups[@group][key_str]
216
+ Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from group"
210
217
  end
211
218
 
212
219
  # model
213
- if Oxidized.config.models.has_key?(@model.class.name.to_s.downcase)
214
- if Oxidized.config.models[@model.class.name.to_s.downcase].has_key?(key_str)
215
- value = Oxidized.config.models[@model.class.name.to_s.downcase][key_str]
216
- Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from model"
217
- end
220
+ if Oxidized.config.models.has_key?(@model.class.name.to_s.downcase) && Oxidized.config.models[@model.class.name.to_s.downcase].has_key?(key_str)
221
+ value = Oxidized.config.models[@model.class.name.to_s.downcase][key_str]
222
+ Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from model"
218
223
  end
219
224
 
220
225
  # node
@@ -3,6 +3,7 @@ module Oxidized
3
3
  require 'oxidized/node'
4
4
  class Oxidized::NotSupported < OxidizedError; end
5
5
  class Oxidized::NodeNotFound < OxidizedError; end
6
+
6
7
  class Nodes < Array
7
8
  attr_accessor :source, :jobs
8
9
  alias put unshift
@@ -36,6 +37,7 @@ module Oxidized
36
37
 
37
38
  node_want_ip = (IPAddr.new(node_want) rescue false)
38
39
  name_is_ip = (IPAddr.new(node[:name]) rescue false)
40
+ # rubocop:todo Lint/DuplicateBranch
39
41
  if name_is_ip && (node_want_ip == node[:name])
40
42
  true
41
43
  elsif node[:ip] && (node_want_ip == node[:ip])
@@ -43,6 +45,7 @@ module Oxidized
43
45
  elsif node_want.match node[:name]
44
46
  true unless name_is_ip
45
47
  end
48
+ # rubocop:enable Lint/DuplicateBranch
46
49
  end
47
50
 
48
51
  def list
@@ -159,13 +162,11 @@ module Oxidized
159
162
  old = dup
160
163
  replace(nodes)
161
164
  each do |node|
162
- begin
163
- if (i = old.find_node_index(node.name))
164
- node.stats = old[i].stats
165
- node.last = old[i].last
166
- end
167
- rescue Oxidized::NodeNotFound
165
+ if (i = old.find_node_index(node.name))
166
+ node.stats = old[i].stats
167
+ node.last = old[i].last
168
168
  end
169
+ rescue Oxidized::NodeNotFound
169
170
  end
170
171
  sort_by! { |x| x.last.nil? ? Time.new(0) : x.last.end }
171
172
  end
@@ -5,6 +5,7 @@ module Oxidized
5
5
  attr_reader :commitref
6
6
 
7
7
  def initialize
8
+ super
8
9
  @cfg = Oxidized.config.output.file
9
10
  end
10
11
 
@@ -21,7 +22,7 @@ module Oxidized
21
22
  file = File.join File.dirname(file), opt[:group] if opt[:group]
22
23
  FileUtils.mkdir_p file
23
24
  file = File.join file, node
24
- File.open(file, 'w') { |fh| fh.write outputs.to_cfg }
25
+ File.write(file, outputs.to_cfg)
25
26
  @commitref = file
26
27
  end
27
28
 
@@ -10,6 +10,7 @@ module Oxidized
10
10
  attr_reader :commitref
11
11
 
12
12
  def initialize
13
+ super
13
14
  @cfg = Oxidized.config.output.git
14
15
  end
15
16
 
@@ -78,7 +79,7 @@ module Oxidized
78
79
  i = -1
79
80
  tab = []
80
81
  walker.each do |commit|
81
- next if commit.diff(paths: [path]).size.zero?
82
+ next if commit.diff(paths: [path]).empty?
82
83
 
83
84
  hash = {}
84
85
  hash[:date] = commit.time.to_s
@@ -158,11 +159,11 @@ module Oxidized
158
159
  begin
159
160
  repo = Rugged::Repository.new repo
160
161
  update_repo repo, file, data
161
- rescue Rugged::OSError, Rugged::RepositoryError => open_error
162
+ rescue Rugged::OSError, Rugged::RepositoryError => e
162
163
  begin
163
164
  Rugged::Repository.init_at repo, :bare
164
165
  rescue StandardError => create_error
165
- raise GitError, "first '#{open_error.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo"
166
+ raise GitError, "first '#{e.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo"
166
167
  end
167
168
  retry
168
169
  end
@@ -10,6 +10,7 @@ module Oxidized
10
10
  attr_reader :commitref
11
11
 
12
12
  def initialize
13
+ super
13
14
  @cfg = Oxidized.config.output.gitcrypt
14
15
  @gitcrypt_cmd = "/usr/bin/git-crypt"
15
16
  @gitcrypt_init = @gitcrypt_cmd + " init"
@@ -194,13 +195,13 @@ module Oxidized
194
195
 
195
196
  begin
196
197
  update_repo repo, file, data, @msg, @user, @email
197
- rescue Git::GitExecuteError, ArgumentError => open_error
198
- Oxidized.logger.debug "open_error #{open_error} #{file}"
198
+ rescue Git::GitExecuteError, ArgumentError => e
199
+ Oxidized.logger.debug "open_error #{e} #{file}"
199
200
  begin
200
201
  grepo = Git.init repo
201
202
  crypt_init grepo
202
203
  rescue StandardError => create_error
203
- raise GitCryptError, "first '#{open_error.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo"
204
+ raise GitCryptError, "first '#{e.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo"
204
205
  end
205
206
  retry
206
207
  end
@@ -214,11 +215,7 @@ module Oxidized
214
215
  unlock grepo
215
216
  File.write(file, data)
216
217
  grepo.add(file)
217
- if grepo.status[file].nil?
218
- grepo.commit(msg)
219
- @commitref = grepo.log(1).first.objectish
220
- true
221
- elsif !grepo.status[file].type.nil?
218
+ if grepo.status[file].nil? || !grepo.status[file].type.nil?
222
219
  grepo.commit(msg)
223
220
  @commitref = grepo.log(1).first.objectish
224
221
  true
@@ -1,7 +1,9 @@
1
1
  module Oxidized
2
2
  class Http < Output
3
3
  attr_reader :commitref
4
+
4
5
  def initialize
6
+ super
5
7
  @cfg = Oxidized.config.output.http
6
8
  end
7
9
 
@@ -32,6 +32,7 @@ module Oxidized
32
32
  keys[key.to_sym] = node_var_interpolate data[position]
33
33
  end
34
34
  keys[:model] = map_model keys[:model] if keys.has_key? :model
35
+ keys[:group] = map_group keys[:group] if keys.has_key? :group
35
36
 
36
37
  # map node specific vars
37
38
  vars = {}
@@ -29,6 +29,7 @@ module Oxidized
29
29
  keys[key.to_sym] = node_var_interpolate string_navigate(node, want_position)
30
30
  end
31
31
  keys[:model] = map_model keys[:model] if keys.has_key? :model
32
+ keys[:group] = map_group keys[:group] if keys.has_key? :group
32
33
 
33
34
  # map node specific vars
34
35
  vars = {}
@@ -61,6 +62,9 @@ module Oxidized
61
62
  http.use_ssl = true if uri.scheme == 'https'
62
63
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @cfg.secure
63
64
 
65
+ # Add read_timeout to handle case of big list of nodes (default value is 60 seconds)
66
+ http.read_timeout = Integer(@cfg.read_timeout) if @cfg.has_key? "read_timeout"
67
+
64
68
  # map headers
65
69
  headers = {}
66
70
  @cfg.headers.each do |header, value|
@@ -3,11 +3,16 @@ module Oxidized
3
3
  class NoConfig < OxidizedError; end
4
4
 
5
5
  def initialize
6
- @map = (Oxidized.config.model_map || {})
6
+ @model_map = (Oxidized.config.model_map || {})
7
+ @group_map = (Oxidized.config.group_map || {})
7
8
  end
8
9
 
9
10
  def map_model(model)
10
- @map.has_key?(model) ? @map[model] : model
11
+ @model_map.has_key?(model) ? @model_map[model] : model
12
+ end
13
+
14
+ def map_group(group)
15
+ @group_map.has_key?(group) ? @group_map[group] : group
11
16
  end
12
17
 
13
18
  def node_var_interpolate(var)
@@ -31,6 +31,7 @@ module Oxidized
31
31
  keys = {}
32
32
  @cfg.map.each { |key, sql_column| keys[key.to_sym] = node_var_interpolate node[sql_column.to_sym] }
33
33
  keys[:model] = map_model keys[:model] if keys.has_key? :model
34
+ keys[:group] = map_group keys[:group] if keys.has_key? :group
34
35
 
35
36
  # map node specific vars
36
37
  vars = {}
@@ -53,11 +54,20 @@ module Oxidized
53
54
  end
54
55
 
55
56
  def connect
56
- Sequel.connect(adapter: @cfg.adapter,
57
- host: @cfg.host?,
58
- user: @cfg.user?,
59
- password: @cfg.password?,
60
- database: @cfg.database)
57
+ options = {
58
+ adapter: @cfg.adapter,
59
+ host: @cfg.host?,
60
+ user: @cfg.user?,
61
+ password: @cfg.password?,
62
+ database: @cfg.database,
63
+ ssl_mode: @cfg.ssl_mode?
64
+ }
65
+ if @cfg.with_ssl?
66
+ options.merge!(sslca: @cfg.ssl_ca?,
67
+ sslcert: @cfg.ssl_cert?,
68
+ sslkey: @cfg.ssl_key?)
69
+ end
70
+ Sequel.connect(options)
61
71
  rescue Sequel::AdapterNotFound => error
62
72
  raise OxidizedError, "SQL adapter gem not installed: " + error.message
63
73
  end
@@ -5,17 +5,23 @@ module Oxidized
5
5
 
6
6
  # @return [Oxidized::String] copy of self with last line removed
7
7
  def cut_tail(lines = 1)
8
- Oxidized::String.new each_line.to_a[0..-1 - lines].join
8
+ return Oxidized::String.new("") if length.zero?
9
+
10
+ Oxidized::String.new each_line.to_a[0..(-1 - lines)].join
9
11
  end
10
12
 
11
13
  # @return [Oxidized::String] copy of self with first line removed
12
14
  def cut_head(lines = 1)
15
+ return Oxidized::String.new("") if length.zero?
16
+
13
17
  Oxidized::String.new each_line.to_a[lines..-1].join
14
18
  end
15
19
 
16
20
  # @return [Oxidized::String] copy of self with first and last lines removed
17
21
  def cut_both(head = 1, tail = 1)
18
- Oxidized::String.new each_line.to_a[head..-1 - tail].join
22
+ return Oxidized::String.new("") if length.zero?
23
+
24
+ Oxidized::String.new each_line.to_a[head..(-1 - tail)].join
19
25
  end
20
26
 
21
27
  # sets @cmd and @name unless @name is already set
@@ -26,7 +32,7 @@ module Oxidized
26
32
 
27
33
  def initialize(str = '')
28
34
  super
29
- return unless str.class == Oxidized::String
35
+ return unless str.instance_of?(Oxidized::String)
30
36
 
31
37
  @cmd = str.cmd
32
38
  @name = str.name
@@ -1,6 +1,6 @@
1
1
  module Oxidized
2
- VERSION = '0.28.0'.freeze
3
- VERSION_FULL = '0.28.0'.freeze
2
+ VERSION = '0.29.0'.freeze
3
+ VERSION_FULL = '0.29.0'.freeze
4
4
  def self.version_set
5
5
  version_full = %x(git describe --tags).chop rescue ""
6
6
  version = %x(git describe --tags --abbrev=0).chop rescue ""
@@ -5,7 +5,7 @@ module Oxidized
5
5
  def initialize(nodes)
6
6
  @jobs_done = 0
7
7
  @nodes = nodes
8
- @jobs = Jobs.new(Oxidized.config.threads, Oxidized.config.interval, @nodes)
8
+ @jobs = Jobs.new(Oxidized.config.threads, Oxidized.config.use_max_threads, Oxidized.config.interval, @nodes)
9
9
  @nodes.jobs = @jobs
10
10
  Thread.abort_on_exception = true
11
11
  end
@@ -56,7 +56,7 @@ module Oxidized
56
56
 
57
57
  def process_success(node, job)
58
58
  @jobs_done += 1 # needed for :nodes_done hook
59
- Oxidized.Hooks.handle :node_success, node: node,
59
+ Oxidized.hooks.handle :node_success, node: node,
60
60
  job: job
61
61
  msg = "update #{node.group}/#{node.name}"
62
62
  msg += " from #{node.from}" if node.from
@@ -66,7 +66,7 @@ module Oxidized
66
66
  msg: msg, email: node.email, user: node.user, group: node.group
67
67
  node.modified
68
68
  Oxidized.logger.info "Configuration updated for #{node.group}/#{node.name}"
69
- Oxidized.Hooks.handle :post_store, node: node,
69
+ Oxidized.hooks.handle :post_store, node: node,
70
70
  job: job,
71
71
  commitref: output.commitref
72
72
  end
@@ -87,7 +87,7 @@ module Oxidized
87
87
  @jobs_done += 1
88
88
  msg += ", retries exhausted, giving up"
89
89
  node.retry = 0
90
- Oxidized.Hooks.handle :node_fail, node: node,
90
+ Oxidized.hooks.handle :node_fail, node: node,
91
91
  job: job
92
92
  end
93
93
  Oxidized.logger.warn msg
@@ -103,7 +103,7 @@ module Oxidized
103
103
 
104
104
  def run_done_hook
105
105
  Oxidized.logger.debug "lib/oxidized/worker.rb: Running :nodes_done hook"
106
- Oxidized.Hooks.handle :nodes_done
106
+ Oxidized.hooks.handle :nodes_done
107
107
  rescue StandardError => e
108
108
  # swallow the hook erros and continue as normal
109
109
  Oxidized.logger.error "lib/oxidized/worker.rb: #{e.message}"
data/oxidized.gemspec CHANGED
@@ -17,22 +17,28 @@ Gem::Specification.new do |s|
17
17
  s.executables = %w[oxidized]
18
18
  s.require_path = 'lib'
19
19
 
20
- s.required_ruby_version = '>= 2.3'
21
- s.add_runtime_dependency 'asetus', '~> 0.1'
20
+ s.metadata['rubygems_mfa_required'] = 'true'
21
+
22
+ s.required_ruby_version = '>= 3.0'
23
+
24
+ s.add_runtime_dependency 'asetus', '~> 0.1'
22
25
  s.add_runtime_dependency 'bcrypt_pbkdf', '~> 1.0'
23
- s.add_runtime_dependency 'ed25519', '~> 1.2'
24
- s.add_runtime_dependency 'net-ssh', '~> 5'
25
- s.add_runtime_dependency 'net-telnet', '~> 0.2'
26
- s.add_runtime_dependency 'rugged', '~> 0.28.0'
27
- s.add_runtime_dependency 'slop', '~> 4.6'
26
+ s.add_runtime_dependency 'ed25519', '~> 1.2'
27
+ s.add_runtime_dependency 'net-ssh', '~> 7.1'
28
+ s.add_runtime_dependency 'net-telnet', '~> 0.2'
29
+ s.add_runtime_dependency 'rugged', '~> 1.6'
30
+ s.add_runtime_dependency 'slop', '~> 4.6'
28
31
 
29
- s.add_development_dependency 'bundler', '~> 2.0'
30
- s.add_development_dependency 'codecov' if ENV['CI'] == 'true'
31
- s.add_development_dependency 'git', '~> 1'
32
- s.add_development_dependency 'minitest', '~> 5.8'
33
- s.add_development_dependency 'mocha', '~> 1.1'
34
- s.add_development_dependency 'pry', '~> 0'
35
- s.add_development_dependency 'rake', '~> 10.0'
36
- s.add_development_dependency 'rubocop', '~> 0.80.0'
37
- s.add_development_dependency 'simplecov'
32
+ s.add_development_dependency 'bundler', '~> 2.2'
33
+ s.add_development_dependency 'git', '~> 1'
34
+ s.add_development_dependency 'minitest', '~> 5.18'
35
+ s.add_development_dependency 'mocha', '~> 1.2'
36
+ s.add_development_dependency 'pry', '~> 0.14.2'
37
+ s.add_development_dependency 'rake', '~> 13.0'
38
+ s.add_development_dependency 'rubocop', '~> 1.48.0'
39
+ s.add_development_dependency 'rubocop-minitest', '~> 0.29.0'
40
+ s.add_development_dependency 'rubocop-rake', '~> 0.6.0'
41
+ s.add_development_dependency 'simplecov', '~> 0.22.0'
42
+ s.add_development_dependency 'simplecov-cobertura', '~> 2.1.0'
43
+ s.add_development_dependency 'simplecov-html', '~> 0.12.3'
38
44
  end