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 +4 -4
- data/bin/tiller +60 -9
- data/lib/tiller/api/handlers/globals.rb +2 -1
- data/lib/tiller/datasource.rb +2 -1
- data/lib/tiller/kv.rb +26 -0
- data/lib/tiller/logger.rb +6 -0
- data/lib/tiller/render.rb +9 -1
- data/lib/tiller/util.rb +17 -4
- data/lib/tiller/version.rb +2 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e44d4f088a889a8fd6d1c4f23bad614e91bfb215
|
4
|
+
data.tar.gz: b1a5e3c7a157675b36dae9fabc71e40155beed0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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']
|
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
|
299
|
+
# Catch signals and send them on to the child processes
|
262
300
|
[ :INT, :TERM, :HUP ].each do |sig|
|
263
|
-
Signal.trap(sig)
|
301
|
+
Signal.trap(sig) do
|
302
|
+
pids.each { |p| signal(sig, p, :verbose => config[:verbose])}
|
303
|
+
end
|
264
304
|
end
|
265
305
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
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 #{
|
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
|
data/lib/tiller/datasource.rb
CHANGED
@@ -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
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
|
-
|
28
|
-
|
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
|
-
#
|
43
|
-
def launch(cmd
|
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)
|
data/lib/tiller/version.rb
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
|
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.
|
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:
|
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
|