foreman 0.29.0 → 0.37.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.
- data/README.md +39 -0
- data/bin/runner +35 -1
- data/data/export/bluepill/master.pill.erb +1 -1
- data/lib/foreman/cli.rb +30 -23
- data/lib/foreman/engine.rb +35 -20
- data/lib/foreman/export/base.rb +12 -5
- data/lib/foreman/export/bluepill.rb +5 -7
- data/lib/foreman/export/inittab.rb +10 -12
- data/lib/foreman/export/runit.rb +10 -11
- data/lib/foreman/export/upstart.rb +8 -10
- data/lib/foreman/export.rb +21 -0
- data/lib/foreman/helpers.rb +45 -0
- data/lib/foreman/process.rb +52 -15
- data/lib/foreman/utils.rb +4 -1
- data/lib/foreman/version.rb +1 -1
- data/lib/foreman.rb +8 -1
- data/man/foreman.1 +5 -1
- data/spec/foreman/cli_spec.rb +77 -7
- data/spec/foreman/engine_spec.rb +5 -5
- data/spec/foreman/export/base_spec.rb +22 -0
- data/spec/foreman/export/bluepill_spec.rb +22 -5
- data/spec/foreman/export/inittab_spec.rb +40 -0
- data/spec/foreman/export/runit_spec.rb +18 -12
- data/spec/foreman/export/upstart_spec.rb +40 -8
- data/spec/foreman/export_spec.rb +22 -0
- data/spec/foreman/helpers_spec.rb +26 -0
- data/spec/foreman/process_spec.rb +131 -2
- data/spec/foreman_spec.rb +8 -7
- data/spec/helper_spec.rb +18 -0
- data/spec/resources/export/bluepill/app-concurrency.pill +47 -0
- data/spec/resources/export/bluepill/app.pill +0 -21
- data/spec/resources/export/inittab/inittab.concurrency +4 -0
- data/spec/resources/export/inittab/inittab.default +4 -0
- data/spec/spec_helper.rb +31 -3
- metadata +17 -15
- data/README.markdown +0 -49
data/lib/foreman/process.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require "foreman"
|
|
2
|
+
require "rubygems"
|
|
2
3
|
|
|
3
4
|
class Foreman::Process
|
|
4
5
|
|
|
@@ -14,10 +15,8 @@ class Foreman::Process
|
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def run(pipe, basedir, environment)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
run_process entry.command, pipe
|
|
20
|
-
end
|
|
18
|
+
with_environment(environment.merge("PORT" => port.to_s)) do
|
|
19
|
+
run_process basedir, entry.command, pipe
|
|
21
20
|
end
|
|
22
21
|
end
|
|
23
22
|
|
|
@@ -25,12 +24,52 @@ class Foreman::Process
|
|
|
25
24
|
"%s.%s" % [ entry.name, num ]
|
|
26
25
|
end
|
|
27
26
|
|
|
27
|
+
def kill(signal)
|
|
28
|
+
pid && Process.kill(signal, pid)
|
|
29
|
+
rescue Errno::ESRCH
|
|
30
|
+
false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def detach
|
|
34
|
+
pid && Process.detach(pid)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def alive?
|
|
38
|
+
kill(0)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def dead?
|
|
42
|
+
!alive?
|
|
43
|
+
end
|
|
44
|
+
|
|
28
45
|
private
|
|
29
46
|
|
|
30
|
-
def
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
47
|
+
def fork_with_io(command, basedir)
|
|
48
|
+
reader, writer = IO.pipe
|
|
49
|
+
command = replace_command_env(command)
|
|
50
|
+
pid = if Foreman.windows?
|
|
51
|
+
Dir.chdir(basedir) do
|
|
52
|
+
Process.spawn command, :out => writer, :err => writer
|
|
53
|
+
end
|
|
54
|
+
elsif Foreman.jruby?
|
|
55
|
+
require "posix/spawn"
|
|
56
|
+
POSIX::Spawn.spawn(Foreman.runner, "-d", basedir, command, {
|
|
57
|
+
:out => writer, :err => writer
|
|
58
|
+
})
|
|
59
|
+
else
|
|
60
|
+
fork do
|
|
61
|
+
writer.sync = true
|
|
62
|
+
$stdout.reopen writer
|
|
63
|
+
$stderr.reopen writer
|
|
64
|
+
reader.close
|
|
65
|
+
exec Foreman.runner, "-d", basedir, command
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
[ reader, pid ]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def run_process(basedir, command, pipe)
|
|
72
|
+
io, @pid = fork_with_io(command, basedir)
|
|
34
73
|
output pipe, "started with pid %d" % @pid
|
|
35
74
|
Thread.new do
|
|
36
75
|
until io.eof?
|
|
@@ -48,12 +87,10 @@ private
|
|
|
48
87
|
end
|
|
49
88
|
|
|
50
89
|
def with_environment(environment)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
ret
|
|
90
|
+
original = ENV.to_hash
|
|
91
|
+
ENV.update environment
|
|
92
|
+
yield
|
|
93
|
+
ensure
|
|
94
|
+
ENV.replace original
|
|
57
95
|
end
|
|
58
|
-
|
|
59
96
|
end
|
data/lib/foreman/utils.rb
CHANGED
|
@@ -5,7 +5,10 @@ class Foreman::Utils
|
|
|
5
5
|
def self.parse_concurrency(concurrency)
|
|
6
6
|
begin
|
|
7
7
|
pairs = concurrency.to_s.gsub(/\s/, "").split(",")
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
default = concurrency.nil? ? 1 : 0
|
|
10
|
+
|
|
11
|
+
pairs.inject(Hash.new(default)) do |hash, pair|
|
|
9
12
|
process, amount = pair.split("=")
|
|
10
13
|
hash.update(process => amount.to_i)
|
|
11
14
|
end
|
data/lib/foreman/version.rb
CHANGED
data/lib/foreman.rb
CHANGED
|
@@ -14,5 +14,12 @@ module Foreman
|
|
|
14
14
|
File.expand_path("../../bin/runner", __FILE__)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
def self.jruby?
|
|
18
|
+
defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java"
|
|
19
|
+
end
|
|
18
20
|
|
|
21
|
+
def self.windows?
|
|
22
|
+
defined?(RUBY_PLATFORM) and RUBY_PLATFORM =~ /(win|w)32$/
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
data/man/foreman.1
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
.\" generated with Ronn/v0.7.3
|
|
2
2
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
|
3
3
|
.
|
|
4
|
-
.TH "FOREMAN" "1" "
|
|
4
|
+
.TH "FOREMAN" "1" "January 2012" "Foreman 0.33.1" "Foreman Manual"
|
|
5
5
|
.
|
|
6
6
|
.SH "NAME"
|
|
7
7
|
\fBforeman\fR \- manage Procfile\-based applications
|
|
@@ -68,6 +68,10 @@ Specify the user the application should be run as\. Defaults to the app name
|
|
|
68
68
|
These options control all modes of foreman\'s operation\.
|
|
69
69
|
.
|
|
70
70
|
.TP
|
|
71
|
+
\fB\-d\fR, \fB\-\-directory\fR
|
|
72
|
+
Specify an alternate application root\. This defaults to the directory containing the Procfile\.
|
|
73
|
+
.
|
|
74
|
+
.TP
|
|
71
75
|
\fB\-e\fR, \fB\-\-env\fR
|
|
72
76
|
Specify an alternate environment file\. You can specify more than one file by using: \fB\-\-env file1,file2\fR\.
|
|
73
77
|
.
|
data/spec/foreman/cli_spec.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
require "foreman/cli"
|
|
3
3
|
|
|
4
|
-
describe "Foreman::CLI" do
|
|
4
|
+
describe "Foreman::CLI", :fakefs do
|
|
5
5
|
subject { Foreman::CLI.new }
|
|
6
6
|
|
|
7
7
|
describe "start" do
|
|
@@ -27,10 +27,21 @@ describe "Foreman::CLI" do
|
|
|
27
27
|
|
|
28
28
|
describe "export" do
|
|
29
29
|
describe "options" do
|
|
30
|
+
it "uses .foreman" do
|
|
31
|
+
write_procfile
|
|
32
|
+
File.open(".foreman", "w") { |f| f.puts "concurrency: alpha=2" }
|
|
33
|
+
mock_export = mock(Foreman::Export::Upstart)
|
|
34
|
+
mock(Foreman::Export::Upstart).new("/upstart", is_a(Foreman::Engine), { "concurrency" => "alpha=2" }) { mock_export }
|
|
35
|
+
mock_export.export
|
|
36
|
+
foreman %{ export upstart /upstart }
|
|
37
|
+
end
|
|
38
|
+
|
|
30
39
|
it "respects --env" do
|
|
31
40
|
write_procfile
|
|
32
41
|
write_env("envfile")
|
|
33
|
-
mock
|
|
42
|
+
mock_export = mock(Foreman::Export::Upstart)
|
|
43
|
+
mock(Foreman::Export::Upstart).new("/upstart", is_a(Foreman::Engine), { "env" => "envfile" }) { mock_export }
|
|
44
|
+
mock_export.export
|
|
34
45
|
foreman %{ export upstart /upstart --env envfile }
|
|
35
46
|
end
|
|
36
47
|
end
|
|
@@ -47,10 +58,18 @@ describe "Foreman::CLI" do
|
|
|
47
58
|
describe "with a Procfile" do
|
|
48
59
|
before(:each) { write_procfile }
|
|
49
60
|
|
|
50
|
-
describe "with
|
|
61
|
+
describe "with a formatter with a generic error" do
|
|
62
|
+
before do
|
|
63
|
+
mock(Foreman::Export).formatter("errorful") { Class.new(Foreman::Export::Base) do
|
|
64
|
+
def export
|
|
65
|
+
raise Foreman::Export::Exception.new("foo")
|
|
66
|
+
end
|
|
67
|
+
end }
|
|
68
|
+
end
|
|
69
|
+
|
|
51
70
|
it "prints an error" do
|
|
52
|
-
mock_error(subject, "
|
|
53
|
-
subject.export("
|
|
71
|
+
mock_error(subject, "foo") do
|
|
72
|
+
subject.export("errorful")
|
|
54
73
|
end
|
|
55
74
|
end
|
|
56
75
|
end
|
|
@@ -60,7 +79,9 @@ describe "Foreman::CLI" do
|
|
|
60
79
|
|
|
61
80
|
it "runs successfully" do
|
|
62
81
|
dont_allow(subject).error
|
|
63
|
-
mock
|
|
82
|
+
mock_export = mock(Foreman::Export::Upstart)
|
|
83
|
+
mock(Foreman::Export::Upstart).new("/tmp/foo", is_a(Foreman::Engine), {}) { mock_export }
|
|
84
|
+
mock_export.export
|
|
64
85
|
subject.export("upstart", "/tmp/foo")
|
|
65
86
|
end
|
|
66
87
|
end
|
|
@@ -72,7 +93,7 @@ describe "Foreman::CLI" do
|
|
|
72
93
|
before { write_procfile }
|
|
73
94
|
|
|
74
95
|
it "displays the jobs" do
|
|
75
|
-
mock(subject).
|
|
96
|
+
mock(subject).puts("valid procfile detected (alpha, bravo)")
|
|
76
97
|
subject.check
|
|
77
98
|
end
|
|
78
99
|
end
|
|
@@ -90,4 +111,53 @@ describe "Foreman::CLI" do
|
|
|
90
111
|
end
|
|
91
112
|
end
|
|
92
113
|
|
|
114
|
+
describe "run" do
|
|
115
|
+
describe "with a valid Procfile" do
|
|
116
|
+
before { write_procfile }
|
|
117
|
+
|
|
118
|
+
describe "and a command" do
|
|
119
|
+
let(:command) { ["ls", "-l"] }
|
|
120
|
+
|
|
121
|
+
before(:each) do
|
|
122
|
+
stub(subject).exec
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "should load the environment file" do
|
|
126
|
+
write_env
|
|
127
|
+
preserving_env do
|
|
128
|
+
subject.run *command
|
|
129
|
+
ENV["FOO"].should == "bar"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
ENV["FOO"].should be_nil
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "should runute the command as a string" do
|
|
136
|
+
mock(subject).exec(command.join(" "))
|
|
137
|
+
subject.run *command
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
describe "and a non-existent command" do
|
|
142
|
+
let(:command) { "iuhtngrglhulhdfg" }
|
|
143
|
+
|
|
144
|
+
it "should print an error" do
|
|
145
|
+
mock_error(subject, "command not found: #{command}") do
|
|
146
|
+
subject.run command
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
describe "and a non-executable command" do
|
|
152
|
+
let(:command) { __FILE__ }
|
|
153
|
+
|
|
154
|
+
it "should print an error" do
|
|
155
|
+
mock_error(subject, "not executable: #{command}") do
|
|
156
|
+
subject.run command
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
93
163
|
end
|
data/spec/foreman/engine_spec.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
require "foreman/engine"
|
|
3
3
|
|
|
4
|
-
describe "Foreman::Engine" do
|
|
4
|
+
describe "Foreman::Engine", :fakefs do
|
|
5
5
|
subject { Foreman::Engine.new("Procfile", {}) }
|
|
6
6
|
|
|
7
7
|
describe "initialize" do
|
|
@@ -24,8 +24,8 @@ describe "Foreman::Engine" do
|
|
|
24
24
|
describe "start" do
|
|
25
25
|
it "forks the processes" do
|
|
26
26
|
write_procfile
|
|
27
|
-
mock.instance_of(Foreman::Process).run_process("./alpha", is_a(IO))
|
|
28
|
-
mock.instance_of(Foreman::Process).run_process("./bravo", is_a(IO))
|
|
27
|
+
mock.instance_of(Foreman::Process).run_process(Dir.pwd, "./alpha", is_a(IO))
|
|
28
|
+
mock.instance_of(Foreman::Process).run_process(Dir.pwd, "./bravo", is_a(IO))
|
|
29
29
|
mock(subject).watch_for_output
|
|
30
30
|
mock(subject).watch_for_termination
|
|
31
31
|
subject.start
|
|
@@ -34,8 +34,8 @@ describe "Foreman::Engine" do
|
|
|
34
34
|
it "handles concurrency" do
|
|
35
35
|
write_procfile
|
|
36
36
|
engine = Foreman::Engine.new("Procfile",:concurrency => "alpha=2")
|
|
37
|
-
mock.instance_of(Foreman::Process).run_process("./alpha", is_a(IO)).twice
|
|
38
|
-
mock.instance_of(Foreman::Process).run_process("./bravo", is_a(IO))
|
|
37
|
+
mock.instance_of(Foreman::Process).run_process(Dir.pwd, "./alpha", is_a(IO)).twice
|
|
38
|
+
mock.instance_of(Foreman::Process).run_process(Dir.pwd, "./bravo", is_a(IO)).never
|
|
39
39
|
mock(engine).watch_for_output
|
|
40
40
|
mock(engine).watch_for_termination
|
|
41
41
|
engine.start
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "foreman/export/base"
|
|
3
|
+
|
|
4
|
+
describe "Foreman::Export::Base" do
|
|
5
|
+
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile") }
|
|
6
|
+
let(:location) { "/tmp/init" }
|
|
7
|
+
let(:engine) { Foreman::Engine.new(procfile) }
|
|
8
|
+
let(:subject) { Foreman::Export::Base.new(location, engine) }
|
|
9
|
+
|
|
10
|
+
it "has a say method for displaying info" do
|
|
11
|
+
mock(subject).puts("[foreman export] foo")
|
|
12
|
+
subject.send(:say, "foo")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "export needs to be overridden" do
|
|
16
|
+
lambda { subject.export }.should raise_error("export method must be overridden")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "raises errors as a Foreman::Export::Exception" do
|
|
20
|
+
lambda { subject.send(:error, "foo") }.should raise_error(Foreman::Export::Exception, "foo")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -3,17 +3,34 @@ require "foreman/engine"
|
|
|
3
3
|
require "foreman/export/bluepill"
|
|
4
4
|
require "tmpdir"
|
|
5
5
|
|
|
6
|
-
describe Foreman::Export::Bluepill do
|
|
6
|
+
describe Foreman::Export::Bluepill, :fakefs do
|
|
7
7
|
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile") }
|
|
8
|
-
let(:engine)
|
|
9
|
-
let(:
|
|
8
|
+
let(:engine) { Foreman::Engine.new(procfile) }
|
|
9
|
+
let(:options) { Hash.new }
|
|
10
|
+
let(:bluepill) { Foreman::Export::Bluepill.new("/tmp/init", engine, options) }
|
|
10
11
|
|
|
11
12
|
before(:each) { load_export_templates_into_fakefs("bluepill") }
|
|
12
13
|
before(:each) { stub(bluepill).say }
|
|
13
14
|
|
|
14
15
|
it "exports to the filesystem" do
|
|
15
|
-
bluepill.export
|
|
16
|
-
File.read("/tmp/init/app.pill").should == example_export_file("bluepill/app.pill")
|
|
16
|
+
bluepill.export
|
|
17
|
+
normalize_space(File.read("/tmp/init/app.pill")).should == normalize_space(example_export_file("bluepill/app.pill"))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "cleans up if exporting into an existing dir" do
|
|
21
|
+
mock(FileUtils).rm("/tmp/init/app.pill")
|
|
22
|
+
|
|
23
|
+
bluepill.export
|
|
24
|
+
bluepill.export
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "with concurrency" do
|
|
28
|
+
let(:options) { Hash[:concurrency => "alpha=2"] }
|
|
29
|
+
|
|
30
|
+
it "exports to the filesystem with concurrency" do
|
|
31
|
+
bluepill.export
|
|
32
|
+
normalize_space(File.read("/tmp/init/app.pill")).should == normalize_space(example_export_file("bluepill/app-concurrency.pill"))
|
|
33
|
+
end
|
|
17
34
|
end
|
|
18
35
|
|
|
19
36
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "foreman/engine"
|
|
3
|
+
require "foreman/export/inittab"
|
|
4
|
+
require "tmpdir"
|
|
5
|
+
|
|
6
|
+
describe Foreman::Export::Inittab, :fakefs do
|
|
7
|
+
let(:location) { "/tmp/inittab" }
|
|
8
|
+
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile") }
|
|
9
|
+
let(:location) { "/tmp/inittab" }
|
|
10
|
+
let(:engine) { Foreman::Engine.new(procfile) }
|
|
11
|
+
let(:options) { Hash.new }
|
|
12
|
+
let(:inittab) { Foreman::Export::Inittab.new(location, engine, options) }
|
|
13
|
+
|
|
14
|
+
before(:each) { load_export_templates_into_fakefs("inittab") }
|
|
15
|
+
before(:each) { stub(inittab).say }
|
|
16
|
+
|
|
17
|
+
it "exports to the filesystem" do
|
|
18
|
+
inittab.export
|
|
19
|
+
File.read("/tmp/inittab").should == example_export_file("inittab/inittab.default")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "to stdout" do
|
|
23
|
+
let(:location) { "-" }
|
|
24
|
+
|
|
25
|
+
it "exports to stdout" do
|
|
26
|
+
mock(inittab).puts example_export_file("inittab/inittab.default")
|
|
27
|
+
inittab.export
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context "with concurrency" do
|
|
32
|
+
let(:options) { Hash[:concurrency => "alpha=2"] }
|
|
33
|
+
|
|
34
|
+
it "exports to the filesystem with concurrency" do
|
|
35
|
+
inittab.export
|
|
36
|
+
File.read("/tmp/inittab").should == example_export_file("inittab/inittab.concurrency")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
@@ -3,33 +3,39 @@ require "foreman/engine"
|
|
|
3
3
|
require "foreman/export/runit"
|
|
4
4
|
require "tmpdir"
|
|
5
5
|
|
|
6
|
-
describe Foreman::Export::Runit do
|
|
6
|
+
describe Foreman::Export::Runit, :fakefs do
|
|
7
7
|
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile", 'bar=baz') }
|
|
8
8
|
let(:engine) { Foreman::Engine.new(procfile) }
|
|
9
|
-
let(:runit) { Foreman::Export::Runit.new(engine) }
|
|
10
|
-
|
|
9
|
+
let(:runit) { Foreman::Export::Runit.new('/tmp/init', engine, :concurrency => 'alpha=2,bravo=1') }
|
|
10
|
+
|
|
11
11
|
before(:each) { load_export_templates_into_fakefs("runit") }
|
|
12
12
|
before(:each) { stub(runit).say }
|
|
13
|
-
|
|
13
|
+
before(:each) { stub(FakeFS::FileUtils).chmod }
|
|
14
|
+
|
|
14
15
|
it "exports to the filesystem" do
|
|
15
16
|
FileUtils.mkdir_p('/tmp/init')
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
runit.export
|
|
19
|
+
|
|
18
20
|
File.read("/tmp/init/app-alpha-1/run").should == example_export_file('runit/app-alpha-1-run')
|
|
19
|
-
File.read("/tmp/init/app-alpha-1/log/run").should ==
|
|
21
|
+
File.read("/tmp/init/app-alpha-1/log/run").should ==
|
|
20
22
|
example_export_file('runit/app-alpha-1-log-run')
|
|
21
23
|
File.read("/tmp/init/app-alpha-1/env/PORT").should == "5000\n"
|
|
22
24
|
File.read("/tmp/init/app-alpha-1/env/BAR").should == "baz\n"
|
|
23
|
-
|
|
25
|
+
|
|
24
26
|
File.read("/tmp/init/app-alpha-2/run").should == example_export_file('runit/app-alpha-2-run')
|
|
25
|
-
File.read("/tmp/init/app-alpha-2/log/run").should ==
|
|
27
|
+
File.read("/tmp/init/app-alpha-2/log/run").should ==
|
|
26
28
|
example_export_file('runit/app-alpha-2-log-run')
|
|
27
29
|
File.read("/tmp/init/app-alpha-2/env/PORT").should == "5001\n"
|
|
28
30
|
File.read("/tmp/init/app-alpha-2/env/BAR").should == "baz\n"
|
|
29
|
-
|
|
31
|
+
|
|
30
32
|
File.read("/tmp/init/app-bravo-1/run").should == example_export_file('runit/app-bravo-1-run')
|
|
31
|
-
File.read("/tmp/init/app-bravo-1/log/run").should ==
|
|
33
|
+
File.read("/tmp/init/app-bravo-1/log/run").should ==
|
|
32
34
|
example_export_file('runit/app-bravo-1-log-run')
|
|
33
35
|
File.read("/tmp/init/app-bravo-1/env/PORT").should == "5100\n"
|
|
34
36
|
end
|
|
35
|
-
|
|
37
|
+
|
|
38
|
+
it "creates a full path to the export directory" do
|
|
39
|
+
expect { runit.export }.to_not raise_error(Errno::ENOENT)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -3,27 +3,53 @@ require "foreman/engine"
|
|
|
3
3
|
require "foreman/export/upstart"
|
|
4
4
|
require "tmpdir"
|
|
5
5
|
|
|
6
|
-
describe Foreman::Export::Upstart do
|
|
6
|
+
describe Foreman::Export::Upstart, :fakefs do
|
|
7
7
|
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile") }
|
|
8
|
-
let(:engine)
|
|
9
|
-
let(:
|
|
8
|
+
let(:engine) { Foreman::Engine.new(procfile) }
|
|
9
|
+
let(:options) { Hash.new }
|
|
10
|
+
let(:upstart) { Foreman::Export::Upstart.new("/tmp/init", engine, options) }
|
|
10
11
|
|
|
11
12
|
before(:each) { load_export_templates_into_fakefs("upstart") }
|
|
12
13
|
before(:each) { stub(upstart).say }
|
|
13
14
|
|
|
14
15
|
it "exports to the filesystem" do
|
|
15
|
-
upstart.export
|
|
16
|
+
upstart.export
|
|
16
17
|
|
|
17
18
|
File.read("/tmp/init/app.conf").should == example_export_file("upstart/app.conf")
|
|
18
19
|
File.read("/tmp/init/app-alpha.conf").should == example_export_file("upstart/app-alpha.conf")
|
|
19
20
|
File.read("/tmp/init/app-alpha-1.conf").should == example_export_file("upstart/app-alpha-1.conf")
|
|
20
|
-
File.read("/tmp/init/app-alpha-2.conf").should == example_export_file("upstart/app-alpha-2.conf")
|
|
21
21
|
File.read("/tmp/init/app-bravo.conf").should == example_export_file("upstart/app-bravo.conf")
|
|
22
22
|
File.read("/tmp/init/app-bravo-1.conf").should == example_export_file("upstart/app-bravo-1.conf")
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
it "cleans up if exporting into an existing dir" do
|
|
26
|
+
mock(FileUtils).rm("/tmp/init/app.conf")
|
|
27
|
+
mock(FileUtils).rm("/tmp/init/app-alpha.conf")
|
|
28
|
+
mock(FileUtils).rm("/tmp/init/app-alpha-1.conf")
|
|
29
|
+
mock(FileUtils).rm("/tmp/init/app-bravo.conf")
|
|
30
|
+
mock(FileUtils).rm("/tmp/init/app-bravo-1.conf")
|
|
31
|
+
|
|
32
|
+
upstart.export
|
|
33
|
+
upstart.export
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context "with concurrency" do
|
|
37
|
+
let(:options) { Hash[:concurrency => "alpha=2"] }
|
|
38
|
+
|
|
39
|
+
it "exports to the filesystem with concurrency" do
|
|
40
|
+
upstart.export
|
|
41
|
+
|
|
42
|
+
File.read("/tmp/init/app.conf").should == example_export_file("upstart/app.conf")
|
|
43
|
+
File.read("/tmp/init/app-alpha.conf").should == example_export_file("upstart/app-alpha.conf")
|
|
44
|
+
File.read("/tmp/init/app-alpha-1.conf").should == example_export_file("upstart/app-alpha-1.conf")
|
|
45
|
+
File.read("/tmp/init/app-alpha-2.conf").should == example_export_file("upstart/app-alpha-2.conf")
|
|
46
|
+
File.exists?("/tmp/init/app-bravo-1.conf").should == false
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
25
50
|
context "with alternate templates" do
|
|
26
51
|
let(:template_root) { "/tmp/alternate" }
|
|
52
|
+
let(:upstart) { Foreman::Export::Upstart.new("/tmp/init", engine, :template => template_root) }
|
|
27
53
|
|
|
28
54
|
before do
|
|
29
55
|
FileUtils.mkdir_p template_root
|
|
@@ -31,22 +57,28 @@ describe Foreman::Export::Upstart do
|
|
|
31
57
|
end
|
|
32
58
|
|
|
33
59
|
it "can export with alternate template files" do
|
|
34
|
-
upstart.export
|
|
60
|
+
upstart.export
|
|
35
61
|
|
|
36
62
|
File.read("/tmp/init/app.conf").should == "alternate_template\n"
|
|
37
63
|
end
|
|
38
64
|
end
|
|
39
65
|
|
|
40
66
|
context "with alternate templates from home dir" do
|
|
41
|
-
let(:default_template_root) {File.expand_path("
|
|
67
|
+
let(:default_template_root) {File.expand_path("#{ENV['HOME']}/.foreman/templates")}
|
|
42
68
|
|
|
43
69
|
before do
|
|
70
|
+
ENV['_FOREMAN_SPEC_HOME'] = ENV['HOME']
|
|
71
|
+
ENV['HOME'] = "/home/appuser"
|
|
44
72
|
FileUtils.mkdir_p default_template_root
|
|
45
73
|
File.open("#{default_template_root}/master.conf.erb", "w") { |f| f.puts "default_alternate_template" }
|
|
46
74
|
end
|
|
47
75
|
|
|
76
|
+
after do
|
|
77
|
+
ENV['HOME'] = ENV.delete('_FOREMAN_SPEC_HOME')
|
|
78
|
+
end
|
|
79
|
+
|
|
48
80
|
it "can export with alternate template files" do
|
|
49
|
-
upstart.export
|
|
81
|
+
upstart.export
|
|
50
82
|
|
|
51
83
|
File.read("/tmp/init/app.conf").should == "default_alternate_template\n"
|
|
52
84
|
end
|
data/spec/foreman/export_spec.rb
CHANGED
|
@@ -1,2 +1,24 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
require "foreman/export"
|
|
3
|
+
|
|
4
|
+
describe "Foreman::Export" do
|
|
5
|
+
subject { Foreman::Export }
|
|
6
|
+
|
|
7
|
+
describe "with a formatter that doesn't declare the appropriate class" do
|
|
8
|
+
it "prints an error" do
|
|
9
|
+
mock(subject).require("foreman/export/invalidformatter")
|
|
10
|
+
mock_export_error("Unknown export format: invalidformatter (no class Foreman::Export::Invalidformatter).") do
|
|
11
|
+
subject.formatter("invalidformatter")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "with an invalid formatter" do
|
|
17
|
+
|
|
18
|
+
it "prints an error" do
|
|
19
|
+
mock_export_error("Unknown export format: invalidformatter (unable to load file 'foreman/export/invalidformatter').") do
|
|
20
|
+
subject.formatter("invalidformatter")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "foreman/helpers"
|
|
3
|
+
|
|
4
|
+
describe "Foreman::Helpers" do
|
|
5
|
+
before do
|
|
6
|
+
module Foo
|
|
7
|
+
class Bar; end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
after do
|
|
12
|
+
Object.send(:remove_const, :Foo)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
subject { o = Object.new; o.extend(Foreman::Helpers); o }
|
|
16
|
+
|
|
17
|
+
it "should classify words" do
|
|
18
|
+
subject.classify("foo").should == "Foo"
|
|
19
|
+
subject.classify("foo-bar").should == "FooBar"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should constantize words" do
|
|
23
|
+
subject.constantize("Object").should == Object
|
|
24
|
+
subject.constantize("Foo::Bar").should == Foo::Bar
|
|
25
|
+
end
|
|
26
|
+
end
|