oxidized 0.29.1 → 0.37.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 (236) hide show
  1. checksums.yaml +4 -4
  2. data/.coderabbit.yaml +21 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +45 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
  5. data/.github/ISSUE_TEMPLATE/support-request.md +39 -0
  6. data/.github/workflows/codeql.yml +4 -4
  7. data/.github/workflows/publishdocker.yml +108 -13
  8. data/.github/workflows/ruby.yml +3 -12
  9. data/.github/workflows/stale.yml +6 -1
  10. data/.gitignore +2 -0
  11. data/.rubocop.yml +69 -13
  12. data/.rubocop_todo.yml +13 -143
  13. data/CHANGELOG.md +431 -4
  14. data/CONTRIBUTING.md +189 -0
  15. data/Dockerfile +89 -34
  16. data/README.md +59 -188
  17. data/Rakefile +58 -12
  18. data/bin/oxidized +2 -5
  19. data/docs/Configuration.md +382 -149
  20. data/docs/Creating-Models.md +262 -10
  21. data/docs/DeviceSimulation.md +196 -0
  22. data/docs/Docker.md +246 -0
  23. data/docs/Hooks.md +146 -51
  24. data/docs/Inputs.md +237 -0
  25. data/docs/Issues.md +123 -0
  26. data/docs/Model-Notes/APC.md +72 -0
  27. data/docs/Model-Notes/Cumulus.md +5 -0
  28. data/docs/Model-Notes/EatonNetwork.md +18 -0
  29. data/docs/Model-Notes/ExaLink.md +43 -0
  30. data/docs/Model-Notes/FSOS.md +17 -0
  31. data/docs/Model-Notes/Fortinet.md +75 -0
  32. data/docs/Model-Notes/GrandstreamHT8xx.md +8 -0
  33. data/docs/Model-Notes/HPEAruba.md +32 -0
  34. data/docs/Model-Notes/IvantiConnectSecure.md +59 -0
  35. data/docs/Model-Notes/OS6.md +10 -0
  36. data/docs/Model-Notes/README.md +1 -20
  37. data/docs/Model-Notes/RouterOS.md +28 -0
  38. data/docs/Model-Notes/SikluMHTG.md +7 -0
  39. data/docs/Model-Notes/TrueNAS.md +23 -0
  40. data/docs/Model-Notes/XGS4600-Zyxel.md +5 -0
  41. data/docs/ModelUnitTests.md +219 -0
  42. data/docs/Outputs.md +102 -5
  43. data/docs/Release.md +102 -0
  44. data/docs/Ruby-API.md +135 -2
  45. data/docs/Sources.md +34 -0
  46. data/docs/Supported-OS-Types.md +207 -270
  47. data/docs/Troubleshooting.md +43 -1
  48. data/extra/device2yaml.rb +259 -0
  49. data/extra/gitdiff-msteams.sh +32 -5
  50. data/extra/hooks/modelrules.rb +55 -0
  51. data/extra/hooks/modelrulesadvanced.rb +167 -0
  52. data/extra/hooks/srcipmap.rb +54 -0
  53. data/extra/nagios_check_failing_nodes.rb +1 -1
  54. data/extra/oxidized.runit +1 -1
  55. data/extra/rest_client.rb +5 -4
  56. data/extra/syslog.rb +11 -6
  57. data/lib/oxidized/cli/support.rb +152 -0
  58. data/lib/oxidized/cli.rb +21 -6
  59. data/lib/oxidized/config/vars.rb +33 -14
  60. data/lib/oxidized/config.rb +28 -17
  61. data/lib/oxidized/core.rb +50 -8
  62. data/lib/oxidized/hook/ciscosparkdiff.rb +11 -9
  63. data/lib/oxidized/hook/exec.rb +5 -4
  64. data/lib/oxidized/hook/githubrepo.rb +55 -18
  65. data/lib/oxidized/hook/noophook.rb +2 -2
  66. data/lib/oxidized/hook/slackdiff.rb +50 -14
  67. data/lib/oxidized/hook/xmppdiff.rb +9 -9
  68. data/lib/oxidized/hook.rb +68 -16
  69. data/lib/oxidized/input/cli.rb +8 -3
  70. data/lib/oxidized/input/debugtext.rb +40 -0
  71. data/lib/oxidized/input/debugyaml.rb +82 -0
  72. data/lib/oxidized/input/exec.rb +2 -11
  73. data/lib/oxidized/input/ftp.rb +2 -19
  74. data/lib/oxidized/input/http.rb +67 -17
  75. data/lib/oxidized/input/input.rb +35 -14
  76. data/lib/oxidized/input/scp.rb +27 -0
  77. data/lib/oxidized/input/ssh.rb +59 -83
  78. data/lib/oxidized/input/sshbase.rb +102 -0
  79. data/lib/oxidized/input/telnet.rb +20 -19
  80. data/lib/oxidized/input/tftp.rb +8 -8
  81. data/lib/oxidized/job.rb +18 -7
  82. data/lib/oxidized/jobs.rb +11 -1
  83. data/lib/oxidized/logger.rb +51 -0
  84. data/lib/oxidized/manager.rb +18 -17
  85. data/lib/oxidized/model/acos.rb +2 -1
  86. data/lib/oxidized/model/addpack.rb +26 -0
  87. data/lib/oxidized/model/adtran.rb +5 -1
  88. data/lib/oxidized/model/adva.rb +3 -3
  89. data/lib/oxidized/model/airfiber.rb +1 -1
  90. data/lib/oxidized/model/aos7.rb +11 -0
  91. data/lib/oxidized/model/aoscx.rb +37 -29
  92. data/lib/oxidized/model/aosw.rb +39 -29
  93. data/lib/oxidized/model/apc_aos.rb +7 -2
  94. data/lib/oxidized/model/apcaos.rb +39 -0
  95. data/lib/oxidized/model/aricentiss.rb +9 -2
  96. data/lib/oxidized/model/arubainstant.rb +93 -0
  97. data/lib/oxidized/model/asa.rb +11 -10
  98. data/lib/oxidized/model/asternos.rb +22 -0
  99. data/lib/oxidized/model/asyncos.rb +3 -3
  100. data/lib/oxidized/model/audiocodes.rb +2 -2
  101. data/lib/oxidized/model/awplus.rb +15 -12
  102. data/lib/oxidized/model/axos.rb +1 -1
  103. data/lib/oxidized/model/bdcom.rb +1 -0
  104. data/lib/oxidized/model/c4cmts.rb +1 -2
  105. data/lib/oxidized/model/ciscosma.rb +1 -1
  106. data/lib/oxidized/model/ciscosmb.rb +6 -1
  107. data/lib/oxidized/model/cnos.rb +13 -10
  108. data/lib/oxidized/model/comtrol.rb +1 -1
  109. data/lib/oxidized/model/comware.rb +5 -3
  110. data/lib/oxidized/model/cumulus.rb +14 -2
  111. data/lib/oxidized/model/defacto.rb +26 -0
  112. data/lib/oxidized/model/dellx.rb +1 -1
  113. data/lib/oxidized/model/dlink.rb +5 -2
  114. data/lib/oxidized/model/dlinknextgen.rb +55 -0
  115. data/lib/oxidized/model/dnos.rb +3 -0
  116. data/lib/oxidized/model/dslcommands.rb +93 -0
  117. data/lib/oxidized/model/dslsetup.rb +102 -0
  118. data/lib/oxidized/model/eatonnetwork.rb +70 -0
  119. data/lib/oxidized/model/edgecos.rb +3 -1
  120. data/lib/oxidized/model/edgeos.rb +7 -6
  121. data/lib/oxidized/model/edgeswitch.rb +3 -1
  122. data/lib/oxidized/model/efos.rb +41 -0
  123. data/lib/oxidized/model/eltex.rb +4 -2
  124. data/lib/oxidized/model/enterasys800.rb +2 -2
  125. data/lib/oxidized/model/enterprise_sonic.rb +46 -0
  126. data/lib/oxidized/model/eos.rb +3 -1
  127. data/lib/oxidized/model/exalink.rb +36 -0
  128. data/lib/oxidized/model/f5os.rb +17 -0
  129. data/lib/oxidized/model/fabricos.rb +2 -2
  130. data/lib/oxidized/model/fastiron.rb +5 -3
  131. data/lib/oxidized/model/firebrick.rb +2 -2
  132. data/lib/oxidized/model/firelinuxos.rb +13 -6
  133. data/lib/oxidized/model/firewareos.rb +10 -1
  134. data/lib/oxidized/model/fortigate.rb +160 -0
  135. data/lib/oxidized/model/fortios.rb +38 -48
  136. data/lib/oxidized/model/fsos.rb +46 -0
  137. data/lib/oxidized/model/gaiaos.rb +4 -4
  138. data/lib/oxidized/model/garderos.rb +38 -0
  139. data/lib/oxidized/model/grandstreamht8xx.rb +19 -0
  140. data/lib/oxidized/model/h3c.rb +1 -1
  141. data/lib/oxidized/model/ibos.rb +1 -0
  142. data/lib/oxidized/model/ingate.rb +47 -0
  143. data/lib/oxidized/model/ios.rb +57 -30
  144. data/lib/oxidized/model/iosxr.rb +2 -2
  145. data/lib/oxidized/model/ironware.rb +7 -5
  146. data/lib/oxidized/model/ivanti.rb +54 -0
  147. data/lib/oxidized/model/junos.rb +12 -5
  148. data/lib/oxidized/model/kornfeldos.rb +33 -0
  149. data/lib/oxidized/model/lenovonos.rb +2 -0
  150. data/lib/oxidized/model/linksyssrw.rb +3 -3
  151. data/lib/oxidized/model/linuxgeneric.rb +4 -2
  152. data/lib/oxidized/model/macros.rb +60 -0
  153. data/lib/oxidized/model/mimosab11.rb +34 -0
  154. data/lib/oxidized/model/ml66.rb +33 -0
  155. data/lib/oxidized/model/mlnxos.rb +18 -14
  156. data/lib/oxidized/model/model.rb +98 -103
  157. data/lib/oxidized/model/mtrlrfs.rb +1 -0
  158. data/lib/oxidized/model/ndms.rb +6 -0
  159. data/lib/oxidized/model/netgear.rb +14 -3
  160. data/lib/oxidized/model/netonix.rb +1 -1
  161. data/lib/oxidized/model/netscaler.rb +1 -1
  162. data/lib/oxidized/model/nodegrid.rb +1 -1
  163. data/lib/oxidized/model/nsxdfw.rb +31 -0
  164. data/lib/oxidized/model/nsxfirewall.rb +2 -1
  165. data/lib/oxidized/model/nxos.rb +20 -15
  166. data/lib/oxidized/model/ocnos.rb +42 -0
  167. data/lib/oxidized/model/onefinity.rb +18 -0
  168. data/lib/oxidized/model/openbsd.rb +1 -1
  169. data/lib/oxidized/model/opengear.rb +36 -1
  170. data/lib/oxidized/model/openwrt.rb +6 -6
  171. data/lib/oxidized/model/opnsense.rb +9 -1
  172. data/lib/oxidized/model/os6.rb +48 -0
  173. data/lib/oxidized/model/outputs.rb +5 -0
  174. data/lib/oxidized/model/panos.rb +2 -0
  175. data/lib/oxidized/model/perle.rb +41 -0
  176. data/lib/oxidized/model/pfsense.rb +9 -0
  177. data/lib/oxidized/model/powerconnect.rb +32 -11
  178. data/lib/oxidized/model/procurve.rb +6 -2
  179. data/lib/oxidized/model/qtech.rb +3 -1
  180. data/lib/oxidized/model/quantaos.rb +8 -6
  181. data/lib/oxidized/model/rgos.rb +33 -0
  182. data/lib/oxidized/model/riverbed.rb +104 -0
  183. data/lib/oxidized/model/routeros.rb +18 -11
  184. data/lib/oxidized/model/saos.rb +18 -1
  185. data/lib/oxidized/model/saos10.rb +38 -0
  186. data/lib/oxidized/model/siklu.rb +1 -1
  187. data/lib/oxidized/model/siklumhtg.rb +22 -0
  188. data/lib/oxidized/model/sixwind.rb +28 -0
  189. data/lib/oxidized/model/slxos.rb +3 -3
  190. data/lib/oxidized/model/smartbyte.rb +48 -0
  191. data/lib/oxidized/model/sonicos.rb +27 -20
  192. data/lib/oxidized/model/speedtouch.rb +1 -1
  193. data/lib/oxidized/model/sros.rb +3 -3
  194. data/lib/oxidized/model/srosmd.rb +1 -1
  195. data/lib/oxidized/model/supermicro.rb +1 -1
  196. data/lib/oxidized/model/telco.rb +1 -1
  197. data/lib/oxidized/model/tmos.rb +1 -0
  198. data/lib/oxidized/model/tnsr.rb +57 -0
  199. data/lib/oxidized/model/tplink.rb +5 -5
  200. data/lib/oxidized/model/trango.rb +4 -2
  201. data/lib/oxidized/model/truenas.rb +64 -3
  202. data/lib/oxidized/model/ucs.rb +1 -1
  203. data/lib/oxidized/model/unifiap.rb +144 -0
  204. data/lib/oxidized/model/uplinkolt.rb +46 -0
  205. data/lib/oxidized/model/voltaire.rb +1 -1
  206. data/lib/oxidized/model/voss.rb +3 -0
  207. data/lib/oxidized/model/vrp.rb +5 -1
  208. data/lib/oxidized/model/vyatta.rb +9 -3
  209. data/lib/oxidized/model/vyos.rb +37 -0
  210. data/lib/oxidized/model/xos.rb +10 -1
  211. data/lib/oxidized/model/zhoneolt.rb +4 -2
  212. data/lib/oxidized/model/zynos.rb +67 -3
  213. data/lib/oxidized/model/zynosadsl.rb +14 -0
  214. data/lib/oxidized/model/zynoscli.rb +1 -1
  215. data/lib/oxidized/model/zynosgs.rb +2 -0
  216. data/lib/oxidized/model/zynosmgs.rb +32 -0
  217. data/lib/oxidized/node.rb +99 -64
  218. data/lib/oxidized/nodes.rb +40 -19
  219. data/lib/oxidized/output/file.rb +80 -43
  220. data/lib/oxidized/output/git.rb +295 -151
  221. data/lib/oxidized/output/gitcrypt.rb +193 -185
  222. data/lib/oxidized/output/http.rb +63 -51
  223. data/lib/oxidized/output/output.rb +20 -4
  224. data/lib/oxidized/signals.rb +44 -0
  225. data/lib/oxidized/source/csv.rb +49 -49
  226. data/lib/oxidized/source/http.rb +76 -63
  227. data/lib/oxidized/source/jsonfile.rb +68 -0
  228. data/lib/oxidized/source/source.rb +73 -18
  229. data/lib/oxidized/source/sql.rb +71 -59
  230. data/lib/oxidized/version.rb +6 -4
  231. data/lib/oxidized/worker.rb +57 -29
  232. data/lib/oxidized.rb +4 -24
  233. data/lib/refinements.rb +21 -1
  234. data/oxidized.gemspec +45 -21
  235. metadata +248 -41
  236. data/lib/oxidized/model/timos.rb +0 -10
@@ -1,226 +1,234 @@
1
1
  module Oxidized
2
- class GitCrypt < Output
3
- class GitCryptError < OxidizedError; end
4
- begin
5
- require 'git'
6
- rescue LoadError
7
- raise OxidizedError, 'git not found: sudo gem install git'
8
- end
9
-
10
- 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
11
11
 
12
- def initialize
13
- super
14
- @cfg = Oxidized.config.output.gitcrypt
15
- @gitcrypt_cmd = "/usr/bin/git-crypt"
16
- @gitcrypt_init = @gitcrypt_cmd + " init"
17
- @gitcrypt_unlock = @gitcrypt_cmd + " unlock"
18
- @gitcrypt_lock = @gitcrypt_cmd + " lock"
19
- @gitcrypt_adduser = @gitcrypt_cmd + " add-gpg-user --trusted "
20
- end
12
+ attr_reader :commitref
21
13
 
22
- def setup
23
- if @cfg.empty?
24
- Oxidized.asetus.user.output.gitcrypt.user = 'Oxidized'
25
- Oxidized.asetus.user.output.gitcrypt.email = 'o@example.com'
26
- Oxidized.asetus.user.output.gitcrypt.repo = File.join(Config::Root, 'oxidized.git')
27
- Oxidized.asetus.save :user
28
- 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 "
29
22
  end
30
23
 
31
- if @cfg.repo.respond_to?(:each)
32
- @cfg.repo.each do |group, repo|
33
- @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
34
39
  end
35
- else
36
- @cfg.repo = File.expand_path @cfg.repo
37
40
  end
38
- end
39
41
 
40
- def crypt_init(repo)
41
- repo.chdir do
42
- system(@gitcrypt_init)
43
- @cfg.users.each do |user|
44
- 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")
45
51
  end
46
- File.write(".gitattributes", "* filter=git-crypt diff=git-crypt\n.gitattributes !filter !diff")
47
- repo.add(".gitattributes")
48
- repo.commit("Initial commit: crypt all config files")
49
52
  end
50
- end
51
53
 
52
- def lock(repo)
53
- repo.chdir do
54
- system(@gitcrypt_lock)
54
+ def lock(repo)
55
+ repo.chdir do
56
+ system(@gitcrypt_lock)
57
+ end
55
58
  end
56
- end
57
59
 
58
- def unlock(repo)
59
- repo.chdir do
60
- system(@gitcrypt_unlock)
60
+ def unlock(repo)
61
+ repo.chdir do
62
+ system(@gitcrypt_unlock)
63
+ end
61
64
  end
62
- end
63
65
 
64
- def store(file, outputs, opt = {})
65
- @msg = opt[:msg]
66
- @user = (opt[:user] || @cfg.user)
67
- @email = (opt[:email] || @cfg.email)
68
- @opt = opt
69
- @commitref = nil
70
- repo = @cfg.repo
71
-
72
- outputs.types.each do |type|
73
- type_cfg = ''
74
- type_repo = File.join(File.dirname(repo), type + '.git')
75
- outputs.type(type).each do |output|
76
- (type_cfg << output; next) unless output.name # rubocop:disable Style/Semicolon
77
- type_file = file + '--' + output.name
78
- if @cfg.type_as_directory?
79
- type_file = type + '/' + type_file
80
- 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
81
85
  end
82
- update type_repo, type_file, output
86
+ update type_repo, file, type_cfg
83
87
  end
84
- update type_repo, file, type_cfg
85
- end
86
88
 
87
- update repo, file, outputs.to_cfg
88
- end
89
+ update repo, file, outputs.to_cfg unless opt[:significant_changes] == false
90
+ end
89
91
 
90
- def fetch(node, group)
91
- repo, path = yield_repo_and_path(node, group)
92
- repo = Git.open repo
93
- unlock repo
94
- index = repo.index
95
- # Empty repo ?
96
- raise 'Empty git repo' if File.exist?(index.path)
97
-
98
- File.read path
99
- lock repo
100
- rescue StandardError
101
- 'node not found'
102
- 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
103
105
 
104
- # give a hash of all oid revision for the given node, and the date of the commit
105
- def version(node, group)
106
- repo, path = yield_repo_and_path(node, group)
107
-
108
- repo = Git.open repo
109
- unlock repo
110
- walker = repo.log.path(path)
111
- i = -1
112
- tab = []
113
- walker.each do |commit|
114
- hash = {}
115
- hash[:date] = commit.date.to_s
116
- hash[:oid] = commit.objectish
117
- hash[:author] = commit.author
118
- hash[:message] = commit.message
119
- 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
+ # We keep :date for reverse compatibility on oxidized-web <= 0.15.1
118
+ hash[:date] = commit.date.to_s
119
+ # date as a Time instance for more flexibility in oxidized-web
120
+ hash[:time] = commit.date
121
+ hash[:oid] = commit.objectish
122
+ hash[:author] = commit.author
123
+ hash[:message] = commit.message
124
+ tab[i += 1] = hash
125
+ end
126
+ walker.reset
127
+ tab
128
+ rescue StandardError
129
+ 'node not found'
120
130
  end
121
- walker.reset
122
- tab
123
- rescue StandardError
124
- 'node not found'
125
- end
126
131
 
127
- # give the blob of a specific revision
128
- def get_version(node, group, oid)
129
- repo, path = yield_repo_and_path(node, group)
130
- repo = Git.open repo
131
- unlock repo
132
- repo.gtree(oid).files[path].contents
133
- rescue StandardError
134
- 'version not found'
135
- ensure
136
- lock repo
137
- end
132
+ # give the blob of a specific revision
133
+ def get_version(node, group, oid)
134
+ repo, path = yield_repo_and_path(node, group)
135
+ repo = Git.open repo
136
+ unlock repo
137
+ repo.gtree(oid).files[path].contents
138
+ rescue StandardError
139
+ 'version not found'
140
+ ensure
141
+ lock repo
142
+ end
138
143
 
139
- # give a hash with the patch of a diff between 2 revision and the stats (added and deleted lines)
140
- def get_diff(node, group, oid1, oid2)
141
- diff_commits = nil
142
- repo, _path = yield_repo_and_path(node, group)
143
- repo = Git.open repo
144
- unlock repo
145
- commit = repo.gcommit(oid1)
146
-
147
- if oid2
148
- commit_old = repo.gcommit(oid2)
149
- diff = repo.diff(commit_old, commit)
150
- stats = [diff.stats[:files][node.name][:insertions], diff.stats[:files][node.name][:deletions]]
151
- diff.each do |patch|
152
- if /#{node.name}\s+/ =~ patch.patch.to_s.lines.first
153
- diff_commits = { patch: patch.patch.to_s, stat: stats }
154
- break
144
+ # give a hash with the patch of a diff between 2 revision and the stats (added and deleted lines)
145
+ def get_diff(node, group, oid1, oid2)
146
+ diff_commits = nil
147
+ repo, _path = yield_repo_and_path(node, group)
148
+ repo = Git.open repo
149
+ unlock repo
150
+ commit = repo.gcommit(oid1)
151
+
152
+ if oid2
153
+ commit_old = repo.gcommit(oid2)
154
+ diff = repo.diff(commit_old, commit)
155
+ stats = [diff.stats[:files][node.name][:insertions], diff.stats[:files][node.name][:deletions]]
156
+ diff.each do |patch|
157
+ if /#{node.name}\s+/ =~ patch.patch.to_s.lines.first
158
+ diff_commits = { patch: patch.patch.to_s, stat: stats }
159
+ break
160
+ end
155
161
  end
162
+ else
163
+ stat = commit.parents[0].diff(commit).stats
164
+ stat = [stat[:files][node.name][:insertions], stat[:files][node.name][:deletions]]
165
+ patch = commit.parents[0].diff(commit).patch
166
+ diff_commits = { patch: patch, stat: stat }
156
167
  end
157
- else
158
- stat = commit.parents[0].diff(commit).stats
159
- stat = [stat[:files][node.name][:insertions], stat[:files][node.name][:deletions]]
160
- patch = commit.parents[0].diff(commit).patch
161
- diff_commits = { patch: patch, stat: stat }
168
+ lock repo
169
+ diff_commits
170
+ rescue StandardError
171
+ 'no diffs'
172
+ ensure
173
+ lock repo
162
174
  end
163
- lock repo
164
- diff_commits
165
- rescue StandardError
166
- 'no diffs'
167
- ensure
168
- lock repo
169
- end
170
-
171
- private
172
175
 
173
- def yield_repo_and_path(node, group)
174
- repo, path = node.repo, node.name
176
+ private
175
177
 
176
- path = "#{group}/#{node.name}" if group && @cfg.single_repo?
178
+ def yield_repo_and_path(node, group)
179
+ repo = node.repo
180
+ path = node.name
177
181
 
178
- [repo, path]
179
- end
182
+ path = "#{group}/#{node.name}" if group && @cfg.single_repo?
180
183
 
181
- def update(repo, file, data)
182
- return if data.empty?
184
+ [repo, path]
185
+ end
183
186
 
184
- if @opt[:group]
185
- if @cfg.single_repo?
186
- file = File.join @opt[:group], file
187
- else
188
- repo = if repo.is_a?(::String)
189
- File.join File.dirname(repo), @opt[:group] + '.git'
190
- else
191
- repo[@opt[:group]]
192
- end
187
+ def update(repo, file, data)
188
+ return if data.empty?
189
+
190
+ if @opt[:group]
191
+ if @cfg.single_repo?
192
+ file = ::File.join @opt[:group], file
193
+ else
194
+ repo = if repo.is_a?(::String)
195
+ ::File.join ::File.dirname(repo), @opt[:group] + '.git'
196
+ else
197
+ repo[@opt[:group]]
198
+ end
199
+ end
193
200
  end
194
- end
195
201
 
196
- begin
197
- update_repo repo, file, data, @msg, @user, @email
198
- rescue Git::GitExecuteError, ArgumentError => e
199
- Oxidized.logger.debug "open_error #{e} #{file}"
200
202
  begin
201
- grepo = Git.init repo
202
- crypt_init grepo
203
- rescue StandardError => create_error
204
- raise GitCryptError, "first '#{e.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo"
203
+ update_repo repo, file, data, @msg, @user, @email
204
+ rescue Git::GitExecuteError, ArgumentError => e
205
+ logger.debug "open_error #{e} #{file}"
206
+ begin
207
+ grepo = Git.init repo
208
+ crypt_init grepo
209
+ rescue StandardError => create_error
210
+ raise GitCryptError, "first '#{e.message}' was raised while opening git repo, then " \
211
+ "'#{create_error.message}' was while trying to create git repo"
212
+ end
213
+ retry
205
214
  end
206
- retry
207
215
  end
208
- end
209
216
 
210
- def update_repo(repo, file, data, msg, user, email)
211
- grepo = Git.open repo
212
- grepo.config('user.name', user)
213
- grepo.config('user.email', email)
214
- grepo.chdir do
215
- unlock grepo
216
- File.write(file, data)
217
- grepo.add(file)
218
- if grepo.status[file].nil? || !grepo.status[file].type.nil?
219
- grepo.commit(msg)
220
- @commitref = grepo.log(1).first.objectish
221
- true
217
+ def update_repo(repo, file, data, msg, user, email)
218
+ grepo = Git.open repo
219
+ grepo.config('user.name', user)
220
+ grepo.config('user.email', email)
221
+ grepo.chdir do
222
+ unlock grepo
223
+ ::File.write(file, data)
224
+ grepo.add(file)
225
+ if grepo.status[file].nil? || !grepo.status[file].type.nil?
226
+ grepo.commit(msg)
227
+ @commitref = grepo.log(1).first.objectish
228
+ true
229
+ end
230
+ lock grepo
222
231
  end
223
- lock grepo
224
232
  end
225
233
  end
226
234
  end
@@ -1,61 +1,73 @@
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
20
+
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
+
30
+ # if uri scheme is https, enable ssl and set verify mode
31
+ if uri.scheme == "https"
32
+ http.use_ssl = true
33
+ http.verify_mode = @cfg.ssl_verify? ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
34
+ end
19
35
 
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}"
36
+ headers = @cfg.headers? ? @cfg.headers : {}
37
+
38
+ req = Net::HTTP::Post.new(uri.request_uri, headers.merge('Content-Type' => 'application/json'))
39
+ req.basic_auth(@cfg.user, @cfg.password) if @cfg.user? && @cfg.password?
40
+
41
+ req.body = generate_json(node, outputs, opt)
42
+ response = http.request req
43
+
44
+ case response.code.to_i
45
+ when 200 || 201
46
+ logger.info "Configuration http backup complete for #{node}"
47
+ p [:success]
48
+ when (400..499)
49
+ logger.info "Configuration http backup for #{node} failed status: #{response.body}"
50
+ p [:bad_request]
51
+ when (500..599)
52
+ p [:server_problems]
53
+ logger.info "Configuration http backup for #{node} failed status: #{response.body}"
54
+ end
44
55
  end
45
- end
46
56
 
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
- )
57
+ private
58
+
59
+ def generate_json(node, outputs, opt)
60
+ JSON.pretty_generate(
61
+ 'msg' => opt[:msg],
62
+ 'user' => opt[:user],
63
+ 'email' => opt[:email],
64
+ 'group' => opt[:group],
65
+ 'node' => node,
66
+ 'config' => outputs.to_cfg
67
+ # actually we need to also iterate outputs, for other types like in gitlab.
68
+ # But most people don't use 'type' functionality.
69
+ )
70
+ end
59
71
  end
60
72
  end
61
73
  end
@@ -1,9 +1,25 @@
1
1
  module Oxidized
2
- class Output
3
- class NoConfig < OxidizedError; end
2
+ module Output
3
+ def self.clean_obsolete_nodes(active_nodes)
4
+ return unless Oxidized.config.output.clean_obsolete_nodes?
4
5
 
5
- def cfg_to_str(cfg)
6
- cfg.select { |h| h[:type] == 'cfg' }.map { |h| h[:data] }.join
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
+
11
+ class Output
12
+ include SemanticLogger::Loggable
13
+
14
+ class NoConfig < OxidizedError; end
15
+
16
+ def cfg_to_str(cfg)
17
+ cfg.select { |h| h[:type] == 'cfg' }.map { |h| h[:data] }.join
18
+ end
19
+
20
+ def self.clean_obsolete_nodes(_active_nodes)
21
+ logger.warn "clean_obsolete_nodes is not implemented for #{name}"
22
+ end
7
23
  end
8
24
  end
9
25
  end
@@ -0,0 +1,44 @@
1
+ # Monkey patch Signal.trap for Puma to keep it from overriding our handlers
2
+ # Also prevent Puma from registering its own SIGHUP handler
3
+ module Puma
4
+ class Signal
5
+ class << self
6
+ alias os_trap trap
7
+ def Signal.trap(sig, &block)
8
+ sigshortname = sig.gsub "SIG", ''
9
+ Oxidized::Signals.register_signal(sig, block) unless sigshortname.eql? 'HUP'
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ module Oxidized
16
+ class Signals
17
+ @handlers = Hash.new { |h, k| h[k] = [] }
18
+ class << self
19
+ attr_accessor :handlers
20
+
21
+ def register_signal(sig, procobj)
22
+ # Compute short name of the signal (without SIG prefix)
23
+ sigshortname = sig.gsub "SIG", ''
24
+ signum = Signal.list[sigshortname]
25
+
26
+ # Register the handler with OS
27
+ Signal.trap signum do
28
+ Oxidized::Signals.handle_signal(signum)
29
+ end
30
+
31
+ # Add the proc to the handler list for the requested signal
32
+ @handlers[signum].push(procobj)
33
+ end
34
+
35
+ def handle_signal(signum)
36
+ return unless handlers.has_key?(signum)
37
+
38
+ @handlers[signum].each do |handler|
39
+ handler.call
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end