upstart-exporter 1.0.1 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +2 -4
- data/README.md +82 -16
- data/lib/upstart-exporter/errors.rb +1 -1
- data/lib/upstart-exporter/expanded_exporter.rb +107 -0
- data/lib/upstart-exporter/exporter_helpers.rb +26 -0
- data/lib/upstart-exporter/options/command_line.rb +8 -2
- data/lib/upstart-exporter/options/global.rb +3 -1
- data/lib/upstart-exporter/templates.rb +14 -4
- data/lib/upstart-exporter/version.rb +1 -1
- data/lib/upstart-exporter.rb +44 -33
- data/spec/lib/upstart-exporter/errors_spec.rb +0 -1
- data/spec/lib/upstart-exporter/expanded_exporter_spec.rb +59 -0
- data/spec/lib/upstart-exporter/options/command_line_spec.rb +16 -6
- data/spec/lib/upstart-exporter/options/global_spec.rb +2 -2
- data/spec/lib/upstart-exporter/templates_spec.rb +23 -5
- data/spec/lib/upstart-exporter_spec.rb +19 -6
- data/upstart-exporter.gemspec +4 -5
- metadata +17 -8
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.8.7-p352
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem for exporting user-scripts as Upstart scripts
|
2
2
|
====================
|
3
3
|
|
4
|
-
[![Build Status](https://secure.travis-ci.org/
|
4
|
+
[![Build Status](https://secure.travis-ci.org/funbox/upstart-exporter.png)](http://travis-ci.org/funbox/upstart-exporter)
|
5
5
|
|
6
6
|
Purpose
|
7
7
|
-------
|
@@ -24,21 +24,21 @@ Configuration
|
|
24
24
|
The export process is configured through the only config, /etc/upstart-exporter.yaml, which is a simple YAML file of the following format:
|
25
25
|
|
26
26
|
---
|
27
|
-
run_user: www # The user under which all installed through upstart-exporter background jobs are run
|
27
|
+
run_user: www # The user under which all installed through upstart-exporter background jobs are run
|
28
28
|
run_group: www # The group of run_user
|
29
29
|
helper_dir: /var/helper_dir # Auxilary directory for scripts incapsulating background jobs
|
30
30
|
upstart_dir: /var/upstart_dir # Directory where upstart scripts should be placed
|
31
31
|
prefix: 'myupstartjobs-' # Prefix added to app's log folders and upstart scripts
|
32
32
|
|
33
33
|
The config is not installed by default. If this config is absent, the default values are the following:
|
34
|
-
|
34
|
+
|
35
35
|
helper_dir: /var/local/upstart_helpers/
|
36
36
|
upstart_dir: /etc/init/
|
37
37
|
run_user: service
|
38
38
|
prefix: 'fb-'
|
39
39
|
|
40
|
-
To give a certain user (i.e. deployuser) ability to use this script,
|
41
|
-
|
40
|
+
To give a certain user (i.e. deployuser) ability to use this script, you can place the following lines into sudoers file:
|
41
|
+
|
42
42
|
# Commands required for manipulating jobs
|
43
43
|
Cmnd_Alias UPSTART = /sbin/start, /sbin/stop, /sbin/restart
|
44
44
|
Cmnd_Alias UPEXPORT = /usr/local/bin/upstart-export
|
@@ -50,27 +50,92 @@ To give a certain user (i.e. deployuser) ability to use this script, one can pla
|
|
50
50
|
|
51
51
|
...
|
52
52
|
|
53
|
-
# Allow deploy user to manipulate jobs
|
53
|
+
# Allow deploy user to manipulate jobs
|
54
54
|
deployuser ALL=(deployuser) NOPASSWD: ALL, (root) NOPASSWD: UPSTART, UPEXPORT
|
55
|
-
|
55
|
+
|
56
56
|
|
57
57
|
Usage
|
58
58
|
-----
|
59
59
|
|
60
|
-
|
60
|
+
Gem is able to process two versions of Procfile's, format of the Procfile is
|
61
|
+
defined in the _version_ key. If the key is not present or is not equal to _2_
|
62
|
+
gem will try to parse it as Procfile v.1.
|
63
|
+
|
64
|
+
Procfile v.1
|
65
|
+
------------
|
66
|
+
|
67
|
+
After upstart-exporter is installed and configured, you may export background jobs from an arbitrary Procfile-like file of the following format:
|
61
68
|
|
62
69
|
cmdlabel1: cmd1
|
63
70
|
cmdlabel2: cmd2
|
64
|
-
|
71
|
+
|
65
72
|
i.e. a file ./myprocfile containing:
|
66
73
|
|
67
74
|
my_tail_cmd: /usr/bin/tail -F /var/log/messages
|
68
75
|
my_another_tail_cmd: /usr/bin/tail -F /var/log/messages
|
69
76
|
|
70
|
-
For security purposes, command labels are allowed to contain only letters, digits and underscores.
|
77
|
+
For security purposes, command labels are allowed to contain only letters, digits, and underscores.
|
78
|
+
|
79
|
+
Procfile v.2
|
80
|
+
------------
|
81
|
+
|
82
|
+
Another format of Procfile scripts is YAML config. A configuration script may
|
83
|
+
look like this:
|
84
|
+
|
85
|
+
version: 2
|
86
|
+
start_on_runlevel: "[2345]"
|
87
|
+
stop_on_runlevel: "[06]"
|
88
|
+
env:
|
89
|
+
RAILS_ENV: production
|
90
|
+
TEST: true
|
91
|
+
working_directory: /srv/projects/mpro/current
|
92
|
+
commands:
|
93
|
+
my_tail_cmd:
|
94
|
+
command: /usr/bin/tail -F /var/log/messages
|
95
|
+
respawn:
|
96
|
+
count: 5
|
97
|
+
interval: 10
|
98
|
+
env:
|
99
|
+
RAILS_ENV: staging # if needs to be redefined or extended
|
100
|
+
working_directory: '/var/...' # if needs to be redefined
|
101
|
+
my_another_tail_cmd:
|
102
|
+
command: /usr/bin/tail -F /var/log/messages
|
103
|
+
respawn: false # by default respawn option is enabled
|
104
|
+
my_one_another_tail_cmd:
|
105
|
+
command: /usr/bin/tail -F /var/log/messages
|
106
|
+
my_multi_tail_cmd:
|
107
|
+
command: /usr/bin/tail -F /var/log/messages
|
108
|
+
count: 2
|
109
|
+
|
110
|
+
*start_on_runlevel* and *stop_on_runlevel* are two global options that can't be
|
111
|
+
redefined. For more information on these options look into [upstart scripts documentation.]( http://upstart.ubuntu.com/cookbook/#start-on)
|
112
|
+
|
113
|
+
*working_directory* will generate the next line:
|
114
|
+
|
115
|
+
cd 'your/working/directory' && your_command
|
116
|
+
|
117
|
+
*env* params can be redefined and extended in per-command options. Note, that
|
118
|
+
you can't remove globally defined *env* variable.
|
119
|
+
For given earlier Procfile example the generated command will look like:
|
120
|
+
|
121
|
+
env RAILS_ENV=staging TEST=true your_command
|
122
|
+
|
123
|
+
*respawn* option controls restarting of scripts in case of their failure.
|
124
|
+
By default this option is enabled. For
|
125
|
+
more info look into [documentation](http://upstart.ubuntu.com/cookbook/#respawn)).
|
126
|
+
|
127
|
+
*respawn_limit* option controls how often job can fail. If the job restarts more
|
128
|
+
often than *count* times in *interval*, it won't be restarted anymore. For more
|
129
|
+
info look into [documentation](http://upstart.ubuntu.com/cookbook/#respawn-limit).
|
130
|
+
|
131
|
+
Options *working_directory*, *env*, *respawn* and *respawn_limit* can be
|
132
|
+
defined both as global and as per-command options.
|
133
|
+
|
134
|
+
Exporting
|
135
|
+
---------
|
136
|
+
|
137
|
+
To export Procfile you should run
|
71
138
|
|
72
|
-
To export this file one should run
|
73
|
-
|
74
139
|
sudo upstart-export -p ./myprocfile -n myapp
|
75
140
|
|
76
141
|
where _myapp_ is the application name. This name only affects the names of generated files. For security purposes, app name is also allowed to contain only letters, digits and underscores. Assuming that default options are used, the following files and folders will be generated:
|
@@ -94,16 +159,17 @@ Prefix 'fb-' (which can be customised through config) is added to avoid collisio
|
|
94
159
|
|
95
160
|
sudo stop fb-myapp-my_tail_cmd
|
96
161
|
|
97
|
-
It's stdout/stderr will be redirected to /var/log/fb-myapp/my\_tail\_cmd.log.
|
162
|
+
It's stdout/stderr will be redirected to /var/log/fb-myapp/my\_tail\_cmd.log.
|
163
|
+
|
164
|
+
To start/stop all application commands at once, you can run:
|
98
165
|
|
99
|
-
To start/stop all application commands at once, one can run:
|
100
|
-
|
101
166
|
sudo start fb-myapp
|
102
167
|
...
|
103
168
|
sudo stop fb-myapp
|
104
169
|
|
105
|
-
To remove upstart scripts and helpers for a particular application
|
170
|
+
To remove upstart scripts and helpers for a particular application you can run
|
106
171
|
|
107
172
|
sudo upstart-export -c -n myapp
|
108
173
|
|
109
174
|
The logs are not cleared in this case. Also, all old application scripts are cleared before each export.
|
175
|
+
|
@@ -0,0 +1,107 @@
|
|
1
|
+
class Upstart::Exporter
|
2
|
+
class ExpandedExporter
|
3
|
+
include ExporterHelpers
|
4
|
+
include Errors
|
5
|
+
|
6
|
+
def self.export(options)
|
7
|
+
new(options).export
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(options)
|
11
|
+
@config = options[:commands]
|
12
|
+
@options = options
|
13
|
+
@commands = @config['commands']
|
14
|
+
@env = @config['env'] || {}
|
15
|
+
@dir = @config['working_directory'] || ''
|
16
|
+
end
|
17
|
+
|
18
|
+
def export
|
19
|
+
@commands.each do |command, value|
|
20
|
+
if count = value['count']
|
21
|
+
count.times do |counter|
|
22
|
+
export_cmd("#{command}_#{counter}", value)
|
23
|
+
end
|
24
|
+
else
|
25
|
+
export_cmd(command, value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def export_cmd(command, value)
|
33
|
+
script = value['command']
|
34
|
+
script = add_env_command(script, value)
|
35
|
+
script = add_dir_command(script, value)
|
36
|
+
export_cmd_helper(command, script)
|
37
|
+
export_cmd_upstart_conf(command, value)
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_env_command(script, command)
|
41
|
+
vars = ''
|
42
|
+
env = @env.merge((command['env'] || {}))
|
43
|
+
env.each do |var, val|
|
44
|
+
vars += "#{var}=#{val} "
|
45
|
+
end
|
46
|
+
if vars.empty?
|
47
|
+
script
|
48
|
+
else
|
49
|
+
"env #{vars} #{script}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_dir_command(script, command)
|
54
|
+
dir = command['working_directory'] || @dir
|
55
|
+
if dir.empty?
|
56
|
+
script
|
57
|
+
else
|
58
|
+
"cd '#{dir}' && #{script}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def respawn_options(cmd_options)
|
63
|
+
if cmd_options.has_key?('respawn')
|
64
|
+
cmd_options['respawn']
|
65
|
+
elsif @config.has_key?('respawn')
|
66
|
+
@config['respawn']
|
67
|
+
else
|
68
|
+
{}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def respawn(cmd_options)
|
73
|
+
respawn_options(cmd_options) ? 'respawn' : ''
|
74
|
+
end
|
75
|
+
|
76
|
+
def respawn_limit(cmd_options)
|
77
|
+
limits = respawn_options(cmd_options)
|
78
|
+
return '' unless limits && limits['count'] && limits['interval']
|
79
|
+
"respawn limit #{limits['count'].to_i} #{limits['interval'].to_i}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def start_on
|
83
|
+
"starting #{app_name}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def stop_on
|
87
|
+
"stopping #{app_name}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def export_cmd_upstart_conf(cmd_name, cmd_options)
|
91
|
+
cmd_upstart_conf_content = Templates.command(
|
92
|
+
:app_name => app_name,
|
93
|
+
:start_on => start_on,
|
94
|
+
:stop_on => stop_on,
|
95
|
+
:run_user => @options[:run_user],
|
96
|
+
:run_group => @options[:run_group],
|
97
|
+
:cmd_name => cmd_name,
|
98
|
+
:helper_cmd_conf => helper_cmd_conf(cmd_name),
|
99
|
+
:respawn => respawn(cmd_options),
|
100
|
+
:respawn_limit => respawn_limit(cmd_options)
|
101
|
+
)
|
102
|
+
File.open(upstart_cmd_conf(cmd_name), 'w') do |f|
|
103
|
+
f.write(cmd_upstart_conf_content)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Upstart::Exporter
|
2
|
+
module ExporterHelpers
|
3
|
+
def export_cmd_helper(cmd_name, cmd)
|
4
|
+
helper_script_cont = Templates.helper :cmd => cmd
|
5
|
+
File.open(helper_cmd_conf(cmd_name), 'w') do |f|
|
6
|
+
f.write(helper_script_cont)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def app_name
|
11
|
+
@options[:prefix] + @options[:app_name]
|
12
|
+
end
|
13
|
+
|
14
|
+
def app_cmd(cmd_name)
|
15
|
+
"#{app_name}-#{cmd_name}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def upstart_cmd_conf(cmd_name)
|
19
|
+
File.join(@options[:upstart_dir], "#{app_cmd(cmd_name)}.conf")
|
20
|
+
end
|
21
|
+
|
22
|
+
def helper_cmd_conf(cmd_name)
|
23
|
+
File.join(@options[:helper_dir], "#{app_cmd(cmd_name)}.sh")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -27,14 +27,20 @@ module Upstart::Exporter::Options
|
|
27
27
|
elsif line =~ /^\s*$/
|
28
28
|
# do nothing, empty
|
29
29
|
else
|
30
|
-
|
30
|
+
break if commands['version'] && commands['version'].strip == '2'
|
31
|
+
error "procfile version 1 lines should have the following format: 'some_label: command'"
|
31
32
|
end
|
32
33
|
end
|
34
|
+
if commands['version'] && commands['version'].strip == '2'
|
35
|
+
commands = YAML.load(content)
|
36
|
+
error('procfile should include "commands" key') unless commands['commands']
|
37
|
+
error('command names should include only letters and/or underscores') if commands['commands'].keys.find { |k| k !~ /\A[A-z\d_]*?\z/ }
|
38
|
+
end
|
33
39
|
commands
|
34
40
|
end
|
35
41
|
|
36
42
|
def process_appname(app_name)
|
37
|
-
error "Application name should contain only letters (and underscore) and be nonempty, so #{app_name.inspect} is not suitable" unless app_name =~ /^\w+$/
|
43
|
+
error "Application name should contain only letters (and underscore) and be nonempty, so #{app_name.inspect} is not suitable" unless app_name =~ /^\w+$/
|
38
44
|
app_name
|
39
45
|
end
|
40
46
|
|
@@ -7,7 +7,9 @@ module Upstart::Exporter::Options
|
|
7
7
|
'upstart_dir' => '/etc/init/',
|
8
8
|
'run_user' => 'service',
|
9
9
|
'run_group' => 'service',
|
10
|
-
'prefix' => 'fb-'
|
10
|
+
'prefix' => 'fb-',
|
11
|
+
'start_on_runlevel' => '[3]',
|
12
|
+
'stop_on_runlevel' => '[3]'
|
11
13
|
}
|
12
14
|
|
13
15
|
CONF = '/etc/upstart-exporter.yaml'
|
@@ -1,16 +1,23 @@
|
|
1
1
|
module Upstart
|
2
2
|
class Exporter
|
3
3
|
class Templates
|
4
|
+
extend Errors
|
4
5
|
|
5
6
|
def self.helper(binds)
|
6
7
|
interpolate(HELPER_TPL, binds)
|
7
8
|
end
|
8
9
|
|
9
10
|
def self.app(binds)
|
11
|
+
if error_val = binds.find { |v| v =~ /\A[A-z0-9_\- ]*?\z/ }
|
12
|
+
error("value #{error_val} is insecure and can't be accepted")
|
13
|
+
end
|
10
14
|
interpolate(APP_TPL, binds)
|
11
15
|
end
|
12
16
|
|
13
17
|
def self.command(binds)
|
18
|
+
if error_val = binds.find { |v| v =~ /\A[A-z0-9_\- ]*?\z/ }
|
19
|
+
error("value #{error_val} is insecure and can't be accepted")
|
20
|
+
end
|
14
21
|
interpolate(COMMAND_TPL, binds)
|
15
22
|
end
|
16
23
|
|
@@ -25,6 +32,9 @@ fi
|
|
25
32
|
HEREDOC
|
26
33
|
|
27
34
|
APP_TPL = <<-HEREDOC
|
35
|
+
start on {{start_on}}
|
36
|
+
stop on {{stop_on}}
|
37
|
+
|
28
38
|
pre-start script
|
29
39
|
|
30
40
|
bash << "EOF"
|
@@ -38,9 +48,10 @@ end script
|
|
38
48
|
HEREDOC
|
39
49
|
|
40
50
|
COMMAND_TPL = <<-HEREDOC
|
41
|
-
start on
|
42
|
-
stop on
|
43
|
-
respawn
|
51
|
+
start on {{start_on}}
|
52
|
+
stop on {{stop_on}}
|
53
|
+
{{respawn}}
|
54
|
+
{{respawn_limit}}
|
44
55
|
|
45
56
|
script
|
46
57
|
touch /var/log/{{app_name}}/{{cmd_name}}.log
|
@@ -62,4 +73,3 @@ HEREDOC
|
|
62
73
|
end
|
63
74
|
end
|
64
75
|
end
|
65
|
-
|
data/lib/upstart-exporter.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
require 'yaml'
|
2
|
+
require 'upstart-exporter/version'
|
3
|
+
require 'upstart-exporter/errors'
|
4
|
+
require 'upstart-exporter/templates'
|
5
|
+
require 'upstart-exporter/exporter_helpers'
|
6
|
+
require 'upstart-exporter/expanded_exporter'
|
7
|
+
require 'upstart-exporter/options/global'
|
8
|
+
require 'upstart-exporter/options/command_line'
|
6
9
|
|
7
10
|
module Upstart
|
8
11
|
class Exporter
|
9
12
|
include Errors
|
13
|
+
include ExporterHelpers
|
10
14
|
|
11
15
|
attr_reader :options
|
12
|
-
|
16
|
+
|
13
17
|
def initialize(command_line_args)
|
14
18
|
global_options = Options::Global.new
|
15
19
|
command_line_options = Options::CommandLine.new(command_line_args)
|
@@ -20,8 +24,12 @@ module Upstart
|
|
20
24
|
def export
|
21
25
|
clear
|
22
26
|
export_app
|
23
|
-
options[:commands]
|
24
|
-
|
27
|
+
if options[:commands]['version'] && options[:commands]['version'] == 2
|
28
|
+
ExpandedExporter.export(options)
|
29
|
+
else
|
30
|
+
options[:commands].each do |cmd_name, cmd|
|
31
|
+
export_command(cmd_name, cmd)
|
32
|
+
end
|
25
33
|
end
|
26
34
|
end
|
27
35
|
|
@@ -37,17 +45,29 @@ module Upstart
|
|
37
45
|
|
38
46
|
protected
|
39
47
|
|
48
|
+
def start_on_runlevel
|
49
|
+
lvl = options[:commands]['start_on_runlevel'] || options[:start_on_runlevel]
|
50
|
+
"runlevel #{lvl}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def stop_on_runlevel
|
54
|
+
lvl = options[:commands]['stop_on_runlevel'] || options[:stop_on_runlevel]
|
55
|
+
"runlevel #{lvl}"
|
56
|
+
end
|
57
|
+
|
40
58
|
def ensure_dirs
|
41
59
|
ensure_dir(options[:helper_dir])
|
42
60
|
ensure_dir(options[:upstart_dir])
|
43
61
|
end
|
44
62
|
|
45
|
-
def app_name
|
46
|
-
options[:prefix] + options[:app_name]
|
47
|
-
end
|
48
|
-
|
49
63
|
def export_app
|
50
|
-
app_conf = Templates.app
|
64
|
+
app_conf = Templates.app(
|
65
|
+
:app_name => app_name,
|
66
|
+
:run_user => options[:run_user],
|
67
|
+
:run_group => options[:run_group],
|
68
|
+
:start_on => start_on_runlevel,
|
69
|
+
:stop_on => stop_on_runlevel
|
70
|
+
)
|
51
71
|
File.open(upstart_conf, 'w') do |f|
|
52
72
|
f.write(app_conf)
|
53
73
|
end
|
@@ -62,27 +82,18 @@ module Upstart
|
|
62
82
|
File.join(options[:upstart_dir], "#{app_name}.conf")
|
63
83
|
end
|
64
84
|
|
65
|
-
def app_cmd(cmd_name)
|
66
|
-
"#{app_name}-#{cmd_name}"
|
67
|
-
end
|
68
|
-
|
69
|
-
def upstart_cmd_conf(cmd_name)
|
70
|
-
File.join(options[:upstart_dir], "#{app_cmd(cmd_name)}.conf")
|
71
|
-
end
|
72
|
-
|
73
|
-
def helper_cmd_conf(cmd_name)
|
74
|
-
File.join(options[:helper_dir], "#{app_cmd(cmd_name)}.sh")
|
75
|
-
end
|
76
|
-
|
77
|
-
def export_cmd_helper(cmd_name, cmd)
|
78
|
-
helper_script_cont = Templates.helper :cmd => cmd
|
79
|
-
File.open(helper_cmd_conf(cmd_name), 'w') do |f|
|
80
|
-
f.write(helper_script_cont)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
85
|
def export_cmd_upstart_conf(cmd_name)
|
85
|
-
cmd_upstart_conf_content = Templates.command
|
86
|
+
cmd_upstart_conf_content = Templates.command(
|
87
|
+
:app_name => app_name,
|
88
|
+
:start_on => "starting #{app_name}",
|
89
|
+
:stop_on => "stopping #{app_name}",
|
90
|
+
:respawn => 'respawn',
|
91
|
+
:respawn_limit => '',
|
92
|
+
:run_user => options[:run_user],
|
93
|
+
:run_group => options[:run_group],
|
94
|
+
:cmd_name => cmd_name,
|
95
|
+
:helper_cmd_conf => helper_cmd_conf(cmd_name)
|
96
|
+
)
|
86
97
|
File.open(upstart_cmd_conf(cmd_name), 'w') do |f|
|
87
98
|
f.write(cmd_upstart_conf_content)
|
88
99
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe Upstart::Exporter::ExpandedExporter do
|
4
|
+
before do
|
5
|
+
@defaults = {}
|
6
|
+
Upstart::Exporter::Options::Global::DEFAULTS.each do |key, value|
|
7
|
+
@defaults[key.to_sym] = value
|
8
|
+
end
|
9
|
+
|
10
|
+
File.stub(:open)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'calls template render exact amount of times' do
|
14
|
+
Upstart::Exporter::Templates.should_receive(:command).exactly(5).times
|
15
|
+
options = {
|
16
|
+
:commands => {
|
17
|
+
'commands' => {
|
18
|
+
'ls' => {
|
19
|
+
'command' => 'ls',
|
20
|
+
'count' => 3
|
21
|
+
},
|
22
|
+
'ls2' => {
|
23
|
+
'command' => 'ls',
|
24
|
+
'count' => 2
|
25
|
+
}
|
26
|
+
}
|
27
|
+
},
|
28
|
+
:app_name => 'appname'
|
29
|
+
}.merge(@defaults)
|
30
|
+
|
31
|
+
described_class.export(options)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'merges env params in the right order' do
|
35
|
+
Upstart::Exporter::Templates.should_receive(:helper) do |options|
|
36
|
+
options[:cmd].should include('B=b')
|
37
|
+
options[:cmd].should include('T=t')
|
38
|
+
end
|
39
|
+
options = {
|
40
|
+
:commands => {
|
41
|
+
'env' => {
|
42
|
+
'T' => 't',
|
43
|
+
'B' => 'a'
|
44
|
+
},
|
45
|
+
'commands' => {
|
46
|
+
'ls' => {
|
47
|
+
'command' => 'ls',
|
48
|
+
'env' => {
|
49
|
+
'B' => 'b'
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
},
|
54
|
+
:app_name => 'appname'
|
55
|
+
}.merge(@defaults)
|
56
|
+
|
57
|
+
described_class.export(options)
|
58
|
+
end
|
59
|
+
end
|
@@ -6,25 +6,32 @@ describe Upstart::Exporter::Options::CommandLine do
|
|
6
6
|
make_procfile('Procfile', 'ls_cmd: ls')
|
7
7
|
described_class.new(:app_name => 'someappname', :procfile => 'Procfile').should respond_to('[]')
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
it "should parse procfile" do
|
11
11
|
make_procfile('Procfile', 'ls_cmd: ls')
|
12
12
|
options = described_class.new(:app_name => 'someappname', :procfile => 'Procfile')
|
13
13
|
options[:commands].should == {'ls_cmd' => ' ls'}
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
|
+
it 'should parse procfile v2' do
|
17
|
+
make_procfile('Procfile', "version: 2\ncommands:\n ls:\n command: ls -al")
|
18
|
+
options = described_class.new(:app_name => 'someappname', :procfile => 'Procfile')
|
19
|
+
options[:commands].should have_key('commands')
|
20
|
+
options[:commands]['commands'].should have_key('ls')
|
21
|
+
end
|
22
|
+
|
16
23
|
it "should skip empty and commented lines in a procfile" do
|
17
24
|
make_procfile('Procfile', "ls_cmd1: ls1\n\nls_cmd2: ls2\n # fooo baaar")
|
18
25
|
options = described_class.new(:app_name => 'someappname', :procfile => 'Procfile')
|
19
26
|
options[:commands].should == {'ls_cmd1' => ' ls1', 'ls_cmd2' => ' ls2'}
|
20
27
|
end
|
21
|
-
|
28
|
+
|
22
29
|
it "should store app_name" do
|
23
30
|
make_procfile('Procfile', "ls_cmd1: ls1\n\nls_cmd2: ls2\n # fooo baaar")
|
24
31
|
options = described_class.new(:app_name => 'someappname', :procfile => 'Procfile')
|
25
32
|
options[:app_name].should == 'someappname'
|
26
33
|
end
|
27
|
-
|
34
|
+
|
28
35
|
it "should not process procfile if :clear arg is present" do
|
29
36
|
make_procfile('Procfile', "bad procfile")
|
30
37
|
options = described_class.new(:app_name => 'someappname', :procfile => 'Procfile', :clear => true)
|
@@ -41,7 +48,7 @@ describe Upstart::Exporter::Options::CommandLine do
|
|
41
48
|
lambda{ described_class.new(:procfile => 'Procfile') }.should raise_exception
|
42
49
|
end
|
43
50
|
end
|
44
|
-
|
51
|
+
|
45
52
|
context "when bad Procfile is passed" do
|
46
53
|
it "should raise exception" do
|
47
54
|
make_procfile('Procfile', 'ls cmd: ls')
|
@@ -51,7 +58,10 @@ describe Upstart::Exporter::Options::CommandLine do
|
|
51
58
|
lambda{ described_class.new(:app_name => 'someappname', :procfile => 'Procfile') }.should raise_exception
|
52
59
|
|
53
60
|
lambda{ described_class.new(:app_name => 'someappname', :procfile => '::') }.should raise_exception
|
54
|
-
|
61
|
+
|
62
|
+
make_procfile('Procfile', "version: 2\ncommands:\n ls cmd:\n command: ls")
|
63
|
+
lambda{ described_class.new(:app_name => 'someappname', :procfile => 'Procfile') }.should raise_exception
|
64
|
+
|
55
65
|
lambda{ described_class.new(:app_name => 'someappname') }.should raise_exception
|
56
66
|
end
|
57
67
|
end
|
@@ -3,7 +3,7 @@ require 'spec/spec_helper'
|
|
3
3
|
describe Upstart::Exporter::Options::Global do
|
4
4
|
let(:defaults){ Upstart::Exporter::Options::Global::DEFAULTS }
|
5
5
|
let(:conf){ Upstart::Exporter::Options::Global::CONF }
|
6
|
-
|
6
|
+
|
7
7
|
|
8
8
|
it "should give access to options like a hash" do
|
9
9
|
capture(:stderr) do
|
@@ -40,7 +40,7 @@ describe Upstart::Exporter::Options::Global do
|
|
40
40
|
described_class.new[:run_user].should == 'wwwww'
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
it "should preserve default values for options not specified in the config" do
|
45
45
|
capture(:stderr) do
|
46
46
|
make_global_config({'run_user' => 'wwwww'}.to_yaml)
|
@@ -3,8 +3,11 @@ require 'spec/spec_helper'
|
|
3
3
|
describe Upstart::Exporter::Templates do
|
4
4
|
describe ".app" do
|
5
5
|
it "should generate a valid app config" do
|
6
|
-
|
6
|
+
|
7
7
|
conf = <<-HEREDOC
|
8
|
+
start on 12
|
9
|
+
stop on 13
|
10
|
+
|
8
11
|
pre-start script
|
9
12
|
|
10
13
|
bash << "EOF"
|
@@ -17,13 +20,19 @@ EOF
|
|
17
20
|
end script
|
18
21
|
HEREDOC
|
19
22
|
|
20
|
-
described_class.app(
|
23
|
+
described_class.app(
|
24
|
+
:run_user => 'SOMEUSER',
|
25
|
+
:run_group => 'SOMEGROUP',
|
26
|
+
:app_name => 'SOMEAPP',
|
27
|
+
:start_on => '12',
|
28
|
+
:stop_on => '13'
|
29
|
+
).should == conf
|
21
30
|
end
|
22
31
|
end
|
23
32
|
|
24
33
|
describe ".helper" do
|
25
34
|
it "should generate a valid helper script" do
|
26
|
-
|
35
|
+
|
27
36
|
conf = <<-HEREDOC
|
28
37
|
#!/bin/bash
|
29
38
|
if [ -f /etc/profile.d/rbenv.sh ]; then
|
@@ -39,11 +48,12 @@ HEREDOC
|
|
39
48
|
|
40
49
|
describe ".helper" do
|
41
50
|
it "should generate a valid upstart script for a single command" do
|
42
|
-
|
51
|
+
|
43
52
|
conf = <<-HEREDOC
|
44
53
|
start on starting SOMEAPP
|
45
54
|
stop on stopping SOMEAPP
|
46
55
|
respawn
|
56
|
+
respawn limit 5 10
|
47
57
|
|
48
58
|
script
|
49
59
|
touch /var/log/SOMEAPP/SOMECMD.log
|
@@ -54,7 +64,15 @@ script
|
|
54
64
|
end script
|
55
65
|
HEREDOC
|
56
66
|
|
57
|
-
described_class.command(:run_user => 'SOMEUSER',
|
67
|
+
described_class.command(:run_user => 'SOMEUSER',
|
68
|
+
:run_group => 'SOMEGROUP',
|
69
|
+
:app_name => 'SOMEAPP',
|
70
|
+
:cmd_name => 'SOMECMD',
|
71
|
+
:respawn => 'respawn',
|
72
|
+
:respawn_limit => 'respawn limit 5 10',
|
73
|
+
:start_on => 'starting SOMEAPP',
|
74
|
+
:stop_on => 'stopping SOMEAPP',
|
75
|
+
:helper_cmd_conf => 'HELPERPATH').should == conf
|
58
76
|
end
|
59
77
|
end
|
60
78
|
|
@@ -9,7 +9,8 @@ describe Upstart::Exporter do
|
|
9
9
|
'upstart_dir' => '/u',
|
10
10
|
'run_user' => 'u',
|
11
11
|
'run_group' => 'g',
|
12
|
-
'prefix' => 'p-'
|
12
|
+
'prefix' => 'p-',
|
13
|
+
'start_on_runlevel' => '[7]'
|
13
14
|
}.to_yaml)
|
14
15
|
make_procfile('Procfile', 'ls_cmd: ls')
|
15
16
|
exporter = described_class.new({:app_name => 'app', :procfile => 'Procfile'})
|
@@ -27,13 +28,25 @@ describe Upstart::Exporter do
|
|
27
28
|
FileTest.file?(f).should be_true
|
28
29
|
end
|
29
30
|
end
|
30
|
-
|
31
|
+
|
31
32
|
it 'created scripts, folders and sh helpers should have valid content' do
|
32
33
|
exporter.export
|
33
34
|
|
34
35
|
File.read('/h/p-app-ls_cmd.sh').should == tpl.helper(:cmd => ' ls')
|
35
|
-
File.read('/u/p-app.conf').should == tpl.app(:run_user => 'u',
|
36
|
-
|
36
|
+
File.read('/u/p-app.conf').should == tpl.app(:run_user => 'u',
|
37
|
+
:run_group => 'g',
|
38
|
+
:app_name => 'p-app',
|
39
|
+
:start_on => 'runlevel [7]',
|
40
|
+
:stop_on => 'runlevel [3]')
|
41
|
+
File.read('/u/p-app-ls_cmd.conf').should == tpl.command(:run_user => 'u',
|
42
|
+
:run_group => 'g',
|
43
|
+
:app_name => 'p-app',
|
44
|
+
:cmd_name => 'ls_cmd',
|
45
|
+
:start_on => 'starting p-app',
|
46
|
+
:stop_on => 'stopping p-app',
|
47
|
+
:respawn => 'respawn',
|
48
|
+
:respawn_limit => '',
|
49
|
+
:helper_cmd_conf => '/h/p-app-ls_cmd.sh')
|
37
50
|
end
|
38
51
|
end
|
39
52
|
|
@@ -44,10 +57,10 @@ describe Upstart::Exporter do
|
|
44
57
|
Dir['/h/*'].should be_empty
|
45
58
|
Dir['/u/*'].should be_empty
|
46
59
|
end
|
47
|
-
|
60
|
+
|
48
61
|
it 'should keep files of other apps' do
|
49
62
|
exporter.export
|
50
|
-
|
63
|
+
|
51
64
|
make_procfile('Procfile1', 'ls_cmd: ls')
|
52
65
|
other_exporter = described_class.new({:app_name => 'other_app', :procfile => 'Procfile1'})
|
53
66
|
other_exporter.export
|
data/upstart-exporter.gemspec
CHANGED
@@ -5,15 +5,14 @@ require "upstart-exporter/version"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "upstart-exporter"
|
7
7
|
s.version = Upstart::Exporter::VERSION
|
8
|
-
s.authors = ["Ilya Averyanov"]
|
9
|
-
s.email = ["ilya@averyanov.org"]
|
8
|
+
s.authors = ["Ilya Averyanov", "Egor Blinov"]
|
9
|
+
s.email = ["ilya@averyanov.org", "monshq@gmail.com"]
|
10
10
|
s.homepage = ""
|
11
|
-
s.summary = %q{Gem for converting Procfile-like files to upstart scripts}
|
12
|
-
s.description = %q{Gem for converting Procfile-like files to upstart scripts}
|
11
|
+
s.summary = %q{Gem for converting extended Procfile-like files to upstart scripts}
|
12
|
+
s.description = %q{Gem for converting extended Procfile-like files to upstart scripts}
|
13
13
|
|
14
14
|
s.files = `git ls-files`.split("\n")
|
15
15
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
17
|
s.require_paths = ["lib"]
|
18
|
-
|
19
18
|
end
|
metadata
CHANGED
@@ -1,26 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: upstart-exporter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
|
-
-
|
7
|
+
- 2
|
8
8
|
- 0
|
9
9
|
- 1
|
10
|
-
version:
|
10
|
+
version: 2.0.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ilya Averyanov
|
14
|
+
- Egor Blinov
|
14
15
|
autorequire:
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date:
|
19
|
+
date: 2014-01-21 00:00:00 +04:00
|
20
|
+
default_executable:
|
19
21
|
dependencies: []
|
20
22
|
|
21
|
-
description: Gem for converting Procfile-like files to upstart scripts
|
23
|
+
description: Gem for converting extended Procfile-like files to upstart scripts
|
22
24
|
email:
|
23
25
|
- ilya@averyanov.org
|
26
|
+
- monshq@gmail.com
|
24
27
|
executables:
|
25
28
|
- upstart-export
|
26
29
|
extensions: []
|
@@ -31,6 +34,8 @@ files:
|
|
31
34
|
- .gitignore
|
32
35
|
- .rbenv-version
|
33
36
|
- .rspec
|
37
|
+
- .ruby-version
|
38
|
+
- .travis.yml
|
34
39
|
- .yardoc/checksums
|
35
40
|
- .yardoc/objects/root.dat
|
36
41
|
- .yardoc/proxy_types
|
@@ -63,11 +68,14 @@ files:
|
|
63
68
|
- doc/top-level-namespace.html
|
64
69
|
- lib/upstart-exporter.rb
|
65
70
|
- lib/upstart-exporter/errors.rb
|
71
|
+
- lib/upstart-exporter/expanded_exporter.rb
|
72
|
+
- lib/upstart-exporter/exporter_helpers.rb
|
66
73
|
- lib/upstart-exporter/options/command_line.rb
|
67
74
|
- lib/upstart-exporter/options/global.rb
|
68
75
|
- lib/upstart-exporter/templates.rb
|
69
76
|
- lib/upstart-exporter/version.rb
|
70
77
|
- spec/lib/upstart-exporter/errors_spec.rb
|
78
|
+
- spec/lib/upstart-exporter/expanded_exporter_spec.rb
|
71
79
|
- spec/lib/upstart-exporter/options/command_line_spec.rb
|
72
80
|
- spec/lib/upstart-exporter/options/global_spec.rb
|
73
81
|
- spec/lib/upstart-exporter/templates_spec.rb
|
@@ -77,6 +85,7 @@ files:
|
|
77
85
|
- spec/support/procfile.rb
|
78
86
|
- spec/support/streams.rb
|
79
87
|
- upstart-exporter.gemspec
|
88
|
+
has_rdoc: true
|
80
89
|
homepage: ""
|
81
90
|
licenses: []
|
82
91
|
|
@@ -106,12 +115,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
115
|
requirements: []
|
107
116
|
|
108
117
|
rubyforge_project:
|
109
|
-
rubygems_version: 1.
|
118
|
+
rubygems_version: 1.6.2
|
110
119
|
signing_key:
|
111
120
|
specification_version: 3
|
112
|
-
summary: Gem for converting Procfile-like files to upstart scripts
|
121
|
+
summary: Gem for converting extended Procfile-like files to upstart scripts
|
113
122
|
test_files:
|
114
123
|
- spec/lib/upstart-exporter/errors_spec.rb
|
124
|
+
- spec/lib/upstart-exporter/expanded_exporter_spec.rb
|
115
125
|
- spec/lib/upstart-exporter/options/command_line_spec.rb
|
116
126
|
- spec/lib/upstart-exporter/options/global_spec.rb
|
117
127
|
- spec/lib/upstart-exporter/templates_spec.rb
|
@@ -120,4 +130,3 @@ test_files:
|
|
120
130
|
- spec/support/global_config.rb
|
121
131
|
- spec/support/procfile.rb
|
122
132
|
- spec/support/streams.rb
|
123
|
-
has_rdoc:
|