tiller 0.9.7 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d50bc4389c299371589ded733f06078559c91555
4
- data.tar.gz: 3f6c1c9cdb4e504f7c5bddce477b684062a3993c
3
+ metadata.gz: e44d4f088a889a8fd6d1c4f23bad614e91bfb215
4
+ data.tar.gz: b1a5e3c7a157675b36dae9fabc71e40155beed0d
5
5
  SHA512:
6
- metadata.gz: a5f706f2109f84b7a015ce5173a67ee3025dd23394b344df5bdae4968adbd037f0f1615fc8c776f8226e60abeb8f2cc8b415ce67b00b5e297c98b28a53a7d472
7
- data.tar.gz: 883ace5cc0dbc824881c129d9d62533f1e27e005fc954cbac5f41ba2a0b24cc4d69eb04602904101e492edae003021e1fa9c7404d68b5d9a2fa465984eb033a0
6
+ metadata.gz: 29465a4eb5cbea636fc6ee2a20a65230e7e33a1ed7b2d41d325800d86e621c8d9bd39c754d7ba6e1f9c5cb3eb5cb3d723d82c8575880ae8e832a53c92bce49bf
7
+ data.tar.gz: 4c79f0d2c99294fd9372f3006a949791360f79d39cec70f1b44bc01a47114bdfbbdcd8028de89e5443a513bd237f41b3614201f8d7d04db45fc59ce9fe91f944
data/bin/tiller CHANGED
@@ -26,6 +26,7 @@ require 'tiller/datasource'
26
26
  require 'tiller/logger'
27
27
  require 'digest/md5'
28
28
  require 'tiller/render'
29
+ require 'tiller/kv'
29
30
  require 'tiller/version'
30
31
 
31
32
  EXIT_SUCCESS = 0
@@ -100,6 +101,8 @@ module Tiller
100
101
  log.info('Helper modules loaded ' + helper_modules.to_s)
101
102
  end
102
103
 
104
+ log.debug("Dynamic values specified. Will parse all values as ERb.") if config.assoc('dynamic_values')
105
+
103
106
  # We now don't actually use the global_values hash for anything when constructing the templates (as they can be
104
107
  # over-ridden by template values), but it's here to keep compatibility with the v1 API.
105
108
  global_values = { 'environment' => config[:environment] }
@@ -133,6 +136,8 @@ module Tiller
133
136
  all_templates = {}
134
137
  skipped_templates = 0
135
138
  updated_templates = 0
139
+ pids = []
140
+
136
141
 
137
142
  templates.each do |template, _content|
138
143
 
@@ -163,6 +168,27 @@ module Tiller
163
168
  target_values.tiller_merge!(dc.target_values(template)) do |key, old, new|
164
169
  warn_merge(key, old, new, 'target', data_class.to_s)
165
170
  end
171
+
172
+ # Dynamic config stuff, allows us to use ERb syntax inside configuration.
173
+ if config.assoc('dynamic_values')
174
+ # Need to recursively walk the hash, looking for ERb syntax
175
+ tiller.deep_traverse do |path,value|
176
+ if value.is_a?(String) && value.include?('<%')
177
+ log.debug("Found ERb syntax for #{value} at #{path}")
178
+ parsed_value = Tiller::render(value, direct_render: true)
179
+ # Proper Ruby voodoo here.
180
+ # See http://stackoverflow.com/questions/19304135/deep-nest-a-value-into-a-hash-given-a-path-array for
181
+ # explanation.
182
+ tiller.merge!((path + [parsed_value]).reverse.reduce { |s,e| { e => s } })
183
+ end
184
+ end
185
+ target_values.each do |key ,value|
186
+ if value.is_a?(String) && value.include?('<%')
187
+ log.debug("Found ERb syntax for target value #{key}:#{value}}")
188
+ target_values[key] = Tiller::render(value, direct_render: true)
189
+ end
190
+ end
191
+ end
166
192
  end
167
193
 
168
194
  # If our data source returned no values (e.g. we don't build this template
@@ -222,6 +248,17 @@ module Tiller
222
248
  "#{target_values['target']}")
223
249
  end
224
250
 
251
+ # Exec on write
252
+ if target_values.key?('exec_on_write')
253
+ if ! target_values['exec_on_write'].is_a?(Array)
254
+ log.warn("Warning: exec_on_write for template #{template} is not in array format")
255
+ else
256
+ eow_pid=launch(target_values['exec_on_write'])
257
+ pids.push(eow_pid)
258
+ log.info("exec_on_write process for #{template} forked with PID #{eow_pid}")
259
+ end
260
+ end
261
+
225
262
  end
226
263
 
227
264
  if config['md5sum']
@@ -254,24 +291,38 @@ module Tiller
254
291
  puts "Executing #{config['exec']}..."
255
292
 
256
293
  # Spawn and wait so API can continue to run
257
- child_pid = launch(config['exec'], :verbose => config[:verbose])
294
+ child_pid = launch(config['exec'])
295
+ pids.push(child_pid)
258
296
 
259
- log.info("Child process forked with PID #{child_pid}.")
297
+ log.info("Child process forked with PID #{child_pid}")
260
298
 
261
- # Catch signals and send them on to the child process
299
+ # Catch signals and send them on to the child processes
262
300
  [ :INT, :TERM, :HUP ].each do |sig|
263
- Signal.trap(sig) { signal(sig, child_pid, :verbose => config[:verbose]) }
301
+ Signal.trap(sig) do
302
+ pids.each { |p| signal(sig, p, :verbose => config[:verbose])}
303
+ end
264
304
  end
265
305
 
266
- Process.wait(child_pid)
267
-
268
- # Capture the child process status, so we can also exit with this code
269
- exit_status = ($?.exitstatus == nil) ? 0 : $?.exitstatus
306
+ # Wait for all PIDs
307
+ main_exit_status = 0
308
+ while pids.length >= 1 do
309
+ collected_pid = Process.wait
310
+ exit_status = ($?.exitstatus == nil) ? 0 : $?.exitstatus
311
+ if collected_pid == child_pid
312
+ log.info("Main child process with PID #{collected_pid} exited with status #{exit_status}")
313
+ main_exit_status = exit_status
314
+ else
315
+ log.info("exec_on_write process with PID #{collected_pid} exited with status #{exit_status}")
316
+ end
317
+ pids.delete(collected_pid)
318
+ end
270
319
 
271
- log.info("Child process exited with status #{exit_status}")
320
+ log.info("Child process exited with status #{main_exit_status}")
272
321
  log.info('Child process finished, Tiller is stopping.')
273
322
  exit exit_status
274
323
 
275
324
  end
276
325
 
326
+
327
+
277
328
  end
@@ -2,10 +2,11 @@ require 'tiller/json'
2
2
  require 'tiller/api/handlers/404'
3
3
 
4
4
  def handle_globals(api_version, tiller_api_hash)
5
+ warning_json = { deprecation_warning: 'The v1 Tiller API is deprecated. Expect this endpoint to be removed in future versions.' }
5
6
  case api_version
6
7
  when 'v1'
7
8
  {
8
- :content => dump_json(tiller_api_hash['global_values']),
9
+ :content => dump_json(tiller_api_hash['global_values'].merge(warning_json)),
9
10
  :status => '200 OK'
10
11
  }
11
12
  else
@@ -36,7 +36,8 @@ module Tiller
36
36
  # 'target' => "/tmp/#{template_name}",
37
37
  # 'user' => 'root',
38
38
  # 'group' => 'root',
39
- # 'perms' => '0644'
39
+ # 'perms' => '0644',
40
+ # 'exec_on_write' => [ "/usr/bin/touch" , "somefile.tmp" ]
40
41
  # }
41
42
  # Again, we should always return a hash; if we have no data for the given
42
43
  # template, just return an empty hash.
data/lib/tiller/kv.rb ADDED
@@ -0,0 +1,26 @@
1
+ module Tiller
2
+
3
+ # Simple KV implementation to facilitate passing 'private' data between datasources and helpers
4
+
5
+ class Kv
6
+ @@kv = {}
7
+
8
+ def self.set(path, value, options={})
9
+ ns = options[:namespace] || 'tiller'
10
+ hash = path.sub(/^\//, '').split('/').reverse.inject(value) { |h, s| {s => h} }
11
+ Tiller::log.debug("#{self} : Setting [#{ns}]#{path} = #{value}")
12
+ @@kv[ns]=hash
13
+ end
14
+
15
+ def self.get(path, options={})
16
+ ns = options[:namespace] || 'tiller'
17
+ value = path.sub(/^\//, '').split('/').inject(@@kv[ns]) { |h,v| h[v] }
18
+ if value == nil
19
+ Tiller::log.warn("#{self} : Request for non-existent key [#{ns}]#{path}")
20
+ end
21
+ value
22
+ end
23
+
24
+ end
25
+ end
26
+
data/lib/tiller/logger.rb CHANGED
@@ -26,6 +26,12 @@ module Tiller
26
26
  self.messages.push(msg)
27
27
  end
28
28
 
29
+ # Quick hack to remove duplicate informational messages
30
+ def debug(msg)
31
+ super(msg) unless self.messages.include?(msg)
32
+ self.messages.push(msg)
33
+ end
34
+
29
35
  end
30
36
 
31
37
  end
data/lib/tiller/render.rb CHANGED
@@ -1,5 +1,13 @@
1
1
  module Tiller
2
- def self.render(template)
2
+ def self.render(template, options={})
3
+
4
+ # This is used for rendering content in dynamic configuration files
5
+ if options.has_key?(:direct_render)
6
+ content = template
7
+ ns = OpenStruct.new(Tiller::tiller)
8
+ return ERB.new(content, nil, '-').result(ns.instance_eval { binding })
9
+ end
10
+
3
11
  if Tiller::templates.key?(template)
4
12
  content = Tiller::templates[template]
5
13
  ns = OpenStruct.new(Tiller::tiller)
data/lib/tiller/util.rb CHANGED
@@ -13,6 +13,19 @@ class ::Hash
13
13
  merger = proc { |_key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
14
14
  self.merge!(second, &merger)
15
15
  end
16
+
17
+ # https://gist.github.com/sepastian/8688143
18
+ def deep_traverse(&block)
19
+ stack = self.map{ |k,v| [ [k], v ] }
20
+ while not stack.empty?
21
+ key, value = stack.pop
22
+ yield(key, value)
23
+ if value.is_a? Hash
24
+ value.each{ |k,v| stack.push [ key.dup << k, v ] }
25
+ end
26
+ end
27
+ end
28
+
16
29
  end
17
30
 
18
31
  # This is needed so we can enumerate all the loaded plugins later
@@ -24,8 +37,8 @@ end
24
37
 
25
38
  # Warn if values are being merged
26
39
  def warn_merge(key, old, new, type, source)
27
- puts "Warning, merging duplicate #{type} values."
28
- puts "#{key} => '#{old}' being replaced by : '#{new}' from #{source}"
40
+ Tiller::log.info("Merging duplicate #{type} values")
41
+ Tiller::log.info("#{key} => '#{old}' being replaced by : '#{new}' from #{source}")
29
42
  new
30
43
  end
31
44
 
@@ -39,8 +52,8 @@ def signal(sig, pid, options={})
39
52
  end
40
53
  end
41
54
 
42
- # Launch the replacement process.
43
- def launch(cmd, _options={})
55
+ # Fork and launch a process.
56
+ def launch(cmd)
44
57
  # If an array, then we use a different form of spawn() which
45
58
  # avoids a subshell. See https://github.com/markround/tiller/issues/8
46
59
  if cmd.is_a?(Array)
@@ -1 +1,2 @@
1
- VERSION="0.9.7"
1
+ # http://semver.org/
2
+ VERSION="1.0.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tiller
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Dastmalchi-Round
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-14 00:00:00.000000000 Z
11
+ date: 2017-02-09 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A tool to create configuration files from a variety of sources, particularly
14
14
  useful for Docker containers. See https://github.com/markround/tiller for examples
@@ -44,6 +44,7 @@ files:
44
44
  - lib/tiller/defaults.rb
45
45
  - lib/tiller/http.rb
46
46
  - lib/tiller/json.rb
47
+ - lib/tiller/kv.rb
47
48
  - lib/tiller/loader.rb
48
49
  - lib/tiller/logger.rb
49
50
  - lib/tiller/options.rb