add more tests
This commit is contained in:
1 parent
7cb73f5c36
commit
224fe94dc2
15 files changed
+207
-39
No files matched your search
+3
-22
@@ -40,22 +40,11 @@ class Foreman::CLI < Thor
|
|||||||
method_option :port, :type => :numeric, :aliases => "-p"
|
method_option :port, :type => :numeric, :aliases => "-p"
|
||||||
method_option :user, :type => :string, :aliases => "-u"
|
method_option :user, :type => :string, :aliases => "-u"
|
||||||
method_option :template, :type => :string, :aliases => "-t"
|
method_option :template, :type => :string, :aliases => "-t"
|
||||||
method_option :concurrency, :type => :string, :aliases => "-c",
|
method_option :concurrency, :type => :string, :aliases => "-c", :banner => '"alpha=5,bar=3"'
|
||||||
:banner => '"alpha=5,bar=3"'
|
|
||||||
|
|
||||||
def export(format, location=nil)
|
def export(format, location=nil)
|
||||||
check_procfile!
|
check_procfile!
|
||||||
|
formatter = Foreman::Export.formatter(format)
|
||||||
begin
|
|
||||||
require "foreman/export/#{ format.tr('-', '_') }"
|
|
||||||
classy_format = classify(format)
|
|
||||||
formatter = constantize("Foreman::Export::#{ classy_format }")
|
|
||||||
rescue NameError => ex
|
|
||||||
error "Unknown export format: #{format} (no class Foreman::Export::#{ classy_format })."
|
|
||||||
rescue LoadError => ex
|
|
||||||
error "Unknown export format: #{format} (unable to load file 'foreman/export/#{ format.tr('-', '_') }')."
|
|
||||||
end
|
|
||||||
|
|
||||||
formatter.new(location, engine, options).export
|
formatter.new(location, engine, options).export
|
||||||
rescue Foreman::Export::Exception => ex
|
rescue Foreman::Export::Exception => ex
|
||||||
error ex.message
|
error ex.message
|
||||||
@@ -65,7 +54,7 @@ class Foreman::CLI < Thor
|
|||||||
|
|
||||||
def check
|
def check
|
||||||
error "no processes defined" unless engine.procfile.entries.length > 0
|
error "no processes defined" unless engine.procfile.entries.length > 0
|
||||||
display "valid procfile detected (#{engine.procfile.process_names.join(', ')})"
|
puts "valid procfile detected (#{engine.procfile.process_names.join(', ')})"
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "run COMMAND", "Run a command using your application's environment"
|
desc "run COMMAND", "Run a command using your application's environment"
|
||||||
@@ -95,19 +84,11 @@ private ######################################################################
|
|||||||
options[:procfile] || "Procfile"
|
options[:procfile] || "Procfile"
|
||||||
end
|
end
|
||||||
|
|
||||||
def display(message)
|
|
||||||
puts message
|
|
||||||
end
|
|
||||||
|
|
||||||
def error(message)
|
def error(message)
|
||||||
puts "ERROR: #{message}"
|
puts "ERROR: #{message}"
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def procfile_exists?(procfile)
|
|
||||||
File.exist?(procfile)
|
|
||||||
end
|
|
||||||
|
|
||||||
def options
|
def options
|
||||||
original_options = super
|
original_options = super
|
||||||
return original_options unless File.exists?(".foreman")
|
return original_options unless File.exists?(".foreman")
|
||||||
|
|||||||
@@ -1,9 +1,30 @@
|
|||||||
require "foreman"
|
require "foreman"
|
||||||
|
require "foreman/helpers"
|
||||||
|
|
||||||
module Foreman::Export
|
module Foreman::Export
|
||||||
|
extend Foreman::Helpers
|
||||||
|
|
||||||
class Exception < ::Exception; end
|
class Exception < ::Exception; end
|
||||||
|
|
||||||
|
def self.formatter(format)
|
||||||
|
begin
|
||||||
|
require "foreman/export/#{ format.tr('-', '_') }"
|
||||||
|
classy_format = classify(format)
|
||||||
|
formatter = constantize("Foreman::Export::#{ classy_format }")
|
||||||
|
rescue NameError => ex
|
||||||
|
error "Unknown export format: #{format} (no class Foreman::Export::#{ classy_format })."
|
||||||
|
rescue LoadError => ex
|
||||||
|
error "Unknown export format: #{format} (unable to load file 'foreman/export/#{ format.tr('-', '_') }')."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.error(message)
|
||||||
|
raise Foreman::Export::Exception.new(message)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
require "foreman/export/base"
|
require "foreman/export/base"
|
||||||
require "foreman/export/inittab"
|
require "foreman/export/inittab"
|
||||||
require "foreman/export/upstart"
|
require "foreman/export/upstart"
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ class Foreman::Export::Inittab < Foreman::Export::Base
|
|||||||
|
|
||||||
inittab = inittab.join("\n") + "\n"
|
inittab = inittab.join("\n") + "\n"
|
||||||
|
|
||||||
if fname
|
if location == "-"
|
||||||
|
puts inittab
|
||||||
|
else
|
||||||
FileUtils.mkdir_p(log_root) rescue error "could not create #{log_root}"
|
FileUtils.mkdir_p(log_root) rescue error "could not create #{log_root}"
|
||||||
FileUtils.chown(user, nil, log_root) rescue error "could not chown #{log_root} to #{user}"
|
FileUtils.chown(user, nil, log_root) rescue error "could not chown #{log_root} to #{user}"
|
||||||
write_file(fname, inittab)
|
write_file(location, inittab)
|
||||||
else
|
|
||||||
puts inittab
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ module Foreman::Helpers
|
|||||||
# classify('job-name') # => 'JobName'
|
# classify('job-name') # => 'JobName'
|
||||||
def classify(dashed_word)
|
def classify(dashed_word)
|
||||||
dashed_word.split('-').each { |part| part[0] = part[0].chr.upcase }.join
|
dashed_word.split('-').each { |part| part[0] = part[0].chr.upcase }.join
|
||||||
end
|
end # Tries to find a constant with the name specified in the argument string:
|
||||||
|
|
||||||
# Tries to find a constant with the name specified in the argument string:
|
|
||||||
#
|
#
|
||||||
# constantize("Module") # => Module
|
# constantize("Module") # => Module
|
||||||
# constantize("Test::Unit") # => Test::Unit
|
# constantize("Test::Unit") # => Test::Unit
|
||||||
@@ -28,10 +27,6 @@ module Foreman::Helpers
|
|||||||
def constantize(camel_cased_word)
|
def constantize(camel_cased_word)
|
||||||
camel_cased_word = camel_cased_word.to_s
|
camel_cased_word = camel_cased_word.to_s
|
||||||
|
|
||||||
if camel_cased_word.include?('-')
|
|
||||||
camel_cased_word = classify(camel_cased_word)
|
|
||||||
end
|
|
||||||
|
|
||||||
names = camel_cased_word.split('::')
|
names = camel_cased_word.split('::')
|
||||||
names.shift if names.empty? || names.first.empty?
|
names.shift if names.empty? || names.first.empty?
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,15 @@ describe "Foreman::CLI", :fakefs do
|
|||||||
|
|
||||||
describe "export" do
|
describe "export" do
|
||||||
describe "options" do
|
describe "options" do
|
||||||
|
it "uses .foreman" do
|
||||||
|
write_procfile
|
||||||
|
File.open(".foreman", "w") { |f| f.puts "concurrency: alpha=2" }
|
||||||
|
mock_export = mock(Foreman::Export::Upstart)
|
||||||
|
mock(Foreman::Export::Upstart).new("/upstart", is_a(Foreman::Engine), { "concurrency" => "alpha=2" }) { mock_export }
|
||||||
|
mock_export.export
|
||||||
|
foreman %{ export upstart /upstart }
|
||||||
|
end
|
||||||
|
|
||||||
it "respects --env" do
|
it "respects --env" do
|
||||||
write_procfile
|
write_procfile
|
||||||
write_env("envfile")
|
write_env("envfile")
|
||||||
@@ -49,10 +58,18 @@ describe "Foreman::CLI", :fakefs do
|
|||||||
describe "with a Procfile" do
|
describe "with a Procfile" do
|
||||||
before(:each) { write_procfile }
|
before(:each) { write_procfile }
|
||||||
|
|
||||||
describe "with an invalid formatter" do
|
describe "with a formatter with a generic error" do
|
||||||
|
before do
|
||||||
|
mock(Foreman::Export).formatter("errorful") { Class.new(Foreman::Export::Base) do
|
||||||
|
def export
|
||||||
|
raise Foreman::Export::Exception.new("foo")
|
||||||
|
end
|
||||||
|
end }
|
||||||
|
end
|
||||||
|
|
||||||
it "prints an error" do
|
it "prints an error" do
|
||||||
mock_error(subject, "Unknown export format: invalidformatter (unable to load file 'foreman/export/invalidformatter').") do
|
mock_error(subject, "foo") do
|
||||||
subject.export("invalidformatter")
|
subject.export("errorful")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -76,7 +93,7 @@ describe "Foreman::CLI", :fakefs do
|
|||||||
before { write_procfile }
|
before { write_procfile }
|
||||||
|
|
||||||
it "displays the jobs" do
|
it "displays the jobs" do
|
||||||
mock(subject).display("valid procfile detected (alpha, bravo)")
|
mock(subject).puts("valid procfile detected (alpha, bravo)")
|
||||||
subject.check
|
subject.check
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
require "spec_helper"
|
||||||
|
require "foreman/export/base"
|
||||||
|
|
||||||
|
describe "Foreman::Export::Base" do
|
||||||
|
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile") }
|
||||||
|
let(:location) { "/tmp/init" }
|
||||||
|
let(:engine) { Foreman::Engine.new(procfile) }
|
||||||
|
let(:subject) { Foreman::Export::Base.new(location, engine) }
|
||||||
|
|
||||||
|
it "has a say method for displaying info" do
|
||||||
|
mock(subject).puts("[foreman export] foo")
|
||||||
|
subject.send(:say, "foo")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "export needs to be overridden" do
|
||||||
|
lambda { subject.export }.should raise_error("export method must be overridden")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises errors as a Foreman::Export::Exception" do
|
||||||
|
lambda { subject.send(:error, "foo") }.should raise_error(Foreman::Export::Exception, "foo")
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -17,7 +17,14 @@ describe Foreman::Export::Bluepill, :fakefs do
|
|||||||
normalize_space(File.read("/tmp/init/app.pill")).should == normalize_space(example_export_file("bluepill/app.pill"))
|
normalize_space(File.read("/tmp/init/app.pill")).should == normalize_space(example_export_file("bluepill/app.pill"))
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with concurrency" do
|
it "cleans up if exporting into an existing dir" do
|
||||||
|
mock(FileUtils).rm("/tmp/init/app.pill")
|
||||||
|
|
||||||
|
bluepill.export
|
||||||
|
bluepill.export
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with concurrency" do
|
||||||
let(:options) { Hash[:concurrency => "alpha=2"] }
|
let(:options) { Hash[:concurrency => "alpha=2"] }
|
||||||
|
|
||||||
it "exports to the filesystem with concurrency" do
|
it "exports to the filesystem with concurrency" do
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
require "spec_helper"
|
||||||
|
require "foreman/engine"
|
||||||
|
require "foreman/export/inittab"
|
||||||
|
require "tmpdir"
|
||||||
|
|
||||||
|
describe Foreman::Export::Inittab, :fakefs do
|
||||||
|
let(:location) { "/tmp/inittab" }
|
||||||
|
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile") }
|
||||||
|
let(:location) { "/tmp/inittab" }
|
||||||
|
let(:engine) { Foreman::Engine.new(procfile) }
|
||||||
|
let(:options) { Hash.new }
|
||||||
|
let(:inittab) { Foreman::Export::Inittab.new(location, engine, options) }
|
||||||
|
|
||||||
|
before(:each) { load_export_templates_into_fakefs("inittab") }
|
||||||
|
before(:each) { stub(inittab).say }
|
||||||
|
|
||||||
|
it "exports to the filesystem" do
|
||||||
|
inittab.export
|
||||||
|
File.read("/tmp/inittab").should == example_export_file("inittab/inittab.default")
|
||||||
|
end
|
||||||
|
|
||||||
|
context "to stdout" do
|
||||||
|
let(:location) { "-" }
|
||||||
|
|
||||||
|
it "exports to stdout" do
|
||||||
|
mock(inittab).puts example_export_file("inittab/inittab.default")
|
||||||
|
inittab.export
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with concurrency" do
|
||||||
|
let(:options) { Hash[:concurrency => "alpha=2"] }
|
||||||
|
|
||||||
|
it "exports to the filesystem with concurrency" do
|
||||||
|
inittab.export
|
||||||
|
File.read("/tmp/inittab").should == example_export_file("inittab/inittab.concurrency")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -22,6 +22,17 @@ describe Foreman::Export::Upstart, :fakefs do
|
|||||||
File.read("/tmp/init/app-bravo-1.conf").should == example_export_file("upstart/app-bravo-1.conf")
|
File.read("/tmp/init/app-bravo-1.conf").should == example_export_file("upstart/app-bravo-1.conf")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "cleans up if exporting into an existing dir" do
|
||||||
|
mock(FileUtils).rm("/tmp/init/app.conf")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-alpha.conf")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-alpha-1.conf")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-bravo.conf")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-bravo-1.conf")
|
||||||
|
|
||||||
|
upstart.export
|
||||||
|
upstart.export
|
||||||
|
end
|
||||||
|
|
||||||
context "with concurrency" do
|
context "with concurrency" do
|
||||||
let(:options) { Hash[:concurrency => "alpha=2"] }
|
let(:options) { Hash[:concurrency => "alpha=2"] }
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,24 @@
|
|||||||
require "spec_helper"
|
require "spec_helper"
|
||||||
require "foreman/export"
|
require "foreman/export"
|
||||||
|
|
||||||
|
describe "Foreman::Export" do
|
||||||
|
subject { Foreman::Export }
|
||||||
|
|
||||||
|
describe "with a formatter that doesn't declare the appropriate class" do
|
||||||
|
it "prints an error" do
|
||||||
|
mock(subject).require("foreman/export/invalidformatter")
|
||||||
|
mock_export_error("Unknown export format: invalidformatter (no class Foreman::Export::Invalidformatter).") do
|
||||||
|
subject.formatter("invalidformatter")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with an invalid formatter" do
|
||||||
|
|
||||||
|
it "prints an error" do
|
||||||
|
mock_export_error("Unknown export format: invalidformatter (unable to load file 'foreman/export/invalidformatter').") do
|
||||||
|
subject.formatter("invalidformatter")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
require "spec_helper"
|
||||||
|
require "foreman/helpers"
|
||||||
|
|
||||||
|
describe "Foreman::Helpers" do
|
||||||
|
before do
|
||||||
|
module Foo
|
||||||
|
class Bar; end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
Object.send(:remove_const, :Foo)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { o = Object.new; o.extend(Foreman::Helpers); o }
|
||||||
|
|
||||||
|
it "should classify words" do
|
||||||
|
subject.classify("foo").should == "Foo"
|
||||||
|
subject.classify("foo-bar").should == "FooBar"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should constantize words" do
|
||||||
|
subject.constantize("Object").should == Object
|
||||||
|
subject.constantize("Foo::Bar").should == Foo::Bar
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -25,4 +25,10 @@ describe Foreman do
|
|||||||
ENV['FOO'].should == 'bar'
|
ENV['FOO'].should == 'bar'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "runner" do
|
||||||
|
it "should exist" do
|
||||||
|
File.exists?(Foreman.runner).should == true
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# ----- foreman app processes -----
|
||||||
|
AP01:4:respawn:/bin/su - app -c 'PORT=5000 ./alpha >> /var/log/app/alpha-1.log 2>&1'
|
||||||
|
AP02:4:respawn:/bin/su - app -c 'PORT=5001 ./alpha >> /var/log/app/alpha-2.log 2>&1'
|
||||||
|
# ----- end foreman app processes -----
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# ----- foreman app processes -----
|
||||||
|
AP01:4:respawn:/bin/su - app -c 'PORT=5000 ./alpha >> /var/log/app/alpha-1.log 2>&1'
|
||||||
|
AP02:4:respawn:/bin/su - app -c 'PORT=5100 ./bravo >> /var/log/app/bravo-1.log 2>&1'
|
||||||
|
# ----- end foreman app processes -----
|
||||||
+14
-2
@@ -1,10 +1,20 @@
|
|||||||
require "rubygems"
|
require "rubygems"
|
||||||
|
|
||||||
|
require "simplecov"
|
||||||
|
SimpleCov.start do
|
||||||
|
add_filter "/spec/"
|
||||||
|
end
|
||||||
|
|
||||||
require "rspec"
|
require "rspec"
|
||||||
require "fakefs/safe"
|
require "fakefs/safe"
|
||||||
require "fakefs/spec_helpers"
|
require "fakefs/spec_helpers"
|
||||||
|
|
||||||
$:.unshift File.expand_path("../../lib", __FILE__)
|
$:.unshift File.expand_path("../../lib", __FILE__)
|
||||||
|
|
||||||
|
def mock_export_error(message)
|
||||||
|
lambda { yield }.should raise_error(Foreman::Export::Exception, message)
|
||||||
|
end
|
||||||
|
|
||||||
def mock_error(subject, message)
|
def mock_error(subject, message)
|
||||||
mock_exit do
|
mock_exit do
|
||||||
mock(subject).puts("ERROR: #{message}")
|
mock(subject).puts("ERROR: #{message}")
|
||||||
@@ -37,9 +47,11 @@ def write_procfile(procfile="Procfile", alpha_env="")
|
|||||||
File.expand_path(procfile)
|
File.expand_path(procfile)
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_env(env=".env")
|
def write_env(env=".env", options={"FOO"=>"bar"})
|
||||||
File.open(env, "w") do |file|
|
File.open(env, "w") do |file|
|
||||||
file.puts "FOO=bar"
|
options.each do |key, val|
|
||||||
|
file.puts "#{key}=#{val}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user