vmc 0.5.0.rc1 → 0.5.0.rc2
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/lib/vmc/cli.rb +2 -1
- data/lib/vmc/cli/app/start.rb +81 -24
- data/lib/vmc/cli/space/create.rb +4 -0
- data/lib/vmc/cli/space/switch.rb +16 -0
- data/lib/vmc/cli/start/base.rb +21 -18
- data/lib/vmc/cli/user/base.rb +1 -1
- data/lib/vmc/cli/user/delete.rb +2 -0
- data/lib/vmc/version.rb +1 -1
- data/spec/assets/hello-sinatra/Gemfile.lock +17 -0
- data/spec/features/{new_user_flow_spec.rb → v1/new_user_flow_spec.rb} +12 -18
- data/spec/features/v2/account_lifecycle_spec.rb +64 -0
- data/spec/features/v2/push_flow_spec.rb +126 -0
- data/spec/spec_helper.rb +16 -3
- data/{lib/vmc/test_support → spec/support}/command_helper.rb +5 -5
- data/spec/support/config_helper.rb +15 -0
- data/spec/support/console_app_specker_matchers.rb +2 -2
- data/spec/support/fake_home_dir.rb +42 -0
- data/{lib/vmc/test_support → spec/support}/interact_helper.rb +1 -1
- data/spec/support/shared_examples/errors.rb +40 -0
- data/{lib/vmc/test_support/common_input_examples.rb → spec/support/shared_examples/input.rb} +0 -0
- data/spec/support/specker_runner.rb +17 -61
- data/spec/support/tracking_expector.rb +71 -0
- data/spec/vmc/cli/app/instances_spec.rb +3 -3
- data/spec/vmc/cli/app/start_spec.rb +201 -0
- data/spec/vmc/cli/app/stats_spec.rb +21 -15
- data/spec/vmc/cli/space/create_spec.rb +73 -0
- data/spec/vmc/cli/space/switch_space_spec.rb +55 -0
- data/spec/vmc/cli/start/info_spec.rb +3 -16
- data/spec/vmc/cli/start/login_spec.rb +97 -37
- data/spec/vmc/cli/start/logout_spec.rb +3 -16
- data/spec/vmc/cli/start/target_spec.rb +84 -0
- data/spec/vmc/cli/user/delete_spec.rb +51 -0
- data/spec/vmc/cli/user/passwd_spec.rb +1 -1
- data/spec/vmc/cli/user/register_spec.rb +1 -1
- data/spec/vmc/cli_spec.rb +38 -36
- metadata +65 -39
- data/lib/vmc/cli/space/take.rb +0 -16
- data/lib/vmc/test_support/fake_home_dir.rb +0 -16
data/spec/spec_helper.rb
CHANGED
@@ -6,6 +6,18 @@ require "cfoundry/test_support"
|
|
6
6
|
require "vmc"
|
7
7
|
require "vmc/test_support"
|
8
8
|
require "webmock"
|
9
|
+
require "ostruct"
|
10
|
+
|
11
|
+
INTEGRATE_WITH = ENV["INTEGRATE_WITH"] || "default"
|
12
|
+
|
13
|
+
def vmc_bin
|
14
|
+
vmc = File.expand_path("#{SPEC_ROOT}/../bin/vmc.dev")
|
15
|
+
if INTEGRATE_WITH != 'default'
|
16
|
+
"rvm #{INTEGRATE_WITH}@vmc do #{vmc}"
|
17
|
+
else
|
18
|
+
vmc
|
19
|
+
end
|
20
|
+
end
|
9
21
|
|
10
22
|
Dir[File.expand_path('../support/**/*.rb', __FILE__)].each do |file|
|
11
23
|
require file
|
@@ -20,9 +32,10 @@ RSpec.configure do |c|
|
|
20
32
|
c.filter_run_excluding :ruby19 => true
|
21
33
|
end
|
22
34
|
|
23
|
-
c.include
|
24
|
-
c.include
|
25
|
-
c.include
|
35
|
+
c.include FakeHomeDir
|
36
|
+
c.include CommandHelper
|
37
|
+
c.include InteractHelper
|
38
|
+
c.include ConfigHelper
|
26
39
|
|
27
40
|
c.before(:all) do
|
28
41
|
WebMock.disable_net_connect!
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module CommandHelper
|
2
2
|
def vmc(argv)
|
3
3
|
Mothership.new.exit_status 0
|
4
4
|
stub(VMC::CLI).exit { |code| code }
|
@@ -20,13 +20,13 @@ module VMC::TestSupport::CommandHelper
|
|
20
20
|
attr_reader :stdout, :stderr, :status
|
21
21
|
|
22
22
|
def capture_output
|
23
|
-
real_stdout = $stdout
|
24
|
-
real_stderr = $stderr
|
23
|
+
$real_stdout = $stdout
|
24
|
+
$real_stderr = $stderr
|
25
25
|
$stdout = @stdout = StringIO.new
|
26
26
|
$stderr = @stderr = StringIO.new
|
27
27
|
@status = yield
|
28
28
|
ensure
|
29
|
-
$stdout = real_stdout
|
30
|
-
$stderr = real_stderr
|
29
|
+
$stdout = $real_stdout
|
30
|
+
$stderr = $real_stderr
|
31
31
|
end
|
32
32
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ConfigHelper
|
2
|
+
def write_token_file(config={})
|
3
|
+
File.open(File.expand_path(tokens_file_path), 'w') do |f|
|
4
|
+
f.puts YAML.dump(
|
5
|
+
{ "https://api.some-domain.com" =>
|
6
|
+
{
|
7
|
+
:version => 2,
|
8
|
+
:token => 'bearer token',
|
9
|
+
:refresh_token => nil
|
10
|
+
}.merge(config)
|
11
|
+
}
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -10,7 +10,7 @@ module ConsoleAppSpeckerMatchers
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def matches?(runner)
|
13
|
-
raise InvalidInputError unless runner.
|
13
|
+
raise InvalidInputError unless runner.respond_to?(:expect)
|
14
14
|
expected = runner.expect(@expected_output, @timeout)
|
15
15
|
@full_output = runner.output
|
16
16
|
!!expected
|
@@ -32,7 +32,7 @@ module ConsoleAppSpeckerMatchers
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def matches?(runner)
|
35
|
-
raise InvalidInputError unless runner.
|
35
|
+
raise InvalidInputError unless runner.respond_to?(:exit_code)
|
36
36
|
|
37
37
|
begin
|
38
38
|
Timeout.timeout(5) do
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module FakeHomeDir
|
2
|
+
def self.included(klass)
|
3
|
+
super
|
4
|
+
klass.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def use_fake_home_dir(&block)
|
9
|
+
around do |example|
|
10
|
+
dir = instance_exec(&block)
|
11
|
+
with_fake_home_dir(dir) do
|
12
|
+
example.call
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def stub_home_dir_with(folder_name)
|
18
|
+
around do |example|
|
19
|
+
tmp_root = Dir.tmpdir
|
20
|
+
FileUtils.cp_r(File.expand_path("#{SPEC_ROOT}/fixtures/fake_home_dirs/#{folder_name}"), tmp_root)
|
21
|
+
fake_home_dir = "#{tmp_root}/#{folder_name}"
|
22
|
+
begin
|
23
|
+
with_fake_home_dir(fake_home_dir) do
|
24
|
+
example.call
|
25
|
+
end
|
26
|
+
ensure
|
27
|
+
FileUtils.rm_rf fake_home_dir
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def with_fake_home_dir(dir, &block)
|
34
|
+
original_home_dir = ENV['HOME']
|
35
|
+
ENV['HOME'] = dir
|
36
|
+
begin
|
37
|
+
block.call
|
38
|
+
ensure
|
39
|
+
ENV['HOME'] = original_home_dir
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
shared_examples_for "an error that's obvious to the user" do |options|
|
2
|
+
message = options[:with_message]
|
3
|
+
|
4
|
+
it "prints the message" do
|
5
|
+
subject
|
6
|
+
expect(stderr.string).to include message
|
7
|
+
end
|
8
|
+
|
9
|
+
it "sets the exit code to 1" do
|
10
|
+
mock(context).exit_status(1)
|
11
|
+
subject
|
12
|
+
end
|
13
|
+
|
14
|
+
it "does not mention ~/.vmc/crash" do
|
15
|
+
subject
|
16
|
+
expect(stderr.string).to_not include VMC::CRASH_FILE
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
shared_examples_for "an error that gets passed through" do |options|
|
21
|
+
before do
|
22
|
+
described_class.class_eval do
|
23
|
+
alias_method :wrap_errors_original, :wrap_errors
|
24
|
+
def wrap_errors
|
25
|
+
yield
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
after do
|
31
|
+
described_class.class_eval do
|
32
|
+
remove_method :wrap_errors
|
33
|
+
alias_method :wrap_errors, :wrap_errors_original
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "reraises the error" do
|
38
|
+
expect { subject }.to raise_error(options[:with_exception], options[:with_message])
|
39
|
+
end
|
40
|
+
end
|
data/{lib/vmc/test_support/common_input_examples.rb → spec/support/shared_examples/input.rb}
RENAMED
File without changes
|
@@ -1,18 +1,15 @@
|
|
1
|
-
require "expect"
|
2
1
|
require "pty"
|
3
2
|
|
4
3
|
class SpeckerRunner
|
5
|
-
attr_reader :output
|
6
|
-
|
7
4
|
def initialize(*args)
|
8
|
-
@output = ""
|
9
|
-
|
10
5
|
@stdout, slave = PTY.open
|
11
6
|
system("stty raw", :in => slave)
|
12
7
|
read, @stdin = IO.pipe
|
13
8
|
|
14
9
|
@pid = spawn(*(args.push(:in => read, :out => slave, :err => slave)))
|
15
10
|
|
11
|
+
@expector = TrackingExpector.new(@stdout, ENV["DEBUG_BACON"])
|
12
|
+
|
16
13
|
yield self
|
17
14
|
end
|
18
15
|
|
@@ -21,7 +18,7 @@ class SpeckerRunner
|
|
21
18
|
when Hash
|
22
19
|
expect_branches(matcher, timeout)
|
23
20
|
else
|
24
|
-
|
21
|
+
@expector.expect(matcher, timeout)
|
25
22
|
end
|
26
23
|
end
|
27
24
|
|
@@ -50,11 +47,23 @@ class SpeckerRunner
|
|
50
47
|
!!Process.getpgid(@pid)
|
51
48
|
end
|
52
49
|
|
50
|
+
def output
|
51
|
+
@expector.output
|
52
|
+
end
|
53
|
+
|
54
|
+
def debug
|
55
|
+
@expector.debug
|
56
|
+
end
|
57
|
+
|
58
|
+
def debug=(x)
|
59
|
+
@expector.debug = x
|
60
|
+
end
|
61
|
+
|
53
62
|
private
|
54
63
|
|
55
64
|
def expect_branches(branches, timeout)
|
56
65
|
branch_names = /#{branches.keys.collect { |k| Regexp.quote(k) }.join("|")}/
|
57
|
-
expected = @
|
66
|
+
expected = @expector.expect(branch_names, timeout)
|
58
67
|
return unless expected
|
59
68
|
|
60
69
|
data = expected.first.match(/(#{branch_names})$/)
|
@@ -67,57 +76,4 @@ class SpeckerRunner
|
|
67
76
|
rescue NoMethodError
|
68
77
|
status
|
69
78
|
end
|
70
|
-
|
71
|
-
def tracking_expect(pattern, timeout)
|
72
|
-
buffer = ''
|
73
|
-
|
74
|
-
case pattern
|
75
|
-
when String
|
76
|
-
pattern = Regexp.new(Regexp.quote(pattern))
|
77
|
-
when Regexp
|
78
|
-
else
|
79
|
-
raise TypeError, "unsupported pattern class: #{pattern.class}"
|
80
|
-
end
|
81
|
-
|
82
|
-
result = nil
|
83
|
-
position = 0
|
84
|
-
@unused ||= ""
|
85
|
-
|
86
|
-
while true
|
87
|
-
if !@unused.empty?
|
88
|
-
c = @unused.slice!(0).chr
|
89
|
-
elsif !IO.select([@stdout], nil, nil, timeout) || @stdout.eof?
|
90
|
-
@unused = buffer
|
91
|
-
break
|
92
|
-
else
|
93
|
-
c = @stdout.getc.chr
|
94
|
-
end
|
95
|
-
|
96
|
-
# wear your flip flops
|
97
|
-
unless (c == "\e") .. (c == "m")
|
98
|
-
if c == "\b"
|
99
|
-
if position > 0 && buffer[position - 1] && buffer[position - 1].chr != "\n"
|
100
|
-
position -= 1
|
101
|
-
end
|
102
|
-
else
|
103
|
-
if buffer.size > position
|
104
|
-
buffer[position] = c
|
105
|
-
else
|
106
|
-
buffer << c
|
107
|
-
end
|
108
|
-
|
109
|
-
position += 1
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
if matches = pattern.match(buffer)
|
114
|
-
result = [buffer, *matches.to_a[1..-1]]
|
115
|
-
break
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
@output << buffer
|
120
|
-
|
121
|
-
result
|
122
|
-
end
|
123
|
-
end
|
79
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class TrackingExpector
|
2
|
+
attr_reader :output
|
3
|
+
|
4
|
+
def initialize(out, debug = false)
|
5
|
+
@out = out
|
6
|
+
@debug = debug
|
7
|
+
@unused = ""
|
8
|
+
@output = ""
|
9
|
+
end
|
10
|
+
|
11
|
+
def expect(pattern, timeout = 5)
|
12
|
+
buffer = ''
|
13
|
+
|
14
|
+
case pattern
|
15
|
+
when String
|
16
|
+
pattern = Regexp.new(Regexp.quote(pattern))
|
17
|
+
when Regexp
|
18
|
+
else
|
19
|
+
raise TypeError, "unsupported pattern class: #{pattern.class}"
|
20
|
+
end
|
21
|
+
|
22
|
+
result = nil
|
23
|
+
position = 0
|
24
|
+
@unused ||= ""
|
25
|
+
|
26
|
+
while true
|
27
|
+
if !@unused.empty?
|
28
|
+
c = @unused.slice!(0).chr
|
29
|
+
elsif output_ended?(timeout)
|
30
|
+
@unused = buffer
|
31
|
+
break
|
32
|
+
else
|
33
|
+
c = @out.getc.chr
|
34
|
+
end
|
35
|
+
|
36
|
+
STDOUT.putc c if @debug
|
37
|
+
|
38
|
+
# wear your flip flops
|
39
|
+
unless (c == "\e") .. (c == "m")
|
40
|
+
if c == "\b"
|
41
|
+
if position > 0 && buffer[position - 1] && buffer[position - 1].chr != "\n"
|
42
|
+
position -= 1
|
43
|
+
end
|
44
|
+
else
|
45
|
+
if buffer.size > position
|
46
|
+
buffer[position] = c
|
47
|
+
else
|
48
|
+
buffer << c
|
49
|
+
end
|
50
|
+
|
51
|
+
position += 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if matches = pattern.match(buffer)
|
56
|
+
result = [buffer, *matches.to_a[1..-1]]
|
57
|
+
break
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
@output << buffer
|
62
|
+
|
63
|
+
result
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def output_ended?(timeout)
|
69
|
+
(@out.is_a?(IO) && !IO.select([@out], nil, nil, timeout)) || @out.eof?
|
70
|
+
end
|
71
|
+
end
|
@@ -3,18 +3,18 @@ require 'stringio'
|
|
3
3
|
|
4
4
|
describe VMC::App::Stats do
|
5
5
|
let(:global) { { :color => false } }
|
6
|
-
let(:inputs) { {:app => apps[0]} }
|
6
|
+
let(:inputs) { { :app => apps[0] } }
|
7
7
|
let(:given) { {} }
|
8
8
|
let(:client) { fake_client(:apps => apps) }
|
9
9
|
let(:apps) { [fake(:app, :name => "basic_app")] }
|
10
|
-
let(:time) { Time.local(2012,11,1,2,30)}
|
10
|
+
let(:time) { Time.local(2012, 11, 1, 2, 30) }
|
11
11
|
|
12
12
|
before do
|
13
13
|
any_instance_of(VMC::CLI) do |cli|
|
14
14
|
stub(cli).client { client }
|
15
15
|
stub(cli).precondition { nil }
|
16
16
|
end
|
17
|
-
stub(client
|
17
|
+
stub(client.base).instances(anything) do
|
18
18
|
{
|
19
19
|
"12" => {:state => "STOPPED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"},
|
20
20
|
"1" => {:state => "STOPPED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"},
|
@@ -0,0 +1,201 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "webmock/rspec"
|
3
|
+
|
4
|
+
describe VMC::App::Start do
|
5
|
+
include ConsoleAppSpeckerMatchers
|
6
|
+
|
7
|
+
let(:client) { fake_client :apps => [app] }
|
8
|
+
let(:app) { fake :app }
|
9
|
+
|
10
|
+
def output
|
11
|
+
stdout.rewind
|
12
|
+
TrackingExpector.new(stdout)
|
13
|
+
end
|
14
|
+
|
15
|
+
def error_output
|
16
|
+
stderr.rewind
|
17
|
+
TrackingExpector.new(stderr)
|
18
|
+
end
|
19
|
+
|
20
|
+
before do
|
21
|
+
any_instance_of described_class do |cli|
|
22
|
+
stub(cli).precondition
|
23
|
+
stub(cli).client { client }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
before(:all) do
|
28
|
+
described_class.class_eval do
|
29
|
+
def wrap_errors
|
30
|
+
yield
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
after(:all) do
|
36
|
+
described_class.class_eval do
|
37
|
+
remove_method :wrap_errors
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
subject { vmc %W[start #{app.name} --no-quiet] }
|
42
|
+
|
43
|
+
context "with an app that's already started" do
|
44
|
+
let(:app) { fake :app, :state => "STARTED" }
|
45
|
+
|
46
|
+
it "skips starting the application" do
|
47
|
+
dont_allow(app).start!
|
48
|
+
subject
|
49
|
+
end
|
50
|
+
|
51
|
+
it "says the app is already started" do
|
52
|
+
subject
|
53
|
+
expect(error_output).to say("Application #{app.name} is already started.")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "with an app that's NOT already started" do
|
58
|
+
def self.it_says_application_is_starting
|
59
|
+
it "says that it's starting the application" do
|
60
|
+
subject
|
61
|
+
expect(output).to say("Starting #{app.name}... OK")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.it_prints_log_progress
|
66
|
+
it "prints out the log progress" do
|
67
|
+
subject
|
68
|
+
expect(output).to say(log_text)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.it_does_not_print_log_progress
|
73
|
+
it "does not print the log progress" do
|
74
|
+
subject
|
75
|
+
expect(output).to_not say(log_text)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.it_waits_for_application_to_become_healthy
|
80
|
+
describe "waits for application to become healthy" do
|
81
|
+
let(:app) { fake :app, :total_instances => 2 }
|
82
|
+
|
83
|
+
def after_sleep
|
84
|
+
any_instance_of described_class do |cli|
|
85
|
+
stub(cli).sleep { yield }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
before do
|
90
|
+
stub(app).instances do
|
91
|
+
[ CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "DOWN"),
|
92
|
+
CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "RUNNING")
|
93
|
+
]
|
94
|
+
end
|
95
|
+
|
96
|
+
after_sleep do
|
97
|
+
stub(app).instances { final_instances }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "when all instances become running" do
|
102
|
+
let(:final_instances) do
|
103
|
+
[ CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "RUNNING"),
|
104
|
+
CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "RUNNING")
|
105
|
+
]
|
106
|
+
end
|
107
|
+
|
108
|
+
it "says app is started" do
|
109
|
+
subject
|
110
|
+
expect(output).to say("Checking #{app.name}...")
|
111
|
+
expect(output).to say("1 running, 1 down")
|
112
|
+
expect(output).to say("2 running")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "when any instance becomes flapping" do
|
117
|
+
let(:final_instances) do
|
118
|
+
[ CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "FLAPPING"),
|
119
|
+
CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "STARTING")
|
120
|
+
]
|
121
|
+
end
|
122
|
+
|
123
|
+
it "says app failed to start" do
|
124
|
+
subject
|
125
|
+
expect(output).to say("Checking #{app.name}...")
|
126
|
+
expect(output).to say("1 running, 1 down")
|
127
|
+
expect(output).to say("1 starting, 1 flapping")
|
128
|
+
expect(error_output).to say("Application failed to start")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
before do
|
135
|
+
stub(app).invalidate!
|
136
|
+
stub(app).instances do
|
137
|
+
[ CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "RUNNING") ]
|
138
|
+
end
|
139
|
+
|
140
|
+
stub(app).start!(true) do |_, blk|
|
141
|
+
app.state = "STARTED"
|
142
|
+
blk.call(log_url)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context "when progress log url is provided" do
|
147
|
+
let(:log_url) { "http://example.com/my-app-log" }
|
148
|
+
let(:log_text) { "Staging complete!" }
|
149
|
+
|
150
|
+
context "and progress log url is not available immediately" do
|
151
|
+
before do
|
152
|
+
stub_request(:get, "#{log_url}&tail&tail_offset=0").to_return(
|
153
|
+
:status => 404, :body => "")
|
154
|
+
end
|
155
|
+
|
156
|
+
it_says_application_is_starting
|
157
|
+
it_does_not_print_log_progress
|
158
|
+
it_waits_for_application_to_become_healthy
|
159
|
+
end
|
160
|
+
|
161
|
+
context "and progress log url becomes unavailable after some time" do
|
162
|
+
before do
|
163
|
+
stub_request(:get, "#{log_url}&tail&tail_offset=0").to_return(
|
164
|
+
:status => 200, :body => log_text[0...5])
|
165
|
+
stub_request(:get, "#{log_url}&tail&tail_offset=5").to_return(
|
166
|
+
:status => 200, :body => log_text[5..-1])
|
167
|
+
stub_request(:get, "#{log_url}&tail&tail_offset=#{log_text.size}").to_return(
|
168
|
+
:status => 404, :body => "")
|
169
|
+
end
|
170
|
+
|
171
|
+
it_says_application_is_starting
|
172
|
+
it_prints_log_progress
|
173
|
+
it_waits_for_application_to_become_healthy
|
174
|
+
end
|
175
|
+
|
176
|
+
context "and a request times out" do
|
177
|
+
before do
|
178
|
+
stub_request(:get, "#{log_url}&tail&tail_offset=0").to_return(
|
179
|
+
:should_timeout => true)
|
180
|
+
stub_request(:get, "#{log_url}&tail&tail_offset=0").to_return(
|
181
|
+
:status => 200, :body => log_text)
|
182
|
+
stub_request(:get, "#{log_url}&tail&tail_offset=#{log_text.size}").to_return(
|
183
|
+
:status => 404, :body => "")
|
184
|
+
end
|
185
|
+
|
186
|
+
it_says_application_is_starting
|
187
|
+
it_prints_log_progress
|
188
|
+
it_waits_for_application_to_become_healthy
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context "when progress log url is not provided" do
|
193
|
+
let(:log_url) { nil }
|
194
|
+
let(:log_text) { "Staging complete!" }
|
195
|
+
|
196
|
+
it_says_application_is_starting
|
197
|
+
it_does_not_print_log_progress
|
198
|
+
it_waits_for_application_to_become_healthy
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|