foreman 0.36.1 → 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 +8 -22
- data/lib/foreman/engine.rb +26 -16
- data/lib/foreman/export/base.rb +11 -4
- data/lib/foreman/export/bluepill.rb +5 -7
- data/lib/foreman/export/inittab.rb +10 -12
- data/lib/foreman/export/runit.rb +8 -10
- 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 +47 -21
- data/lib/foreman/version.rb +1 -1
- data/lib/foreman.rb +8 -1
- data/spec/foreman/cli_spec.rb +37 -16
- data/spec/foreman/engine_spec.rb +5 -5
- data/spec/foreman/export/base_spec.rb +22 -0
- data/spec/foreman/export/bluepill_spec.rb +21 -9
- data/spec/foreman/export/inittab_spec.rb +40 -0
- data/spec/foreman/export/runit_spec.rb +17 -12
- data/spec/foreman/export/upstart_spec.rb +30 -13
- 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 +3 -3
- data/spec/resources/export/inittab/inittab.concurrency +4 -0
- data/spec/resources/export/inittab/inittab.default +4 -0
- data/spec/spec_helper.rb +17 -4
- metadata +14 -14
- data/README.markdown +0 -50
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
|
|
@@ -89,47 +110,47 @@ describe "Foreman::CLI" do
|
|
|
89
110
|
end
|
|
90
111
|
end
|
|
91
112
|
end
|
|
92
|
-
|
|
113
|
+
|
|
93
114
|
describe "run" do
|
|
94
115
|
describe "with a valid Procfile" do
|
|
95
116
|
before { write_procfile }
|
|
96
117
|
|
|
97
118
|
describe "and a command" do
|
|
98
119
|
let(:command) { ["ls", "-l"] }
|
|
99
|
-
|
|
120
|
+
|
|
100
121
|
before(:each) do
|
|
101
122
|
stub(subject).exec
|
|
102
123
|
end
|
|
103
|
-
|
|
124
|
+
|
|
104
125
|
it "should load the environment file" do
|
|
105
126
|
write_env
|
|
106
127
|
preserving_env do
|
|
107
128
|
subject.run *command
|
|
108
129
|
ENV["FOO"].should == "bar"
|
|
109
130
|
end
|
|
110
|
-
|
|
131
|
+
|
|
111
132
|
ENV["FOO"].should be_nil
|
|
112
133
|
end
|
|
113
|
-
|
|
134
|
+
|
|
114
135
|
it "should runute the command as a string" do
|
|
115
136
|
mock(subject).exec(command.join(" "))
|
|
116
137
|
subject.run *command
|
|
117
138
|
end
|
|
118
139
|
end
|
|
119
|
-
|
|
140
|
+
|
|
120
141
|
describe "and a non-existent command" do
|
|
121
142
|
let(:command) { "iuhtngrglhulhdfg" }
|
|
122
|
-
|
|
143
|
+
|
|
123
144
|
it "should print an error" do
|
|
124
145
|
mock_error(subject, "command not found: #{command}") do
|
|
125
146
|
subject.run command
|
|
126
147
|
end
|
|
127
148
|
end
|
|
128
149
|
end
|
|
129
|
-
|
|
150
|
+
|
|
130
151
|
describe "and a non-executable command" do
|
|
131
152
|
let(:command) { __FILE__ }
|
|
132
|
-
|
|
153
|
+
|
|
133
154
|
it "should print an error" do
|
|
134
155
|
mock_error(subject, "not executable: #{command}") do
|
|
135
156
|
subject.run command
|
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)).never
|
|
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,22 +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
|
+
bluepill.export
|
|
16
17
|
normalize_space(File.read("/tmp/init/app.pill")).should == normalize_space(example_export_file("bluepill/app.pill"))
|
|
17
18
|
end
|
|
18
19
|
|
|
19
|
-
it "
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
|
23
25
|
end
|
|
24
|
-
|
|
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
|
|
34
|
+
end
|
|
35
|
+
|
|
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,34 +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
15
|
it "exports to the filesystem" do
|
|
16
16
|
FileUtils.mkdir_p('/tmp/init')
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
|
|
18
|
+
runit.export
|
|
19
|
+
|
|
19
20
|
File.read("/tmp/init/app-alpha-1/run").should == example_export_file('runit/app-alpha-1-run')
|
|
20
|
-
File.read("/tmp/init/app-alpha-1/log/run").should ==
|
|
21
|
+
File.read("/tmp/init/app-alpha-1/log/run").should ==
|
|
21
22
|
example_export_file('runit/app-alpha-1-log-run')
|
|
22
23
|
File.read("/tmp/init/app-alpha-1/env/PORT").should == "5000\n"
|
|
23
24
|
File.read("/tmp/init/app-alpha-1/env/BAR").should == "baz\n"
|
|
24
|
-
|
|
25
|
+
|
|
25
26
|
File.read("/tmp/init/app-alpha-2/run").should == example_export_file('runit/app-alpha-2-run')
|
|
26
|
-
File.read("/tmp/init/app-alpha-2/log/run").should ==
|
|
27
|
+
File.read("/tmp/init/app-alpha-2/log/run").should ==
|
|
27
28
|
example_export_file('runit/app-alpha-2-log-run')
|
|
28
29
|
File.read("/tmp/init/app-alpha-2/env/PORT").should == "5001\n"
|
|
29
30
|
File.read("/tmp/init/app-alpha-2/env/BAR").should == "baz\n"
|
|
30
|
-
|
|
31
|
+
|
|
31
32
|
File.read("/tmp/init/app-bravo-1/run").should == example_export_file('runit/app-bravo-1-run')
|
|
32
|
-
File.read("/tmp/init/app-bravo-1/log/run").should ==
|
|
33
|
+
File.read("/tmp/init/app-bravo-1/log/run").should ==
|
|
33
34
|
example_export_file('runit/app-bravo-1-log-run')
|
|
34
35
|
File.read("/tmp/init/app-bravo-1/env/PORT").should == "5100\n"
|
|
35
36
|
end
|
|
36
|
-
|
|
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,16 +3,17 @@ 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")
|
|
@@ -21,18 +22,34 @@ describe Foreman::Export::Upstart do
|
|
|
21
22
|
File.read("/tmp/init/app-bravo-1.conf").should == example_export_file("upstart/app-bravo-1.conf")
|
|
22
23
|
end
|
|
23
24
|
|
|
24
|
-
it "
|
|
25
|
-
|
|
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")
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
|
32
48
|
end
|
|
33
49
|
|
|
34
50
|
context "with alternate templates" do
|
|
35
51
|
let(:template_root) { "/tmp/alternate" }
|
|
52
|
+
let(:upstart) { Foreman::Export::Upstart.new("/tmp/init", engine, :template => template_root) }
|
|
36
53
|
|
|
37
54
|
before do
|
|
38
55
|
FileUtils.mkdir_p template_root
|
|
@@ -40,7 +57,7 @@ describe Foreman::Export::Upstart do
|
|
|
40
57
|
end
|
|
41
58
|
|
|
42
59
|
it "can export with alternate template files" do
|
|
43
|
-
upstart.export
|
|
60
|
+
upstart.export
|
|
44
61
|
|
|
45
62
|
File.read("/tmp/init/app.conf").should == "alternate_template\n"
|
|
46
63
|
end
|
|
@@ -61,7 +78,7 @@ describe Foreman::Export::Upstart do
|
|
|
61
78
|
end
|
|
62
79
|
|
|
63
80
|
it "can export with alternate template files" do
|
|
64
|
-
upstart.export
|
|
81
|
+
upstart.export
|
|
65
82
|
|
|
66
83
|
File.read("/tmp/init/app.conf").should == "default_alternate_template\n"
|
|
67
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
|
|
@@ -1,2 +1,131 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'foreman/process'
|
|
3
|
+
require 'ostruct'
|
|
4
|
+
require 'timeout'
|
|
5
|
+
require 'tmpdir'
|
|
6
|
+
|
|
7
|
+
describe Foreman::Process do
|
|
8
|
+
subject { described_class.new entry, number, port }
|
|
9
|
+
|
|
10
|
+
let(:number) { 1 }
|
|
11
|
+
let(:port) { 777 }
|
|
12
|
+
let(:command) { "script" }
|
|
13
|
+
let(:name) { "foobar" }
|
|
14
|
+
let(:entry) { OpenStruct.new :name => name, :command => command }
|
|
15
|
+
|
|
16
|
+
its(:entry) { entry }
|
|
17
|
+
its(:num) { number }
|
|
18
|
+
its(:port) { port }
|
|
19
|
+
its(:name) { "#{name}.#{port}" }
|
|
20
|
+
its(:pid) { nil }
|
|
21
|
+
|
|
22
|
+
describe '#run' do
|
|
23
|
+
let(:pipe) { :pipe }
|
|
24
|
+
let(:basedir) { Dir.mktmpdir }
|
|
25
|
+
let(:env) {{ 'foo' => 'bar' }}
|
|
26
|
+
let(:init_delta) { 0.1 }
|
|
27
|
+
|
|
28
|
+
after { FileUtils.remove_entry_secure basedir }
|
|
29
|
+
|
|
30
|
+
def run(cmd=command)
|
|
31
|
+
entry.command = cmd
|
|
32
|
+
subject.run pipe, basedir, env
|
|
33
|
+
subject.detach && sleep(init_delta)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def run_file(executable, code)
|
|
37
|
+
file = File.open("#{basedir}/script", 'w') {|it| it << code }
|
|
38
|
+
run "#{executable} #{file.path}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context 'options' do
|
|
42
|
+
it 'should set PORT for environment' do
|
|
43
|
+
mock(subject).run_process(basedir, command, pipe) do
|
|
44
|
+
ENV['PORT'].should == port.to_s
|
|
45
|
+
end
|
|
46
|
+
run
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'should set custom variables for environment' do
|
|
50
|
+
mock(subject).run_process(basedir, command, pipe) do
|
|
51
|
+
ENV['foo'].should == 'bar'
|
|
52
|
+
end
|
|
53
|
+
run
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'should restore environment afterwards' do
|
|
57
|
+
mock(subject).run_process(basedir, command, pipe)
|
|
58
|
+
run
|
|
59
|
+
ENV.should_not include('PORT', 'foo')
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'process' do
|
|
64
|
+
around do |spec|
|
|
65
|
+
IO.pipe do |reader, writer|
|
|
66
|
+
@reader, @writer = reader, writer
|
|
67
|
+
spec.run
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
let(:pipe) { @writer }
|
|
72
|
+
let(:output) { @reader.read_nonblock 1024 }
|
|
73
|
+
|
|
74
|
+
it 'should not block' do
|
|
75
|
+
expect {
|
|
76
|
+
Timeout.timeout(2*init_delta) { run 'sleep 2' }
|
|
77
|
+
}.should_not raise_exception
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'should be alive' do
|
|
81
|
+
run 'sleep 1'
|
|
82
|
+
subject.should be_alive
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'should be dead' do
|
|
86
|
+
run 'exit'
|
|
87
|
+
subject.should be_dead
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'should be killable' do
|
|
91
|
+
run 'sleep 1'
|
|
92
|
+
subject.kill 'TERM'
|
|
93
|
+
subject.should be_dead
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'should send different signals' do
|
|
97
|
+
run_file 'ruby', <<-CODE
|
|
98
|
+
trap "TERM", "IGNORE"
|
|
99
|
+
loop { sleep 1 }
|
|
100
|
+
CODE
|
|
101
|
+
sleep 1 # wait for ruby to start
|
|
102
|
+
subject.should be_alive
|
|
103
|
+
subject.kill 'TERM'
|
|
104
|
+
subject.should be_alive
|
|
105
|
+
subject.kill 'KILL'
|
|
106
|
+
subject.should be_dead
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'should redirect stdout' do
|
|
110
|
+
run 'echo hey'
|
|
111
|
+
output.should include('hey')
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'should redirect stderr' do
|
|
115
|
+
run 'echo hey >2'
|
|
116
|
+
output.should include('hey')
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it 'should handle variables' do
|
|
120
|
+
run 'echo $PORT'
|
|
121
|
+
output.should include('777')
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it 'should handle arguments' do
|
|
125
|
+
pending
|
|
126
|
+
run %{ sh -c "trap '' TERM; sleep 10" }
|
|
127
|
+
subject.should be_alive
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
data/spec/foreman_spec.rb
CHANGED
|
@@ -8,13 +8,8 @@ describe Foreman do
|
|
|
8
8
|
it { should be_a String }
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
describe "::load_env!(env_file)" do
|
|
12
|
-
before do
|
|
13
|
-
FakeFS.activate!
|
|
14
|
-
end
|
|
15
|
-
|
|
11
|
+
describe "::load_env!(env_file)", :fakefs do
|
|
16
12
|
after do
|
|
17
|
-
FakeFS.deactivate!
|
|
18
13
|
ENV['FOO'] = nil
|
|
19
14
|
end
|
|
20
15
|
|
|
@@ -22,7 +17,7 @@ describe Foreman do
|
|
|
22
17
|
File.open("/tmp/env1", "w") { |f| f.puts("FOO=bar") }
|
|
23
18
|
Foreman.load_env!("/tmp/env1")
|
|
24
19
|
ENV['FOO'].should == 'bar'
|
|
25
|
-
end
|
|
20
|
+
end
|
|
26
21
|
|
|
27
22
|
it "should assume env_file in ./.env" do
|
|
28
23
|
File.open("./.env", "w") { |f| f.puts("FOO=bar") }
|
|
@@ -30,4 +25,10 @@ describe Foreman do
|
|
|
30
25
|
ENV['FOO'].should == 'bar'
|
|
31
26
|
end
|
|
32
27
|
end
|
|
28
|
+
|
|
29
|
+
describe "runner" do
|
|
30
|
+
it "should exist" do
|
|
31
|
+
File.exists?(Foreman.runner).should == true
|
|
32
|
+
end
|
|
33
|
+
end
|
|
33
34
|
end
|
data/spec/helper_spec.rb
CHANGED
|
@@ -3,16 +3,16 @@ require "spec_helper"
|
|
|
3
3
|
describe "spec helpers" do
|
|
4
4
|
describe "#preserving_env" do
|
|
5
5
|
after { ENV.delete "FOO" }
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
it "should remove added environment vars" do
|
|
8
8
|
preserving_env { ENV["FOO"] = "baz" }
|
|
9
9
|
ENV["FOO"].should == nil
|
|
10
10
|
end
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
it "should reset modified environment vars" do
|
|
13
13
|
ENV["FOO"] = "bar"
|
|
14
14
|
preserving_env { ENV["FOO"] = "baz"}
|
|
15
15
|
ENV["FOO"].should == "bar"
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
|
-
end
|
|
18
|
+
end
|