template_configurator 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +674 -0
- data/README.md +60 -0
- data/Rakefile +2 -0
- data/bin/template_configurator +31 -0
- data/lib/template_configurator/command_line.rb +191 -0
- data/lib/template_configurator/processor.rb +108 -0
- data/lib/template_configurator/service.rb +115 -0
- data/lib/template_configurator/version.rb +24 -0
- data/lib/template_configurator.rb +37 -0
- data/template_configurator.gemspec +18 -0
- data/test/test.cfg +2 -0
- data/test/test.cfg.erb +2 -0
- data/test/test.js +1 -0
- metadata +92 -0
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Template Configurator
|
2
|
+
|
3
|
+
Template Configurator is a utility to write configuration files from ERB templates. When the file's content changes, it can then call an init script to intelligently reload the configuration. Through out the entire process exclusive file locks are used on the output file and json file to help ensure they are unmanipulated during the transformation process.
|
4
|
+
|
5
|
+
## Use Cases
|
6
|
+
|
7
|
+
* Dynamically configure HAProxy to pick up new backends contained in a JSON file. Call "service haproxy reload" when the configuration changes.
|
8
|
+
* Dynamically configure NGinx to pick up new backends contained in a JSON file. Call "service nginx reload" when the configuration changes.
|
9
|
+
* Dynamically configure Varnish to pick up new backends contained in a JSON file. Call "service varnish reload" when the configuration changes.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'template_configurator'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install template_configurator
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
Usage: bin/template_configurator
|
28
|
+
--service:command EXECUTABLE action to execute to command service (default: /sbin/service)
|
29
|
+
--service:name INITRC initrc used to control service (default: )
|
30
|
+
--service:status ACTION action to execute to get status of service (default: status)
|
31
|
+
--service:reload ACTION action to execute to reload service (default: reload)
|
32
|
+
--service:restart ACTION action to execute to restart service (default: restart)
|
33
|
+
--service:start ACTION action to execute to start service (default: start)
|
34
|
+
--service:stop ACTION action to execute to stop service (default: stop)
|
35
|
+
--service:retries NUMBER number of attempts to reload service (default: 5)
|
36
|
+
--service:retry-delay SECS seconds to sleep between retries (default: 2)
|
37
|
+
--template:input-file FILE Where to read ERB template
|
38
|
+
--template:output-file FILE Where to write the output of the template
|
39
|
+
--template:json-file FILE Base port to initialize haproxy listening for mysql clusters
|
40
|
+
--log:level LEVEL Logging level
|
41
|
+
--log:file FILE Write logs to FILE (default: STDERR)
|
42
|
+
--log:age DAYS Rotate logs after DAYS pass (default: 7)
|
43
|
+
--log:size SIZE Rotate logs after the grow past SIZE bytes
|
44
|
+
--dry-run Dry run (do not commit changes to disk)
|
45
|
+
-V, --version Display version information
|
46
|
+
-h, --help Display this screen
|
47
|
+
|
48
|
+
## Examples
|
49
|
+
|
50
|
+
Generate a new configuration file in /tmp/test.cfg using /tmp/test.cfg.erb using JSON data from /tmp/test.js. Reload "test" service when configuration changes.
|
51
|
+
|
52
|
+
template_configurator --template:input-file "/tmp/test.cfg.erb" --template:output-file "/tmp/test.cfg" --template:json-file "/tmp/test.js" --service:name "test"
|
53
|
+
|
54
|
+
## Contributing
|
55
|
+
|
56
|
+
1. Fork it
|
57
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
58
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
59
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
60
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Template Configurator - A utility to generate configuration files from ERB templates and restart
|
4
|
+
# services when configuration changes.
|
5
|
+
#
|
6
|
+
# Copyright (C) 2012 Erik Osterman <e@osterman.com>
|
7
|
+
#
|
8
|
+
# This file is part of Template Configurator.
|
9
|
+
#
|
10
|
+
# Template Configurator is free software: you can redistribute it and/or modify
|
11
|
+
# it under the terms of the GNU General Public License as published by
|
12
|
+
# the Free Software Foundation, either version 3 of the License, or
|
13
|
+
# (at your option) any later version.
|
14
|
+
#
|
15
|
+
# Template Configurator is distributed in the hope that it will be useful,
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
18
|
+
# GNU General Public License for more details.
|
19
|
+
#
|
20
|
+
# You should have received a copy of the GNU General Public License
|
21
|
+
# along with Template Configurator. If not, see <http://www.gnu.org/licenses/>.
|
22
|
+
#
|
23
|
+
|
24
|
+
$:.unshift(File.expand_path('.')) # Ruby 1.9 doesn't have . in the load path...
|
25
|
+
$:.push(File.expand_path('lib/'))
|
26
|
+
|
27
|
+
require 'rubygems'
|
28
|
+
require 'template_configurator'
|
29
|
+
|
30
|
+
command_line = TemplateConfigurator::CommandLine.new
|
31
|
+
command_line.execute
|
@@ -0,0 +1,191 @@
|
|
1
|
+
#
|
2
|
+
# Template Configurator - A utility to generate configuration files from ERB templates and restart
|
3
|
+
# services when configuration changes.
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012 Erik Osterman <e@osterman.com>
|
6
|
+
#
|
7
|
+
# This file is part of Template Configurator.
|
8
|
+
#
|
9
|
+
# Template Configurator is free software: you can redistribute it and/or modify
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
11
|
+
# the Free Software Foundation, either version 3 of the License, or
|
12
|
+
# (at your option) any later version.
|
13
|
+
#
|
14
|
+
# Template Configurator is distributed in the hope that it will be useful,
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17
|
+
# GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License
|
20
|
+
# along with Template Configurator. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
#
|
22
|
+
require 'optparse'
|
23
|
+
require 'logger'
|
24
|
+
|
25
|
+
module TemplateConfigurator
|
26
|
+
class CommandLine
|
27
|
+
def initialize
|
28
|
+
@logger = Logger.new STDERR
|
29
|
+
|
30
|
+
@options = {}
|
31
|
+
@options[:log] = {}
|
32
|
+
@options[:template] = {}
|
33
|
+
@options[:service] = {}
|
34
|
+
|
35
|
+
args = OptionParser.new do |opts|
|
36
|
+
opts.banner = "Usage: #{$0}"
|
37
|
+
|
38
|
+
#
|
39
|
+
# Service options
|
40
|
+
#
|
41
|
+
@options[:service][:command] = '/sbin/service'
|
42
|
+
opts.on("--service:command EXECUTABLE", "action to execute to command service (default: #{@options[:service][:command]})") do |executable|
|
43
|
+
@options[:service][:command] = executable
|
44
|
+
end
|
45
|
+
|
46
|
+
@options[:service][:name] = nil
|
47
|
+
opts.on("--service:name INITRC", "initrc used to control service (default: #{@options[:service][:name]})") do |initrc|
|
48
|
+
@options[:service][:name] = initrc
|
49
|
+
end
|
50
|
+
|
51
|
+
@options[:service][:status] = 'status'
|
52
|
+
opts.on("--service:status ACTION", "action to execute to get status of service (default: #{@options[:service][:status]})") do |action|
|
53
|
+
@options[:service][:status] = action
|
54
|
+
end
|
55
|
+
|
56
|
+
@options[:service][:reload] = 'reload'
|
57
|
+
opts.on("--service:reload ACTION", "action to execute to reload service (default: #{@options[:service][:reload]})") do |action|
|
58
|
+
@options[:service][:reload] = action
|
59
|
+
end
|
60
|
+
|
61
|
+
@options[:service][:restart] = 'restart'
|
62
|
+
opts.on("--service:restart ACTION", "action to execute to restart service (default: #{@options[:service][:restart]})") do |action|
|
63
|
+
@options[:service][:restart] = action
|
64
|
+
end
|
65
|
+
|
66
|
+
@options[:service][:start] = 'start'
|
67
|
+
opts.on("--service:start ACTION", "action to execute to start service (default: #{@options[:service][:start]})") do |action|
|
68
|
+
@options[:service][:start] = action
|
69
|
+
end
|
70
|
+
|
71
|
+
@options[:service][:stop] = 'stop'
|
72
|
+
opts.on("--service:stop ACTION", "action to execute to stop service (default: #{@options[:service][:stop]})") do |action|
|
73
|
+
@options[:service][:stop] = action
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
@options[:service][:retries] = 5
|
78
|
+
opts.on("--service:retries NUMBER", "number of attempts to reload service (default: #{@options[:service][:retries]})") do |number|
|
79
|
+
@options[:service][:retries] = number.to_i
|
80
|
+
end
|
81
|
+
|
82
|
+
@options[:service][:retry_delay] = 2
|
83
|
+
opts.on("--service:retry-delay SECS", "seconds to sleep between retries (default: #{@options[:service][:retry_delay]})") do |seconds|
|
84
|
+
@options[:service][:retry_delay] = seconds.to_i
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Template options
|
89
|
+
#
|
90
|
+
|
91
|
+
@options[:template][:input_file] = nil
|
92
|
+
opts.on("--template:input-file FILE", "Where to read ERB template") do |file|
|
93
|
+
@options[:template][:input_file] = file
|
94
|
+
end
|
95
|
+
|
96
|
+
@options[:template][:output_file] = nil
|
97
|
+
opts.on("--template:output-file FILE", "Where to write the output of the template") do |file|
|
98
|
+
@options[:template][:output_file] = file
|
99
|
+
end
|
100
|
+
|
101
|
+
@options[:template][:json_file] = nil
|
102
|
+
opts.on("--template:json-file FILE", "Base port to initialize haproxy listening for mysql clusters") do |file|
|
103
|
+
@options[:template][:json_file] = file
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Logging
|
108
|
+
#
|
109
|
+
|
110
|
+
@options[:log][:level] = Logger::INFO
|
111
|
+
opts.on( '--log:level LEVEL', 'Logging level' ) do|level|
|
112
|
+
@options[:log][:level] = Logger.const_get level.upcase
|
113
|
+
end
|
114
|
+
|
115
|
+
@options[:log][:file] = STDERR
|
116
|
+
opts.on( '--log:file FILE', 'Write logs to FILE (default: STDERR)' ) do|file|
|
117
|
+
@options[:log][:file] = File.open(file, File::WRONLY | File::APPEND | File::CREAT)
|
118
|
+
end
|
119
|
+
|
120
|
+
@options[:log][:age] = 7
|
121
|
+
opts.on( '--log:age DAYS', "Rotate logs after DAYS pass (default: #{@options[:log][:age]})" ) do|days|
|
122
|
+
@options[:log][:age] = days.to_i
|
123
|
+
end
|
124
|
+
|
125
|
+
@options[:log][:size] = 1024*1024*10
|
126
|
+
opts.on( '--log:size SIZE', 'Rotate logs after the grow past SIZE bytes' ) do |size|
|
127
|
+
@options[:log][:size] = size.to_i
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
#
|
132
|
+
# General options
|
133
|
+
#
|
134
|
+
|
135
|
+
@options[:dry_run] = false
|
136
|
+
opts.on("--dry-run", "Dry run (do not commit changes to disk)") do
|
137
|
+
@options[:dry_run] = true
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
opts.on( '-V', '--version', 'Display version information' ) do
|
142
|
+
puts "Template Configurator #{TemplateConfigurator::VERSION}"
|
143
|
+
puts "Copyright (C) 2012 Erik Osterman <e@osterman.com>"
|
144
|
+
puts "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>"
|
145
|
+
puts "This is free software: you are free to change and redistribute it."
|
146
|
+
puts "There is NO WARRANTY, to the extent permitted by law."
|
147
|
+
exit
|
148
|
+
end
|
149
|
+
|
150
|
+
opts.on( '-h', '--help', 'Display this screen' ) do
|
151
|
+
puts opts
|
152
|
+
exit
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
begin
|
158
|
+
args.parse!
|
159
|
+
raise OptionParser::MissingArgument.new("--template:input-file") if @options[:template][:input_file].nil?
|
160
|
+
rescue OptionParser::MissingArgument => e
|
161
|
+
puts e.message
|
162
|
+
puts args
|
163
|
+
exit 1
|
164
|
+
rescue OptionParser::InvalidOption => e
|
165
|
+
puts e.message
|
166
|
+
puts args
|
167
|
+
exit 1
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def execute
|
172
|
+
@processor = Processor.new(@options)
|
173
|
+
TemplateConfigurator.log = Logger.new(@options[:log][:file], @options[:log][:age], @options[:log][:size])
|
174
|
+
TemplateConfigurator.log.level = @options[:log][:level]
|
175
|
+
begin
|
176
|
+
@processor.render
|
177
|
+
rescue Interrupt => e
|
178
|
+
TemplateConfigurator.log.info("Aborting")
|
179
|
+
rescue NameError, ArgumentError => e
|
180
|
+
TemplateConfigurator.log.fatal(e.message)
|
181
|
+
TemplateConfigurator.log.debug(e.backtrace.join("\n"))
|
182
|
+
exit(1)
|
183
|
+
rescue Exception => e
|
184
|
+
TemplateConfigurator.log.fatal("#{e.class}: #{e.message}")
|
185
|
+
TemplateConfigurator.log.debug(e.backtrace.join("\n"))
|
186
|
+
exit(1)
|
187
|
+
end
|
188
|
+
exit(0)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
#
|
2
|
+
# Template Configurator - A utility to generate configuration files from ERB templates and restart
|
3
|
+
# services when configuration changes.
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012 Erik Osterman <e@osterman.com>
|
6
|
+
#
|
7
|
+
# This file is part of Template Configurator.
|
8
|
+
#
|
9
|
+
# Template Configurator is free software: you can redistribute it and/or modify
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
11
|
+
# the Free Software Foundation, either version 3 of the License, or
|
12
|
+
# (at your option) any later version.
|
13
|
+
#
|
14
|
+
# Template Configurator is distributed in the hope that it will be useful,
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17
|
+
# GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License
|
20
|
+
# along with Template Configurator. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
#
|
22
|
+
require 'erb'
|
23
|
+
require 'digest/sha1'
|
24
|
+
require 'json'
|
25
|
+
|
26
|
+
module TemplateConfigurator
|
27
|
+
class Processor
|
28
|
+
attr_accessor :service, :options, :locks
|
29
|
+
|
30
|
+
def lock file
|
31
|
+
@locks[:file] = File.open(file, File::RDWR|File::CREAT, 0644)
|
32
|
+
@locks[:file].flock(File::LOCK_EX)
|
33
|
+
@locks[:file]
|
34
|
+
end
|
35
|
+
|
36
|
+
def unlock
|
37
|
+
@locks[:file].flock(File::LOCK_UN)
|
38
|
+
@locks[:file]
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(options)
|
42
|
+
@options = options
|
43
|
+
@locks = {}
|
44
|
+
@service = Service.new(@options[:service])
|
45
|
+
end
|
46
|
+
|
47
|
+
def reload
|
48
|
+
if @options[:service][:name].nil?
|
49
|
+
TemplateConfigurator.log.info("service not specified; skipping reload")
|
50
|
+
else
|
51
|
+
begin
|
52
|
+
@service.conditional_reload
|
53
|
+
rescue ServiceException => e
|
54
|
+
TemplateConfigurator.log.error(e.message)
|
55
|
+
TemplateConfigurator.log.error(e.output) unless e.output.nil?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def render
|
61
|
+
@data = {}
|
62
|
+
unless @options[:template][:json_file].nil?
|
63
|
+
json_fh = lock(@options[:template][:json_file])
|
64
|
+
@data = JSON.parse(json_fh.read)
|
65
|
+
end
|
66
|
+
TemplateConfigurator.log.debug("json:[#{@data.inspect}]")
|
67
|
+
template = ERB.new(File.read(@options[:template][:input_file]), 0, '%<>')
|
68
|
+
|
69
|
+
if @options[:template][:output_file].nil?
|
70
|
+
output_fh = STDOUT
|
71
|
+
old_output = ""
|
72
|
+
else
|
73
|
+
output_fh = lock(@options[:template][:output_file])
|
74
|
+
old_output = output_fh.read
|
75
|
+
end
|
76
|
+
|
77
|
+
new_output = template.result(binding)
|
78
|
+
|
79
|
+
new_sha1 = Digest::SHA1.hexdigest(new_output)
|
80
|
+
old_sha1 = Digest::SHA1.hexdigest(old_output)
|
81
|
+
|
82
|
+
TemplateConfigurator.log.debug("old_sha1:#{old_sha1} new_sha1:#{new_sha1}")
|
83
|
+
|
84
|
+
if new_sha1 == old_sha1
|
85
|
+
TemplateConfigurator.log.debug("SHA1 checksum unchanged")
|
86
|
+
else
|
87
|
+
TemplateConfigurator.log.info "SHA1 checksum changed"
|
88
|
+
# Write the new configuration
|
89
|
+
if @options[:dry_run]
|
90
|
+
TemplateConfigurator.log.debug("Not attemptig service reload due to dry-run")
|
91
|
+
output_fh.write new_output
|
92
|
+
elsif !@options[:template][:output_file].nil?
|
93
|
+
TemplateConfigurator.log.debug("writing new configuation (#{new_output.length} bytes)")
|
94
|
+
output_fh.rewind
|
95
|
+
output_fh.write(new_output)
|
96
|
+
output_fh.flush
|
97
|
+
output_fh.truncate(output_fh.pos)
|
98
|
+
output_fh.flush
|
99
|
+
reload()
|
100
|
+
else
|
101
|
+
TemplateConfigurator.log.debug("Not attemptig service reload due to missing output file parameter")
|
102
|
+
output_fh.write new_output
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
#
|
2
|
+
# Template Configurator - A utility to generate configuration files from ERB templates and restart
|
3
|
+
# services when configuration changes.
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012 Erik Osterman <e@osterman.com>
|
6
|
+
#
|
7
|
+
# This file is part of Template Configurator.
|
8
|
+
#
|
9
|
+
# Template Configurator is free software: you can redistribute it and/or modify
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
11
|
+
# the Free Software Foundation, either version 3 of the License, or
|
12
|
+
# (at your option) any later version.
|
13
|
+
#
|
14
|
+
# Template Configurator is distributed in the hope that it will be useful,
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17
|
+
# GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License
|
20
|
+
# along with Template Configurator. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
#
|
22
|
+
require 'shellwords'
|
23
|
+
|
24
|
+
module TemplateConfigurator
|
25
|
+
class ServiceException < Exception
|
26
|
+
attr_accessor :code, :output
|
27
|
+
def initialize(msg, code, output = nil)
|
28
|
+
@code = code
|
29
|
+
@output = output
|
30
|
+
super(msg)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Service
|
35
|
+
attr_accessor :options
|
36
|
+
def initialize options
|
37
|
+
@options = options
|
38
|
+
end
|
39
|
+
|
40
|
+
def command action
|
41
|
+
args = []
|
42
|
+
args << @options[:command]
|
43
|
+
args << @options[:name]
|
44
|
+
args << action
|
45
|
+
TemplateConfigurator.log.debug("command args: #{args.inspect}")
|
46
|
+
Shellwords.join(args)
|
47
|
+
end
|
48
|
+
|
49
|
+
def execute command
|
50
|
+
TemplateConfigurator.log.debug("command: #{command}")
|
51
|
+
begin
|
52
|
+
output = %x{#{command}}
|
53
|
+
exit_code = $?.exitstatus
|
54
|
+
raise ServiceException.new("execution failed; #{command} exited with status #{exit_code}", exit_code, output) unless exit_code == 0
|
55
|
+
rescue Errno::ENOENT => e
|
56
|
+
raise ServiceException.new(e.message, 1)
|
57
|
+
end
|
58
|
+
return output
|
59
|
+
end
|
60
|
+
|
61
|
+
def status
|
62
|
+
execute command(@options[:status])
|
63
|
+
end
|
64
|
+
|
65
|
+
def restart
|
66
|
+
execute command(@options[:restart])
|
67
|
+
end
|
68
|
+
|
69
|
+
def reload
|
70
|
+
execute command(@options[:reload])
|
71
|
+
end
|
72
|
+
|
73
|
+
def start
|
74
|
+
execute command(@options[:start])
|
75
|
+
end
|
76
|
+
|
77
|
+
def stop
|
78
|
+
execute command(@options[:stop])
|
79
|
+
end
|
80
|
+
|
81
|
+
def conditional_reload
|
82
|
+
# Attempt to reload service if it's running, otherwise start it.
|
83
|
+
@options[:retries].times do
|
84
|
+
begin
|
85
|
+
status_output = self.status
|
86
|
+
TemplateConfigurator.log.debug("#{@options[:name]} is running")
|
87
|
+
# If the configuration has changed, reload config
|
88
|
+
begin
|
89
|
+
reload_output = self.reload
|
90
|
+
TemplateConfigurator.log.debug("Reload command succeeded")
|
91
|
+
return reload_output
|
92
|
+
rescue ServiceException => e
|
93
|
+
TemplateConfigurator.log.error(e.message)
|
94
|
+
TemplateConfigurator.log.error(e.output) unless e.output.nil?
|
95
|
+
end
|
96
|
+
rescue ServiceException => e
|
97
|
+
# service is not running
|
98
|
+
TemplateConfigurator.log.error(e.message)
|
99
|
+
TemplateConfigurator.log.error(e.output) unless e.output.nil?
|
100
|
+
begin
|
101
|
+
start_output = self.start
|
102
|
+
TemplateConfigurator.log.debug("Start command succeeded")
|
103
|
+
return start_output
|
104
|
+
rescue ServiceException => e
|
105
|
+
TemplateConfigurator.log.error(e.message)
|
106
|
+
TemplateConfigurator.log.error(e.output) unless e.output.nil?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
sleep(@options[:retry_delay])
|
110
|
+
end
|
111
|
+
# Everything else failed. Try a restart
|
112
|
+
return self.restart
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#
|
2
|
+
# Template Configurator - A utility to generate configuration files from ERB templates and restart
|
3
|
+
# services when configuration changes.
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012 Erik Osterman <e@osterman.com>
|
6
|
+
#
|
7
|
+
# This file is part of Template Configurator.
|
8
|
+
#
|
9
|
+
# Template Configurator is free software: you can redistribute it and/or modify
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
11
|
+
# the Free Software Foundation, either version 3 of the License, or
|
12
|
+
# (at your option) any later version.
|
13
|
+
#
|
14
|
+
# Template Configurator is distributed in the hope that it will be useful,
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17
|
+
# GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License
|
20
|
+
# along with Template Configurator. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
#
|
22
|
+
module TemplateConfigurator
|
23
|
+
VERSION = "1.0.0"
|
24
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# Template Configurator - A utility to generate configuration files from ERB templates and restart
|
3
|
+
# services when configuration changes.
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012 Erik Osterman <e@osterman.com>
|
6
|
+
#
|
7
|
+
# This file is part of Template Configurator.
|
8
|
+
#
|
9
|
+
# Template Configurator is free software: you can redistribute it and/or modify
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
11
|
+
# the Free Software Foundation, either version 3 of the License, or
|
12
|
+
# (at your option) any later version.
|
13
|
+
#
|
14
|
+
# Template Configurator is distributed in the hope that it will be useful,
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17
|
+
# GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License
|
20
|
+
# along with Template Configurator. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
#
|
22
|
+
require "template_configurator/version"
|
23
|
+
require 'template_configurator/service'
|
24
|
+
require 'template_configurator/processor'
|
25
|
+
require 'template_configurator/command_line'
|
26
|
+
|
27
|
+
module TemplateConfigurator
|
28
|
+
@@logger = nil
|
29
|
+
|
30
|
+
def self.log=(logger)
|
31
|
+
@@logger=logger
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.log
|
35
|
+
@@logger
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/template_configurator/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Erik Osterman"]
|
6
|
+
gem.email = ["e@osterman.com"]
|
7
|
+
gem.summary = %q{Template Configurator is a utility to write configuration files from ERB templates.}
|
8
|
+
gem.description = %q{Template Configurator is a utility to write configuration files from ERB templates. When the file's content changes, it can then call an init script to intelligently reload the configuration. Through out the entire process exclusive file locks are used on the output file and json file to help ensure they are unmanipulated during the transformation process.}
|
9
|
+
gem.homepage = "https://github.com/osterman/template_configurator"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "template_configurator"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = TemplateConfigurator::VERSION
|
17
|
+
gem.add_runtime_dependency 'json', '>= 1.4.3'
|
18
|
+
end
|
data/test/test.cfg
ADDED
data/test/test.cfg.erb
ADDED
data/test/test.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{ "key1":"value1", "key2":"value2" }
|