oxidized 0.34.3 → 0.36.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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/.coderabbit.yaml +21 -0
  3. data/.github/workflows/codeql.yml +4 -4
  4. data/.github/workflows/publishdocker.yml +88 -15
  5. data/.github/workflows/ruby.yml +2 -4
  6. data/.github/workflows/stale.yml +1 -1
  7. data/.rubocop.yml +14 -2
  8. data/.rubocop_todo.yml +21 -2
  9. data/CHANGELOG.md +86 -1
  10. data/Dockerfile +74 -66
  11. data/README.md +4 -5
  12. data/Rakefile +21 -3
  13. data/docs/Configuration.md +122 -1
  14. data/docs/Creating-Models.md +209 -28
  15. data/docs/Docker.md +2 -1
  16. data/docs/Inputs.md +29 -0
  17. data/docs/Model-Notes/APC.md +72 -0
  18. data/docs/Model-Notes/ExaLink.md +43 -0
  19. data/docs/Model-Notes/Fortinet.md +75 -0
  20. data/docs/Model-Notes/IvantiConnectSecure.md +59 -0
  21. data/docs/Model-Notes/TrueNAS.md +19 -0
  22. data/docs/ModelUnitTests.md +23 -0
  23. data/docs/Outputs.md +18 -4
  24. data/docs/Release.md +1 -1
  25. data/docs/Ruby-API.md +134 -1
  26. data/docs/Supported-OS-Types.md +22 -8
  27. data/docs/Troubleshooting.md +1 -1
  28. data/extra/device2yaml.rb +2 -3
  29. data/extra/hooks/modelrules.rb +55 -0
  30. data/extra/hooks/modelrulesadvanced.rb +168 -0
  31. data/extra/hooks/srcipmap.rb +54 -0
  32. data/extra/oxidized.runit +1 -1
  33. data/lib/oxidized/core.rb +2 -1
  34. data/lib/oxidized/hook/githubrepo.rb +2 -1
  35. data/lib/oxidized/hook.rb +56 -8
  36. data/lib/oxidized/input/exec.rb +0 -4
  37. data/lib/oxidized/input/ftp.rb +0 -13
  38. data/lib/oxidized/input/http.rb +47 -15
  39. data/lib/oxidized/input/input.rb +33 -13
  40. data/lib/oxidized/input/scp.rb +11 -65
  41. data/lib/oxidized/input/ssh.rb +12 -62
  42. data/lib/oxidized/input/sshbase.rb +107 -0
  43. data/lib/oxidized/input/telnet.rb +2 -6
  44. data/lib/oxidized/input/tftp.rb +7 -3
  45. data/lib/oxidized/model/adva.rb +1 -1
  46. data/lib/oxidized/model/airfiber.rb +1 -1
  47. data/lib/oxidized/model/aoscx.rb +32 -45
  48. data/lib/oxidized/model/aosw.rb +11 -12
  49. data/lib/oxidized/model/apc_aos.rb +4 -0
  50. data/lib/oxidized/model/apcaos.rb +39 -0
  51. data/lib/oxidized/model/arubainstant.rb +29 -26
  52. data/lib/oxidized/model/asa.rb +7 -7
  53. data/lib/oxidized/model/asternos.rb +1 -1
  54. data/lib/oxidized/model/axos.rb +1 -1
  55. data/lib/oxidized/model/comtrol.rb +1 -1
  56. data/lib/oxidized/model/comware.rb +3 -1
  57. data/lib/oxidized/model/cumulus.rb +2 -7
  58. data/lib/oxidized/model/defacto.rb +26 -0
  59. data/lib/oxidized/model/dslcommands.rb +93 -0
  60. data/lib/oxidized/model/dslsetup.rb +102 -0
  61. data/lib/oxidized/model/eatonnetwork.rb +5 -0
  62. data/lib/oxidized/model/efos.rb +5 -5
  63. data/lib/oxidized/model/eltex.rb +1 -1
  64. data/lib/oxidized/model/enterasys800.rb +1 -1
  65. data/lib/oxidized/model/exalink.rb +36 -0
  66. data/lib/oxidized/model/fabricos.rb +1 -1
  67. data/lib/oxidized/model/fastiron.rb +2 -2
  68. data/lib/oxidized/model/firelinuxos.rb +1 -3
  69. data/lib/oxidized/model/fortigate.rb +160 -0
  70. data/lib/oxidized/model/fortios.rb +28 -69
  71. data/lib/oxidized/model/fsos.rb +2 -4
  72. data/lib/oxidized/model/garderos.rb +1 -6
  73. data/lib/oxidized/model/h3c.rb +1 -1
  74. data/lib/oxidized/model/ios.rb +21 -15
  75. data/lib/oxidized/model/ironware.rb +6 -4
  76. data/lib/oxidized/model/ivanti.rb +54 -0
  77. data/lib/oxidized/model/macros.rb +60 -0
  78. data/lib/oxidized/model/mlnxos.rb +14 -17
  79. data/lib/oxidized/model/model.rb +89 -98
  80. data/lib/oxidized/model/ndms.rb +6 -0
  81. data/lib/oxidized/model/netgear.rb +6 -3
  82. data/lib/oxidized/model/netonix.rb +1 -1
  83. data/lib/oxidized/model/netscaler.rb +1 -1
  84. data/lib/oxidized/model/nxos.rb +9 -9
  85. data/lib/oxidized/model/onefinity.rb +1 -1
  86. data/lib/oxidized/model/opnsense.rb +8 -0
  87. data/lib/oxidized/model/outputs.rb +5 -0
  88. data/lib/oxidized/model/perle.rb +41 -0
  89. data/lib/oxidized/model/pfsense.rb +8 -0
  90. data/lib/oxidized/model/saos10.rb +1 -1
  91. data/lib/oxidized/model/siklu.rb +1 -1
  92. data/lib/oxidized/model/siklumhtg.rb +1 -1
  93. data/lib/oxidized/model/sixwind.rb +1 -1
  94. data/lib/oxidized/model/slxos.rb +1 -1
  95. data/lib/oxidized/model/smartbyte.rb +48 -0
  96. data/lib/oxidized/model/sonicos.rb +1 -1
  97. data/lib/oxidized/model/speedtouch.rb +1 -1
  98. data/lib/oxidized/model/telco.rb +1 -1
  99. data/lib/oxidized/model/tnsr.rb +7 -3
  100. data/lib/oxidized/model/trango.rb +1 -1
  101. data/lib/oxidized/model/truenas.rb +10 -1
  102. data/lib/oxidized/model/ucs.rb +1 -1
  103. data/lib/oxidized/model/voltaire.rb +1 -1
  104. data/lib/oxidized/model/voss.rb +3 -0
  105. data/lib/oxidized/model/vyatta.rb +1 -1
  106. data/lib/oxidized/model/vyos.rb +36 -0
  107. data/lib/oxidized/model/zhoneolt.rb +1 -1
  108. data/lib/oxidized/model/zynoscli.rb +1 -1
  109. data/lib/oxidized/node.rb +31 -24
  110. data/lib/oxidized/nodes.rb +2 -0
  111. data/lib/oxidized/output/file.rb +7 -1
  112. data/lib/oxidized/output/git.rb +11 -1
  113. data/lib/oxidized/output/gitcrypt.rb +1 -1
  114. data/lib/oxidized/output/http.rb +12 -3
  115. data/lib/oxidized/source/csv.rb +5 -0
  116. data/lib/oxidized/source/http.rb +10 -2
  117. data/lib/oxidized/source/jsonfile.rb +5 -0
  118. data/lib/oxidized/source/sql.rb +5 -0
  119. data/lib/oxidized/version.rb +2 -2
  120. data/lib/oxidized/worker.rb +36 -15
  121. data/lib/refinements.rb +18 -0
  122. data/oxidized.gemspec +28 -25
  123. metadata +98 -71
  124. data/docs/Model-Notes/APC_AOS.md +0 -65
  125. data/docs/Model-Notes/FortiOS.md +0 -44
  126. data/lib/oxidized/model/timos.rb +0 -10
@@ -23,11 +23,11 @@ module Oxidized
23
23
  "#{@jobs_done} of #{@nodes.size}"
24
24
  # ask for next node in queue non destructive way
25
25
  nextnode = @nodes.first
26
- unless nextnode.last.nil?
27
- # Set unobtainable value for 'last' if interval checking is disabled
28
- last = Oxidized.config.interval.zero? ? Time.now.utc + 10 : nextnode.last.end
29
- break if last + Oxidized.config.interval > Time.now.utc
30
- end
26
+ break if Oxidized.config.interval.zero? && !nextnode.nexted?
27
+
28
+ nextnode.nexted = false
29
+ break if !nextnode.last.nil? && (nextnode.last.end + Oxidized.config.interval > Time.now.utc)
30
+
31
31
  # shift nodes and get the next node
32
32
  node = @nodes.get
33
33
  node.running? ? next : node.running = true
@@ -64,21 +64,43 @@ module Oxidized
64
64
 
65
65
  private
66
66
 
67
+ def significant_changes?(job, output)
68
+ node = job.node
69
+ model = node.model
70
+ return true unless model.vars(:output_store_mode) == "on_significant"
71
+
72
+ unless output.respond_to?(:fetch)
73
+ logger.error("Detection of significant changes needs an output " \
74
+ "capable of fetching the last configuration")
75
+ return true
76
+ end
77
+
78
+ old = model.significant_changes output.fetch(node, node.group)
79
+ new = model.significant_changes job.config.to_cfg
80
+ if old == new
81
+ logger.debug "No significant change on node #{node.name}"
82
+ false
83
+ else
84
+ true
85
+ end
86
+ end
87
+
67
88
  def process_success(node, job)
68
89
  @jobs_done += 1 # needed for :nodes_done hook
69
- Oxidized.hooks.handle :node_success, node: node,
70
- job: job
90
+ Oxidized.hooks.node_success(node: node, job: job)
71
91
  msg = "update #{node.group}/#{node.name}"
72
92
  msg += " from #{node.from}" if node.from
73
93
  msg += " with message '#{node.msg}'" if node.msg
74
94
  output = node.output.new
75
- if output.store node.name, job.config,
76
- msg: msg, email: node.email, user: node.user, group: node.group
95
+
96
+ significant_changes = significant_changes?(job, output)
97
+ if output.store(node.name, job.config,
98
+ msg: msg, email: node.email, user: node.user,
99
+ group: node.group,
100
+ significant_changes: significant_changes)
77
101
  node.modified
78
102
  logger.info "Configuration updated for #{node.group}/#{node.name}"
79
- Oxidized.hooks.handle :post_store, node: node,
80
- job: job,
81
- commitref: output.commitref
103
+ Oxidized.hooks.post_store(node: node, job: job, commitref: output.commitref)
82
104
  end
83
105
  node.reset
84
106
  end
@@ -97,8 +119,7 @@ module Oxidized
97
119
  @jobs_done += 1
98
120
  msg += ", retries exhausted, giving up"
99
121
  node.retry = 0
100
- Oxidized.hooks.handle :node_fail, node: node,
101
- job: job
122
+ Oxidized.hooks.node_fail(node: node, job: job)
102
123
  end
103
124
  logger.warn msg
104
125
  end
@@ -110,7 +131,7 @@ module Oxidized
110
131
 
111
132
  def run_done_hook
112
133
  logger.debug "Running :nodes_done hook"
113
- Oxidized.hooks.handle :nodes_done
134
+ Oxidized.hooks.nodes_done
114
135
  rescue StandardError => e
115
136
  # swallow the hook erros and continue as normal
116
137
  logger.error e.message
data/lib/refinements.rb CHANGED
@@ -32,6 +32,24 @@ module Refinements
32
32
  # rubocop:enable Naming/MemoizedInstanceVariableName
33
33
  end
34
34
 
35
+ # keeps lines matching any pattern (String or Regexp)
36
+ def keep_lines(patterns)
37
+ each_line.select do |line|
38
+ patterns.any? do |pattern|
39
+ pattern.is_a?(Regexp) ? line =~ pattern : line.include?(pattern)
40
+ end
41
+ end.join
42
+ end
43
+
44
+ # remove lines matching any pattern (String or Regexp)
45
+ def reject_lines(patterns)
46
+ each_line.reject do |line|
47
+ patterns.any? do |pattern|
48
+ pattern.is_a?(Regexp) ? line =~ pattern : line.include?(pattern)
49
+ end
50
+ end.join
51
+ end
52
+
35
53
  # Initializes the String instance variables from another String instance
36
54
  # when the given str is an instance of String with Oxidized refinements applied
37
55
  def init_from_string(str = '')
data/oxidized.gemspec CHANGED
@@ -18,48 +18,51 @@ Gem::Specification.new do |s|
18
18
 
19
19
  s.metadata['rubygems_mfa_required'] = 'true'
20
20
 
21
- s.required_ruby_version = '>= 3.1'
21
+ # Ruby version strategy
22
+ #
23
+ # We try to keep the minimum version of Ruby to match supported LTS versions
24
+ # of common Linux distributions, as long as the maintenance effort remains
25
+ # reasonable.
26
+ s.required_ruby_version = '>= 3.0'
22
27
 
23
28
  # Gemspec strategy
24
29
  #
25
30
  # For dependency and optional dependencies, we try to set the minimal
26
- # dependency lower than the Ubuntu Noble or Debian Bookworm package version,
31
+ # dependency lower or equal to the Debian 13 "Trixie" package version,
27
32
  # so that native packages can be used.
28
- # We limit the maximal version so that dependabot can warn about new versions
29
- # and we can test them before activating them in Oxidized.
30
- #
31
- # development dependencies are set to the latest minor version of a library
32
- # and updated after having tested them
33
+ # We limit the maximal minor version so that dependabot can warn about new
34
+ # major versions and we can test them before activating them in Oxidized.
33
35
 
34
36
  s.add_dependency 'asetus', '~> 0.4'
35
37
  s.add_dependency 'bcrypt_pbkdf', '~> 1.0'
36
38
  s.add_dependency 'ed25519', '~> 1.2'
37
39
  s.add_dependency 'net-ftp', '~> 0.2'
38
40
  s.add_dependency 'net-http-digest_auth', '~> 1.4'
39
- s.add_dependency 'net-scp', '~> 4.1'
40
41
  s.add_dependency 'net-ssh', '~> 7.3'
41
42
  s.add_dependency 'net-telnet', '~> 0.2'
42
43
  s.add_dependency 'psych', '~> 5.0'
43
44
  s.add_dependency 'rugged', '~> 1.6'
44
- s.add_dependency 'semantic_logger', '~> 4.17.0'
45
+ s.add_dependency 'semantic_logger', '~> 4.17'
45
46
  s.add_dependency 'slop', '~> 4.6'
46
- s.add_dependency 'syslog', '~> 0.3.0'
47
- s.add_dependency 'syslog_protocol', '~> 0.9.2'
47
+ s.add_dependency 'syslog', '~> 0.3'
48
+ s.add_dependency 'syslog_protocol', '~> 0.9'
48
49
 
49
- s.add_development_dependency 'bundler', '~> 2.2'
50
- # ruby-git 4.0 requests ruby >= 3.2, we stick to ruby >= 3.1 (Ubuntu Noble/Debian Bookworm)
51
- s.add_development_dependency 'git', '>= 2.0', '< 3.2.0'
52
- s.add_development_dependency 'minitest', '~> 5.25.4'
53
- s.add_development_dependency 'mocha', '~> 2.1'
54
- s.add_development_dependency 'pry', '~> 0.15.0'
55
- s.add_development_dependency 'rake', '~> 13.0'
56
- s.add_development_dependency 'rubocop', '~> 1.79.1'
57
- s.add_development_dependency 'rubocop-minitest', '~> 0.38.0'
58
- s.add_development_dependency 'rubocop-rake', '~> 0.7.0'
59
- s.add_development_dependency 'rubocop-sequel', '~> 0.4.0'
60
- s.add_development_dependency 'simplecov', '~> 0.22.0'
50
+ s.add_development_dependency 'minitest', '>= 5.18', '<7'
51
+ s.add_development_dependency 'mocha', '>= 2.1', '<4'
52
+ s.add_development_dependency 'pry', '~> 0.15'
53
+ s.add_development_dependency 'rake', '~> 13.0'
54
+ # Rubocop introduces new rules in minor versions, so we limit automatic
55
+ # updates to patches
56
+ s.add_development_dependency 'rubocop', '~> 1.86.0'
57
+ s.add_development_dependency 'rubocop-minitest', '~> 0.39.1'
58
+ s.add_development_dependency 'rubocop-rake', '~> 0.7.0'
59
+ s.add_development_dependency 'rubocop-sequel', '~> 0.4.0'
60
+ s.add_development_dependency 'simplecov', '~> 0.22'
61
61
 
62
62
  # Dependencies on optional libraries, used for unit tests & development
63
- s.add_development_dependency 'oxidized-web', '~> 0.17.1'
64
- s.add_development_dependency 'sequel', '>= 5.63.0', '< 5.96.0'
63
+ s.add_development_dependency 'git', '>= 2.0', '< 5'
64
+ s.add_development_dependency 'net-scp', '~> 4.1'
65
+ s.add_development_dependency 'net-tftp', '~> 0.1.0'
66
+ s.add_development_dependency 'oxidized-web', '>= 0.17.1'
67
+ s.add_development_dependency 'sequel', '>= 5.63.0', '< 6'
65
68
  end