oxidized 0.35.0 → 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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/.coderabbit.yaml +21 -0
  3. data/.github/workflows/publishdocker.yml +11 -9
  4. data/.github/workflows/ruby.yml +1 -3
  5. data/.rubocop.yml +13 -2
  6. data/.rubocop_todo.yml +21 -2
  7. data/CHANGELOG.md +50 -3
  8. data/README.md +2 -3
  9. data/docs/Configuration.md +30 -1
  10. data/docs/Creating-Models.md +128 -13
  11. data/docs/Docker.md +2 -1
  12. data/docs/Inputs.md +29 -0
  13. data/docs/Model-Notes/APC.md +72 -0
  14. data/docs/Model-Notes/ExaLink.md +43 -0
  15. data/docs/Model-Notes/Fortinet.md +75 -0
  16. data/docs/Model-Notes/IvantiConnectSecure.md +59 -0
  17. data/docs/Model-Notes/TrueNAS.md +19 -0
  18. data/docs/ModelUnitTests.md +23 -0
  19. data/docs/Outputs.md +18 -4
  20. data/docs/Release.md +1 -1
  21. data/docs/Ruby-API.md +86 -5
  22. data/docs/Supported-OS-Types.md +20 -9
  23. data/docs/Troubleshooting.md +1 -1
  24. data/extra/device2yaml.rb +2 -3
  25. data/extra/hooks/modelrules.rb +55 -0
  26. data/extra/hooks/modelrulesadvanced.rb +168 -0
  27. data/extra/hooks/srcipmap.rb +54 -0
  28. data/lib/oxidized/hook/githubrepo.rb +2 -1
  29. data/lib/oxidized/hook.rb +56 -8
  30. data/lib/oxidized/input/exec.rb +0 -4
  31. data/lib/oxidized/input/ftp.rb +0 -13
  32. data/lib/oxidized/input/http.rb +38 -13
  33. data/lib/oxidized/input/input.rb +33 -13
  34. data/lib/oxidized/input/scp.rb +10 -64
  35. data/lib/oxidized/input/ssh.rb +10 -60
  36. data/lib/oxidized/input/sshbase.rb +107 -0
  37. data/lib/oxidized/input/telnet.rb +0 -4
  38. data/lib/oxidized/input/tftp.rb +7 -3
  39. data/lib/oxidized/model/aoscx.rb +5 -3
  40. data/lib/oxidized/model/aosw.rb +10 -11
  41. data/lib/oxidized/model/apc_aos.rb +4 -0
  42. data/lib/oxidized/model/apcaos.rb +39 -0
  43. data/lib/oxidized/model/arubainstant.rb +11 -20
  44. data/lib/oxidized/model/asa.rb +7 -7
  45. data/lib/oxidized/model/comware.rb +3 -1
  46. data/lib/oxidized/model/defacto.rb +26 -0
  47. data/lib/oxidized/model/dslcommands.rb +93 -0
  48. data/lib/oxidized/model/dslsetup.rb +102 -0
  49. data/lib/oxidized/model/efos.rb +5 -5
  50. data/lib/oxidized/model/exalink.rb +36 -0
  51. data/lib/oxidized/model/fastiron.rb +2 -2
  52. data/lib/oxidized/model/firelinuxos.rb +1 -3
  53. data/lib/oxidized/model/fortigate.rb +160 -0
  54. data/lib/oxidized/model/fortios.rb +28 -69
  55. data/lib/oxidized/model/fsos.rb +1 -3
  56. data/lib/oxidized/model/h3c.rb +1 -1
  57. data/lib/oxidized/model/ios.rb +21 -15
  58. data/lib/oxidized/model/ironware.rb +5 -3
  59. data/lib/oxidized/model/ivanti.rb +54 -0
  60. data/lib/oxidized/model/macros.rb +60 -0
  61. data/lib/oxidized/model/mlnxos.rb +11 -7
  62. data/lib/oxidized/model/model.rb +28 -126
  63. data/lib/oxidized/model/ndms.rb +6 -0
  64. data/lib/oxidized/model/netgear.rb +5 -3
  65. data/lib/oxidized/model/nxos.rb +2 -2
  66. data/lib/oxidized/model/outputs.rb +5 -0
  67. data/lib/oxidized/model/perle.rb +14 -8
  68. data/lib/oxidized/model/smartbyte.rb +48 -0
  69. data/lib/oxidized/model/truenas.rb +10 -1
  70. data/lib/oxidized/model/voss.rb +3 -0
  71. data/lib/oxidized/model/vyos.rb +3 -1
  72. data/lib/oxidized/node.rb +25 -23
  73. data/lib/oxidized/nodes.rb +2 -0
  74. data/lib/oxidized/output/file.rb +7 -1
  75. data/lib/oxidized/output/git.rb +11 -1
  76. data/lib/oxidized/output/gitcrypt.rb +1 -1
  77. data/lib/oxidized/output/http.rb +12 -3
  78. data/lib/oxidized/source/csv.rb +5 -0
  79. data/lib/oxidized/source/jsonfile.rb +5 -0
  80. data/lib/oxidized/source/sql.rb +5 -0
  81. data/lib/oxidized/version.rb +2 -2
  82. data/lib/oxidized/worker.rb +36 -15
  83. data/lib/refinements.rb +18 -0
  84. data/oxidized.gemspec +28 -24
  85. metadata +98 -55
  86. data/docs/Model-Notes/APC_AOS.md +0 -65
  87. data/docs/Model-Notes/FortiOS.md +0 -44
@@ -1,5 +1,8 @@
1
1
  require 'strscan'
2
2
  require_relative 'outputs'
3
+ require_relative 'dslsetup'
4
+ require_relative 'dslcommands'
5
+ require_relative 'macros'
3
6
 
4
7
  module Oxidized
5
8
  class Model
@@ -7,6 +10,11 @@ module Oxidized
7
10
 
8
11
  using Refinements
9
12
 
13
+ # Domain Specific Language for models
14
+ extend Oxidized::Model::DSLSetup
15
+ extend Oxidized::Model::DSLCommands
16
+ extend Oxidized::Model::Macros
17
+
10
18
  include Oxidized::Config::Vars
11
19
 
12
20
  # rubocop:disable Style/FormatStringToken
@@ -25,6 +33,8 @@ module Oxidized
25
33
  klass.instance_variable_set '@comment', nil
26
34
  klass.instance_variable_set '@prompt', nil
27
35
  klass.instance_variable_set '@metadata', {}
36
+ klass.instance_variable_set '@inputs', nil
37
+
28
38
  else # we're subclassing some existing model, take its variables
29
39
  instance_variables.each do |var|
30
40
  iv = instance_variable_get(var)
@@ -33,136 +43,20 @@ module Oxidized
33
43
  end
34
44
  end
35
45
  end
36
-
37
- def comment(str = "# ")
38
- @comment = if block_given?
39
- yield
40
- elsif not @comment
41
- str
42
- else
43
- @comment
44
- end
45
- end
46
-
47
- def prompt(regex = nil)
48
- @prompt = regex || @prompt
49
- end
50
-
51
- def cfg(*methods, **args, &block)
52
- [methods].flatten.each do |method|
53
- process_args_block(@cfg[method.to_s], args, block)
54
- end
55
- end
56
-
57
- def cfgs
58
- @cfg
59
- end
60
-
61
- def cmd(cmd_arg = nil, **args, &block)
62
- if cmd_arg.instance_of?(Symbol)
63
- process_args_block(@cmd[cmd_arg], args, block)
64
- else
65
- # Normal command
66
- process_args_block(@cmd[:cmd], args,
67
- { cmd: cmd_arg, args: args, block: block })
68
- end
69
- logger.debug "Added #{cmd_arg} to the commands list"
70
- end
71
-
72
- def metadata(position, value = nil, &block)
73
- return unless %i[top bottom].include? position
74
-
75
- if block_given?
76
- @metadata[position] = block
77
- else
78
- @metadata[position] = value
79
- end
80
- end
81
-
82
- def cmds
83
- @cmd
84
- end
85
-
86
- def expect(regex, **args, &block)
87
- process_args_block(@expect, args, [regex, block])
88
- end
89
-
90
- def expects
91
- @expect
92
- end
93
-
94
- def clean(what)
95
- case what
96
- when :escape_codes
97
- ansi_escape_regex = /
98
- \r? # Optional carriage return at start
99
- \e # ESC character - starts escape sequence
100
- (?: # Non-capturing group for different sequence types:
101
- # Type 1: CSI (Control Sequence Introducer)
102
- \[ # Literal '[' - starts CSI sequence
103
- [0-?]* # Parameter bytes: digits (0-9), semicolon, colon, etc.
104
- [ -\/]* # Intermediate bytes: space through slash characters
105
- [@-~] # Final byte: determines the actual command
106
- | # OR
107
- # Type 2: Simple escape
108
- [=>] # Single character commands after ESC
109
- )
110
- \r? # Optional carriage return at end
111
- /x
112
- expect ansi_escape_regex do |data, re|
113
- data.gsub re, ''
114
- end
115
- end
116
- end
117
-
118
- # calls the block at the end of the model, prepending the output of the
119
- # block to the output string
120
- #
121
- # @yield expects block which should return [String]
122
- # @return [void]
123
- def pre(**args, &block)
124
- process_args_block(@procs[:pre], args, block)
125
- end
126
-
127
- # calls the block at the end of the model, adding the output of the block
128
- # to the output string
129
- #
130
- # @yield expects block which should return [String]
131
- # @return [void]
132
- def post(**args, &block)
133
- process_args_block(@procs[:post], args, block)
134
- end
135
-
136
- # @author Saku Ytti <saku@ytti.fi>
137
- # @since 0.0.39
138
- # @return [Hash] hash proc procs :pre+:post to be prepended/postfixed to output
139
- attr_reader :procs
140
-
141
- private
142
-
143
- def process_args_block(target, args, block)
144
- if args[:clear]
145
- if block.instance_of?(Array)
146
- target.reject! { |k, _| k == block[0] }
147
- target.push(block)
148
- elsif block.instance_of?(Hash)
149
- target.reject! { |item| item[:cmd] == block[:cmd] }
150
- target.push(block)
151
- else
152
- target.replace([block])
153
- end
154
- else
155
- method = args[:prepend] ? :unshift : :push
156
- target.send(method, block)
157
- end
158
- end
159
46
  end
160
47
 
161
48
  attr_accessor :input, :node
162
49
 
163
- def cmd(string, &block)
50
+ # input specifies to run this command only with this input type
51
+ # if input is not specified, always run the command
52
+ def cmd(string, input: nil, &block)
164
53
  logger.debug "Executing #{string}"
165
- out = @input.cmd(string)
54
+ out = if input.nil? || input.include?(@input.to_sym)
55
+ out = @input.cmd(string)
56
+ else
57
+ # Do not run this command
58
+ return ''
59
+ end
166
60
  return false unless out
167
61
 
168
62
  out = out.b unless Oxidized.config.input.utf8_encoded?
@@ -245,6 +139,7 @@ module Oxidized
245
139
  data
246
140
  end
247
141
 
142
+ # Get the commands from the model
248
143
  def get
249
144
  logger.debug 'Collecting commands\' outputs'
250
145
  outputs = Outputs.new
@@ -255,7 +150,7 @@ module Oxidized
255
150
 
256
151
  next if args.include?(:if) && !instance_exec(&args[:if])
257
152
 
258
- out = cmd command, &block
153
+ out = cmd command, input: args[:input], &block
259
154
  return false unless out
260
155
 
261
156
  outputs << out
@@ -306,6 +201,13 @@ module Oxidized
306
201
  @input.class.to_s.match(/Telnet/) || vars(:ssh_no_exec)
307
202
  end
308
203
 
204
+ def significant_changes(config)
205
+ self.class.cmds[:significant_changes].each do |block|
206
+ config = instance_exec config, &block
207
+ end
208
+ config
209
+ end
210
+
309
211
  private
310
212
 
311
213
  def process_cmd_output(output, name)
@@ -22,4 +22,10 @@ class NDMS < Oxidized::Model
22
22
  password /^Password:/
23
23
  pre_logout 'exit'
24
24
  end
25
+
26
+ cmd :significant_changes do |cfg|
27
+ cfg.reject_lines [
28
+ 'Last change:'
29
+ ]
30
+ end
25
31
  end
@@ -6,7 +6,7 @@ class Netgear < Oxidized::Model
6
6
  clean :escape_codes
7
7
 
8
8
  # Handle pager for "show version" on old Netgear models: #2394
9
- expect /^--More-- or \(q\)uit$/ do |data, re|
9
+ expect /^--More--(?: or \(q\)uit)?$/ do |data, re|
10
10
  send ' '
11
11
  data.sub re, ''
12
12
  end
@@ -20,7 +20,7 @@ class Netgear < Oxidized::Model
20
20
  end
21
21
 
22
22
  cfg :telnet do
23
- username /^(User:|Applying Interface configuration, please wait ...)/
23
+ username /^(Username:|User:|Applying Interface configuration, please wait ...)/
24
24
  password /^Password:/i
25
25
  end
26
26
 
@@ -58,9 +58,11 @@ class Netgear < Oxidized::Model
58
58
  comment cfg
59
59
  end
60
60
  cmd 'show running-config' do |cfg|
61
- cfg.gsub! /(System Up Time\s+).*/, '\\1 <removed>'
61
+ cfg.gsub! /(System Up Time:?\s+).*/, '\\1 <removed>'
62
62
  cfg.gsub! /(Current SNTP Synchronized Time:).*/, '\\1 <removed>'
63
63
  cfg.gsub! /(Current System Time:).*/, '\\1 <removed>'
64
+ # Remove standalone backspace lines
65
+ cfg.gsub!(/(?:\r?\n)?\x08(?:\r?\n)?/, "\n")
64
66
  cfg
65
67
  end
66
68
  end
@@ -25,8 +25,8 @@ class NXOS < Oxidized::Model
25
25
  end
26
26
 
27
27
  cmd 'show inventory all' do |cfg|
28
- if cfg.include? "% Invalid parameter detected at '^' marker."
29
- # 'show inventory all' isn't supported on older versions (See Issue #3657)
28
+ if cfg.match? /^% Invalid .* at '\^' marker\./
29
+ # 'show inventory all' isn't supported on older versions (See Issues #3657, #3779)
30
30
  cfg = cmd 'show inventory'
31
31
  end
32
32
  comment cfg
@@ -31,6 +31,11 @@ module Oxidized
31
31
  @outputs.map { |out| out.type }.uniq.compact
32
32
  end
33
33
 
34
+ def merge!(other)
35
+ other.all.each { |o| @outputs << o }
36
+ self
37
+ end
38
+
34
39
  private
35
40
 
36
41
  def initialize
@@ -5,7 +5,8 @@ class Perle < Oxidized::Model
5
5
  comment '! '
6
6
 
7
7
  cmd :all do |cfg|
8
- cfg.cut_both
8
+ cfg = cfg.cut_both
9
+ cfg.delete "\r"
9
10
  end
10
11
 
11
12
  cmd 'show version verbose' do |cfg|
@@ -17,17 +18,22 @@ class Perle < Oxidized::Model
17
18
  end
18
19
 
19
20
  cmd 'show interfaces transceiver' do |cfg|
20
- out = []
21
- cfg.each_line do |line|
22
- out << line if line =~ /SFP Information/
23
- out << line if line =~ /Vendor Name/
24
- out << line if line =~ /Vendor Serial Number/
25
- end
26
- comment out.join + "\n"
21
+ cfg = cfg.keep_lines [
22
+ 'SFP Information',
23
+ 'Vendor Name',
24
+ 'Vendor Serial Number'
25
+ ]
26
+ comment cfg + "\n"
27
27
  end
28
28
 
29
29
  cmd 'show running-config'
30
30
 
31
+ cmd :significant_changes do |cfg|
32
+ cfg.reject_lines [
33
+ /^tacacs-server key 7 \$0\$\S+==$/
34
+ ]
35
+ end
36
+
31
37
  cfg :ssh do
32
38
  post_login 'terminal length 0'
33
39
  pre_logout 'exit'
@@ -0,0 +1,48 @@
1
+ class SmartByte < Oxidized::Model
2
+ using Refinements
3
+
4
+ comment '! '
5
+
6
+ cmd :secret do |cfg|
7
+ cfg.gsub!(/group (\S+) v2c/, 'group <hidden> v2c')
8
+ cfg.gsub!(/community (\S+)/, 'community <hidden>')
9
+ cfg
10
+ end
11
+
12
+ cmd :all do |cfg|
13
+ cfg = cfg.delete("\r")
14
+ cfg.cut_tail
15
+ end
16
+
17
+ cmd 'show running-config'
18
+
19
+ cmd 'show version' do |cfg|
20
+ comment cfg
21
+ end
22
+
23
+ cmd 'show interface optical-transceiver info' do |cfg|
24
+ cfg.gsub! /^\|Transceiver current alarm information: \|\s+\+-------------------------------------------------\+.*?\s+\+-------------------------------------------------\+\s+/m, ''
25
+ comment cfg
26
+ end
27
+
28
+ cmd 'show power' do |cfg|
29
+ comment cfg
30
+ end
31
+
32
+ cfg :telnet do
33
+ username /^.*? login:/
34
+ password /^Password:/
35
+ end
36
+
37
+ cfg :telnet, :ssh do
38
+ post_login do
39
+ if vars(:enable)
40
+ cmd "enable", /^[pP]assword:/
41
+ cmd vars(:enable)
42
+ end
43
+ end
44
+
45
+ post_login 'terminal length 0'
46
+ pre_logout 'exit'
47
+ end
48
+ end
@@ -5,7 +5,16 @@ class TrueNAS < Oxidized::Model
5
5
 
6
6
  cmd('uname -a') { |cfg| comment cfg }
7
7
  cmd('cat /etc/version') { |cfg| comment cfg }
8
- cmd('sqlite3 "file:///data/freenas-v1.db?mode=ro&immutable=1" .dump') do |cfg|
8
+
9
+ # for TrueNAS SCALE machines, make sure the user you use to connect can run
10
+ # this command, or if needed, with passwordless sudo. Try putting this in
11
+ # /etc/sudoers
12
+ # oxidized ALL=(ALL) NOPASSWD: /usr/bin/sqlite3 file\:///data/freenas-v1.db?mode\=ro&immutable\=1 .dump
13
+
14
+ cmd("sqlite3 'file:///data/freenas-v1.db?mode=ro&immutable=1' .dump") do |cfg|
15
+ if cfg.include? "Error: unable to open database"
16
+ cfg = cmd("sudo sqlite3 'file:///data/freenas-v1.db?mode=ro&immutable=1' .dump")
17
+ end
9
18
  cfg.lines.reject do |line|
10
19
  line.match(/^INSERT INTO storage_replication /) ||
11
20
  line.match(/^INSERT INTO system_alert /) || # ignore system alerts in db
@@ -23,6 +23,9 @@ class Voss < Oxidized::Model
23
23
  cfg.gsub! /(^((.*)Last Vlan Change(.*):(.*))$)/, 'removed Last Vlan Change'
24
24
  cfg.gsub! /(^((.*)Temperature(.*):(.*))$)/, 'removed Temperature'
25
25
  cfg.gsub! /(^((.*)Total Power Usage(.*):(.*))$)/, 'removed Total Power Usage'
26
+ cfg.gsub! /(^((.*)(Tray \d+ Fan \d+)\s+(\w+)\s+(\w+)\s+(.*))$)/, '\3\4 \5 [removed RPM values]'
27
+ cfg.gsub! /(^((.*)Command Execution Time: (.*))$)/, 'Command Execution Time [removed]'
28
+ cfg.gsub! /(^((.*)(Ambient\s+\d+|CPU|INTERNAL\s+MAC|SODIMM)\s+\d+\s+\d+(.*))$)/, '\3\4 [removed temperature readings]'
26
29
  comment "#{cfg}\n"
27
30
  end
28
31
 
@@ -15,8 +15,10 @@ class Vyos < Oxidized::Model
15
15
  cmd :secret do |cfg|
16
16
  cfg.gsub! /secret (\S+).*/, 'secret <secret removed>'
17
17
  cfg.gsub! /password (\S+).*/, 'password <secret removed>'
18
- cfg.gsub! /community (\S+)/, 'community <secret removed>'
18
+ cfg.gsub! /snmp community (\S+)/, 'snmp community <secret removed>'
19
+ cfg.gsub! /preshared-key (\S+).*/, 'preshared-key <secret removed>'
19
20
  cfg.gsub! /private key (\S+).*/, 'private key <secret removed>'
21
+ cfg.gsub! /private-key (\S+).*/, 'private-key <secret removed>'
20
22
  # password in URLs like protocol://user:password@domain.tld/
21
23
  cfg.gsub! /([a-z]+:\/\/[^:\s]+:)\S+@/, '\1<secret removed>@'
22
24
  cfg
data/lib/oxidized/node.rb CHANGED
@@ -8,8 +8,9 @@ module Oxidized
8
8
  include SemanticLogger::Loggable
9
9
 
10
10
  attr_reader :name, :ip, :model, :input, :output, :group, :auth, :prompt, :timeout, :vars, :last, :repo
11
- attr_accessor :running, :user, :email, :msg, :from, :stats, :retry, :err_type, :err_reason
11
+ attr_accessor :running, :user, :email, :msg, :from, :stats, :retry, :err_type, :err_reason, :nexted
12
12
  alias running? running
13
+ alias nexted? nexted
13
14
 
14
15
  # opt is a hash with the node parameters given in the source (:name, :group, :ip...)
15
16
  def initialize(opt)
@@ -34,6 +35,7 @@ module Oxidized
34
35
  @repo = resolve_repo opt
35
36
  @err_type = nil
36
37
  @err_reason = nil
38
+ @nexted = false
37
39
 
38
40
  # model instance needs to access node instance
39
41
  @model.node = self
@@ -41,37 +43,37 @@ module Oxidized
41
43
 
42
44
  def run
43
45
  status = :fail
44
- config = nil
45
- @input.each do |input|
46
- # don't try input if model is missing config block, we may need strong config to class_name map
47
- cfg_name = input.to_s.split('::').last.downcase
48
- next unless @model.cfg[cfg_name] && (not @model.cfg[cfg_name].empty?)
49
-
50
- @model.input = input = input.new
51
- if (config = run_input(input))
52
- logger.debug "#{input.class.name} ran for #{name} successfully"
53
- status = :success
54
- break
46
+ config = Oxidized::Model::Outputs.new
47
+ input_sequence = @model.class.input_sequence(@input)
48
+
49
+ input_sequence.each do |sequence|
50
+ status = :fail
51
+ sequence_config = nil
52
+ sequence.each do |input|
53
+ @model.input = input = input.new
54
+ if (sequence_config = run_input(input))
55
+ logger.debug "#{input.class.name} ran for #{name} successfully"
56
+ status = :success
57
+ break
58
+ else
59
+ logger.debug "#{input.class.name} failed for #{name}"
60
+ status = :no_connection
61
+ end
62
+ end
63
+ if status == :success
64
+ config.merge! sequence_config
55
65
  else
56
- logger.debug "#{input.class.name} failed for #{name}"
57
- status = :no_connection
66
+ config = nil
67
+ break
58
68
  end
59
69
  end
60
- logger.error "No suitable input found for #{name}" unless @model.input
61
70
 
62
71
  @model.input = nil
63
72
  [status, config]
64
73
  end
65
74
 
66
75
  def run_input(input)
67
- rescue_fail = {}
68
- [input.class::RESCUE_FAIL, input.class.superclass::RESCUE_FAIL].each do |hash|
69
- hash.each do |level, errors|
70
- errors.each do |err|
71
- rescue_fail[err] = level
72
- end
73
- end
74
- end
76
+ rescue_fail = input.class.rescue_fail
75
77
  begin
76
78
  input.connect(self) && input.get
77
79
  rescue *rescue_fail.keys => err
@@ -88,6 +88,8 @@ module Oxidized
88
88
  n.from = opt['from']
89
89
  # set last job to nil so that the node is picked for immediate update
90
90
  n.last = nil
91
+ # set nexted to true so that the node will not be skipped with interval 0
92
+ n.nexted = true
91
93
  put n
92
94
  jobs.increment if Oxidized.config.next_adds_job?
93
95
  end
@@ -21,8 +21,14 @@ module Oxidized
21
21
 
22
22
  # node: node name (String)
23
23
  # outputs: Oxidized::Models::Outputs
24
- # opts: hash of node vars
24
+ # opts: dict of optional parameters:
25
+ # - group: node group
26
+ # - significant_changes:
27
+ # nil / not set / true -> store as usual
28
+ # false -> do not store
25
29
  def store(node, outputs, opt = {})
30
+ return false if opt[:significant_changes] == false
31
+
26
32
  file = ::File.expand_path @cfg.directory
27
33
  file = ::File.join ::File.dirname(file), opt[:group] if opt[:group]
28
34
  FileUtils.mkdir_p file
@@ -35,6 +35,16 @@ module Oxidized
35
35
  end
36
36
  end
37
37
 
38
+ # file: node name (String)
39
+ # outputs: Oxidized::Models::Outputs
40
+ # opts: dict of optional parameters:
41
+ # - msg: commit message
42
+ # - email: committer email
43
+ # - user: committer name
44
+ # - group: node group
45
+ # - significant_changes:
46
+ # nil / not set / true: store as usual
47
+ # false: skip general config, only store configs where type != nil
38
48
  def store(file, outputs, opt = {})
39
49
  @msg = opt[:msg]
40
50
  @user = opt[:user] || @cfg.user
@@ -58,7 +68,7 @@ module Oxidized
58
68
  update type_repo, file, type_cfg
59
69
  end
60
70
 
61
- update repo, file, outputs.to_cfg
71
+ update repo, file, outputs.to_cfg unless opt[:significant_changes] == false
62
72
  end
63
73
 
64
74
  # Returns the configuration of group/node_name
@@ -86,7 +86,7 @@ module Oxidized
86
86
  update type_repo, file, type_cfg
87
87
  end
88
88
 
89
- update repo, file, outputs.to_cfg
89
+ update repo, file, outputs.to_cfg unless opt[:significant_changes] == false
90
90
  end
91
91
 
92
92
  def fetch(node, group)
@@ -26,9 +26,18 @@ module Oxidized
26
26
  @commitref = nil
27
27
  uri = URI.parse @cfg.url
28
28
  http = Net::HTTP.new uri.host, uri.port
29
- # http.use_ssl = true if uri.scheme = 'https'
30
- req = Net::HTTP::Post.new(uri.request_uri, 'Content-Type' => 'application/json')
31
- req.basic_auth @cfg.user, @cfg.password
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
35
+
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
+
32
41
  req.body = generate_json(node, outputs, opt)
33
42
  response = http.request req
34
43
 
@@ -47,6 +47,11 @@ module Oxidized
47
47
  end
48
48
  keys[:vars] = vars unless vars.empty?
49
49
 
50
+ keys = Oxidized.hooks.source_node_transform(node: keys,
51
+ node_raw: data,
52
+ context: self)
53
+ next if keys.nil?
54
+
50
55
  nodes << keys
51
56
  end
52
57
  nodes
@@ -54,6 +54,11 @@ module Oxidized
54
54
  end
55
55
  keys[:vars] = vars unless vars.empty?
56
56
 
57
+ keys = Oxidized.hooks.source_node_transform(node: keys,
58
+ node_raw: node,
59
+ context: self)
60
+ next if keys.nil?
61
+
57
62
  nodes << keys
58
63
  end
59
64
  nodes
@@ -46,6 +46,11 @@ module Oxidized
46
46
  end
47
47
  keys[:vars] = vars unless vars.empty?
48
48
 
49
+ keys = Oxidized.hooks.source_node_transform(node: keys,
50
+ node_raw: node.to_hash,
51
+ context: self)
52
+ next if keys.nil?
53
+
49
54
  nodes << keys
50
55
  end
51
56
  db.disconnect
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Oxidized
4
- VERSION = '0.35.0'
5
- VERSION_FULL = '0.35.0'
4
+ VERSION = '0.36.0'
5
+ VERSION_FULL = '0.36.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 ""