foreman 0.27.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.
Files changed (38) hide show
  1. data/README.md +39 -0
  2. data/bin/runner +36 -0
  3. data/data/export/bluepill/master.pill.erb +3 -3
  4. data/lib/foreman/cli.rb +34 -32
  5. data/lib/foreman/engine.rb +97 -78
  6. data/lib/foreman/export/base.rb +12 -5
  7. data/lib/foreman/export/bluepill.rb +5 -7
  8. data/lib/foreman/export/inittab.rb +11 -13
  9. data/lib/foreman/export/runit.rb +24 -25
  10. data/lib/foreman/export/upstart.rb +9 -11
  11. data/lib/foreman/export.rb +21 -0
  12. data/lib/foreman/helpers.rb +45 -0
  13. data/lib/foreman/process.rb +88 -6
  14. data/lib/foreman/procfile.rb +8 -7
  15. data/lib/foreman/procfile_entry.rb +22 -0
  16. data/lib/foreman/utils.rb +4 -1
  17. data/lib/foreman/version.rb +1 -1
  18. data/lib/foreman.rb +13 -1
  19. data/man/foreman.1 +5 -1
  20. data/spec/foreman/cli_spec.rb +77 -7
  21. data/spec/foreman/engine_spec.rb +13 -26
  22. data/spec/foreman/export/base_spec.rb +22 -0
  23. data/spec/foreman/export/bluepill_spec.rb +23 -7
  24. data/spec/foreman/export/inittab_spec.rb +40 -0
  25. data/spec/foreman/export/runit_spec.rb +18 -12
  26. data/spec/foreman/export/upstart_spec.rb +40 -8
  27. data/spec/foreman/export_spec.rb +22 -0
  28. data/spec/foreman/helpers_spec.rb +26 -0
  29. data/spec/foreman/process_spec.rb +131 -2
  30. data/spec/foreman_spec.rb +8 -7
  31. data/spec/helper_spec.rb +18 -0
  32. data/spec/resources/export/bluepill/app-concurrency.pill +47 -0
  33. data/spec/resources/export/bluepill/app.pill +1 -22
  34. data/spec/resources/export/inittab/inittab.concurrency +4 -0
  35. data/spec/resources/export/inittab/inittab.default +4 -0
  36. data/spec/spec_helper.rb +31 -3
  37. metadata +19 -15
  38. data/README.markdown +0 -49
@@ -3,37 +3,35 @@ require "foreman/export"
3
3
 
4
4
  class Foreman::Export::Upstart < Foreman::Export::Base
5
5
 
6
- def export(location, options={})
6
+ def export
7
7
  error("Must specify a location") unless location
8
8
 
9
9
  FileUtils.mkdir_p location
10
10
 
11
- app = options[:app] || File.basename(engine.directory)
12
- user = options[:user] || app
13
- log_root = options[:log] || "/var/log/#{app}"
14
- template_root = options[:template]
11
+ app = self.app || File.basename(engine.directory)
12
+ user = self.user || app
13
+ log_root = self.log || "/var/log/#{app}"
14
+ template_root = self.template
15
15
 
16
16
  Dir["#{location}/#{app}*.conf"].each do |file|
17
17
  say "cleaning up: #{file}"
18
18
  FileUtils.rm(file)
19
19
  end
20
20
 
21
- concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
22
-
23
21
  master_template = export_template("upstart", "master.conf.erb", template_root)
24
22
  master_config = ERB.new(master_template).result(binding)
25
23
  write_file "#{location}/#{app}.conf", master_config
26
24
 
27
25
  process_template = export_template("upstart", "process.conf.erb", template_root)
28
26
 
29
- engine.processes.each do |process|
30
- next if (conc = concurrency[process.name]) < 1
27
+ engine.procfile.entries.each do |process|
28
+ next if (conc = self.concurrency[process.name]) < 1
31
29
  process_master_template = export_template("upstart", "process_master.conf.erb", template_root)
32
30
  process_master_config = ERB.new(process_master_template).result(binding)
33
31
  write_file "#{location}/#{app}-#{process.name}.conf", process_master_config
34
32
 
35
- 1.upto(concurrency[process.name]) do |num|
36
- port = engine.port_for(process, num, options[:port])
33
+ 1.upto(self.concurrency[process.name]) do |num|
34
+ port = engine.port_for(process, num, self.port)
37
35
  process_config = ERB.new(process_template).result(binding)
38
36
  write_file "#{location}/#{app}-#{process.name}-#{num}.conf", process_config
39
37
  end
@@ -1,9 +1,30 @@
1
1
  require "foreman"
2
+ require "foreman/helpers"
2
3
 
3
4
  module Foreman::Export
5
+ extend Foreman::Helpers
6
+
4
7
  class Exception < ::Exception; end
8
+
9
+ def self.formatter(format)
10
+ begin
11
+ require "foreman/export/#{ format.tr('-', '_') }"
12
+ classy_format = classify(format)
13
+ formatter = constantize("Foreman::Export::#{ classy_format }")
14
+ rescue NameError => ex
15
+ error "Unknown export format: #{format} (no class Foreman::Export::#{ classy_format })."
16
+ rescue LoadError => ex
17
+ error "Unknown export format: #{format} (unable to load file 'foreman/export/#{ format.tr('-', '_') }')."
18
+ end
19
+ end
20
+
21
+ def self.error(message)
22
+ raise Foreman::Export::Exception.new(message)
23
+ end
24
+
5
25
  end
6
26
 
27
+
7
28
  require "foreman/export/base"
8
29
  require "foreman/export/inittab"
9
30
  require "foreman/export/upstart"
@@ -0,0 +1,45 @@
1
+ module Foreman::Helpers
2
+ # Copied whole sale from, https://github.com/defunkt/resque/
3
+
4
+ # Given a word with dashes, returns a camel cased version of it.
5
+ #
6
+ # classify('job-name') # => 'JobName'
7
+ def classify(dashed_word)
8
+ dashed_word.split('-').each { |part| part[0] = part[0].chr.upcase }.join
9
+ end # Tries to find a constant with the name specified in the argument string:
10
+
11
+ #
12
+ # constantize("Module") # => Module
13
+ # constantize("Test::Unit") # => Test::Unit
14
+ #
15
+ # The name is assumed to be the one of a top-level constant, no matter
16
+ # whether it starts with "::" or not. No lexical context is taken into
17
+ # account:
18
+ #
19
+ # C = 'outside'
20
+ # module M
21
+ # C = 'inside'
22
+ # C # => 'inside'
23
+ # constantize("C") # => 'outside', same as ::C
24
+ # end
25
+ #
26
+ # NameError is raised when the constant is unknown.
27
+ def constantize(camel_cased_word)
28
+ camel_cased_word = camel_cased_word.to_s
29
+
30
+ names = camel_cased_word.split('::')
31
+ names.shift if names.empty? || names.first.empty?
32
+
33
+ constant = Object
34
+ names.each do |name|
35
+ args = Module.method(:const_get).arity != 1 ? [false] : []
36
+
37
+ if constant.const_defined?(name, *args)
38
+ constant = constant.const_get(name)
39
+ else
40
+ constant = constant.const_missing(name)
41
+ end
42
+ end
43
+ constant
44
+ end
45
+ end
@@ -1,14 +1,96 @@
1
1
  require "foreman"
2
+ require "rubygems"
2
3
 
3
4
  class Foreman::Process
4
5
 
5
- attr_reader :name
6
- attr_reader :command
7
- attr_accessor :color
6
+ attr_reader :entry
7
+ attr_reader :num
8
+ attr_reader :pid
9
+ attr_reader :port
8
10
 
9
- def initialize(name, command)
10
- @name = name
11
- @command = command
11
+ def initialize(entry, num, port)
12
+ @entry = entry
13
+ @num = num
14
+ @port = port
12
15
  end
13
16
 
17
+ def run(pipe, basedir, environment)
18
+ with_environment(environment.merge("PORT" => port.to_s)) do
19
+ run_process basedir, entry.command, pipe
20
+ end
21
+ end
22
+
23
+ def name
24
+ "%s.%s" % [ entry.name, num ]
25
+ end
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
+
45
+ private
46
+
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)
73
+ output pipe, "started with pid %d" % @pid
74
+ Thread.new do
75
+ until io.eof?
76
+ output pipe, io.gets
77
+ end
78
+ end
79
+ end
80
+
81
+ def output(pipe, message)
82
+ pipe.puts "%s,%s" % [ name, message ]
83
+ end
84
+
85
+ def replace_command_env(command)
86
+ command.gsub(/\$(\w+)/) { |e| ENV[e[1..-1]] }
87
+ end
88
+
89
+ def with_environment(environment)
90
+ original = ENV.to_hash
91
+ ENV.update environment
92
+ yield
93
+ ensure
94
+ ENV.replace original
95
+ end
14
96
  end
@@ -1,4 +1,5 @@
1
1
  require "foreman"
2
+ require "foreman/procfile_entry"
2
3
 
3
4
  # A valid Procfile entry is captured by this regex.
4
5
  # All other lines are ignored.
@@ -10,18 +11,18 @@ require "foreman"
10
11
  #
11
12
  class Foreman::Procfile
12
13
 
13
- attr_reader :processes
14
+ attr_reader :entries
14
15
 
15
16
  def initialize(filename)
16
- @processes = parse_procfile(filename)
17
+ @entries = parse_procfile(filename)
17
18
  end
18
19
 
19
- def process_names
20
- processes.map(&:name)
20
+ def [](name)
21
+ entries.detect { |entry| entry.name == name }
21
22
  end
22
23
 
23
- def [](name)
24
- processes.detect { |process| process.name == name }
24
+ def process_names
25
+ entries.map(&:name)
25
26
  end
26
27
 
27
28
  private
@@ -29,7 +30,7 @@ private
29
30
  def parse_procfile(filename)
30
31
  File.read(filename).split("\n").map do |line|
31
32
  if line =~ /^([A-Za-z0-9_]+):\s*(.+)$/
32
- Foreman::Process.new($1, $2)
33
+ Foreman::ProcfileEntry.new($1, $2)
33
34
  end
34
35
  end.compact
35
36
  end
@@ -0,0 +1,22 @@
1
+ require "foreman"
2
+
3
+ class Foreman::ProcfileEntry
4
+
5
+ attr_reader :name
6
+ attr_reader :command
7
+ attr_accessor :color
8
+
9
+ def initialize(name, command)
10
+ @name = name
11
+ @command = command
12
+ end
13
+
14
+ def spawn(num, pipe, basedir, environment, base_port)
15
+ (1..num).to_a.map do |n|
16
+ process = Foreman::Process.new(self, n, base_port + (n-1))
17
+ process.run(pipe, basedir, environment)
18
+ process
19
+ end
20
+ end
21
+
22
+ 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
- pairs.inject(Hash.new(1)) do |hash, pair|
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
@@ -1,5 +1,5 @@
1
1
  module Foreman
2
2
 
3
- VERSION = "0.27.0"
3
+ VERSION = "0.37.0"
4
4
 
5
5
  end
data/lib/foreman.rb CHANGED
@@ -9,5 +9,17 @@ module Foreman
9
9
  require 'foreman/engine'
10
10
  Foreman::Engine.load_env!(env_file)
11
11
  end
12
- end
13
12
 
13
+ def self.runner
14
+ File.expand_path("../../bin/runner", __FILE__)
15
+ end
16
+
17
+ def self.jruby?
18
+ defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java"
19
+ end
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" "November 2011" "Foreman 0.26.0" "Foreman Manual"
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
  .
@@ -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.instance_of(Foreman::Export::Upstart).export("/upstart", { "env" => "envfile" })
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 an invalid formatter" do
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, "Unknown export format: invalidformatter.") do
53
- subject.export("invalidformatter")
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.instance_of(Foreman::Export::Upstart).export("/tmp/foo", {})
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).display("valid procfile detected (alpha, bravo)")
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
@@ -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,9 @@ describe "Foreman::Engine" do
24
24
  describe "start" do
25
25
  it "forks the processes" do
26
26
  write_procfile
27
- mock(subject).fork(subject.procfile["alpha"])
28
- mock(subject).fork(subject.procfile["bravo"])
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
+ mock(subject).watch_for_output
29
30
  mock(subject).watch_for_termination
30
31
  subject.start
31
32
  end
@@ -33,29 +34,14 @@ describe "Foreman::Engine" do
33
34
  it "handles concurrency" do
34
35
  write_procfile
35
36
  engine = Foreman::Engine.new("Procfile",:concurrency => "alpha=2")
36
- mock(engine).fork_individual(engine.procfile["alpha"], 1, 5000)
37
- mock(engine).fork_individual(engine.procfile["alpha"], 2, 5001)
38
- mock(engine).fork_individual(engine.procfile["bravo"], 1, 5100)
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
+ mock(engine).watch_for_output
39
40
  mock(engine).watch_for_termination
40
41
  engine.start
41
42
  end
42
43
  end
43
44
 
44
- describe "execute" do
45
- it "runs the processes" do
46
- write_procfile
47
- mock(subject).fork(subject.procfile["alpha"])
48
- mock(subject).watch_for_termination
49
- subject.execute("alpha")
50
- end
51
-
52
- it "shows an error running a process that doesnt exist" do
53
- write_procfile
54
- mock(subject).puts("ERROR: no such process: foo")
55
- lambda { subject.execute("foo") }.should raise_error(SystemExit)
56
- end
57
- end
58
-
59
45
  describe "environment" do
60
46
  before(:each) do
61
47
  write_procfile
@@ -66,9 +52,10 @@ describe "Foreman::Engine" do
66
52
  File.open("/tmp/env", "w") { |f| f.puts("FOO=baz") }
67
53
  engine = Foreman::Engine.new("Procfile", :env => "/tmp/env")
68
54
  stub(engine).info
55
+ mock(engine).spawn_processes
69
56
  mock(engine).watch_for_termination
70
57
  engine.environment.should == {"FOO"=>"baz"}
71
- engine.execute("alpha")
58
+ engine.start
72
59
  end
73
60
 
74
61
  it "should read more than one if specified" do
@@ -76,9 +63,10 @@ describe "Foreman::Engine" do
76
63
  File.open("/tmp/env2", "w") { |f| f.puts("BAZ=qux") }
77
64
  engine = Foreman::Engine.new("Procfile", :env => "/tmp/env1,/tmp/env2")
78
65
  stub(engine).info
66
+ mock(engine).spawn_processes
79
67
  mock(engine).watch_for_termination
80
68
  engine.environment.should == { "FOO"=>"bar", "BAZ"=>"qux" }
81
- engine.execute("alpha")
69
+ engine.start
82
70
  end
83
71
 
84
72
  it "should fail if specified and doesnt exist" do
@@ -89,11 +77,10 @@ describe "Foreman::Engine" do
89
77
  it "should read .env if none specified" do
90
78
  File.open(".env", "w") { |f| f.puts("FOO=qoo") }
91
79
  engine = Foreman::Engine.new("Procfile")
92
- stub(engine).info
80
+ mock(engine).spawn_processes
93
81
  mock(engine).watch_for_termination
94
- mock(engine).fork_individual(anything, anything, anything)
95
82
  engine.environment.should == {"FOO"=>"qoo"}
96
- engine.execute("bravo")
83
+ engine.start
97
84
  end
98
85
  end
99
86
  end
@@ -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,18 +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) { Foreman::Engine.new(procfile) }
9
- let(:bluepill) { Foreman::Export::Bluepill.new(engine) }
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("/tmp/init", :concurrency => "alpha=2")
16
-
17
- 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
18
  end
19
19
 
20
- end
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
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