vmc 0.4.0.beta.29 → 0.4.0.beta.30
Sign up to get free protection for your applications and to get access to all the features.
- data/vmc-ng/lib/vmc/cli.rb +31 -1
- data/vmc-ng/lib/vmc/cli/app.rb +3 -17
- data/vmc-ng/lib/vmc/cli/service.rb +0 -21
- data/vmc-ng/lib/vmc/cli/space.rb +12 -0
- data/vmc-ng/lib/vmc/cli/start.rb +4 -4
- data/vmc-ng/lib/vmc/version.rb +1 -1
- data/vmc-ng/spec/app/apps_spec.rb +39 -45
- data/vmc-ng/spec/app/push_spec.rb +68 -0
- data/vmc-ng/spec/eventlog.rb +157 -0
- data/vmc-ng/spec/helpers.rb +206 -10
- data/vmc-ng/spec/patches.rb +36 -0
- data/vmc-ng/spec/start/target_spec.rb +16 -7
- metadata +10 -7
data/vmc-ng/lib/vmc/cli.rb
CHANGED
@@ -34,6 +34,9 @@ module VMC
|
|
34
34
|
option :version, :alias => "-v", :type => :boolean,
|
35
35
|
:desc => "Print version number"
|
36
36
|
|
37
|
+
option :verbose, :alias => "-V", :type => :boolean,
|
38
|
+
:desc => "Print extra information"
|
39
|
+
|
37
40
|
option(:force, :alias => "-f", :type => :boolean,
|
38
41
|
:desc => "Skip interaction when possible") {
|
39
42
|
option(:script)
|
@@ -156,6 +159,10 @@ module VMC
|
|
156
159
|
option(:color)
|
157
160
|
end
|
158
161
|
|
162
|
+
def verbose?
|
163
|
+
option(:verbose)
|
164
|
+
end
|
165
|
+
|
159
166
|
def err(msg, status = 1)
|
160
167
|
if quiet?
|
161
168
|
$stderr.puts(msg)
|
@@ -175,7 +182,7 @@ module VMC
|
|
175
182
|
begin
|
176
183
|
TCPSocket.new(url, Net::HTTP.https_default_port)
|
177
184
|
url = "https://#{url}"
|
178
|
-
rescue SocketError, Timeout::Error
|
185
|
+
rescue Errno::ECONNREFUSED, SocketError, Timeout::Error
|
179
186
|
url = "http://#{url}"
|
180
187
|
end
|
181
188
|
end
|
@@ -324,6 +331,29 @@ module VMC
|
|
324
331
|
def client=(c)
|
325
332
|
@@client = c
|
326
333
|
end
|
334
|
+
|
335
|
+
private
|
336
|
+
|
337
|
+
def find_by_name(what)
|
338
|
+
proc { |name, choices, *_|
|
339
|
+
choices.find { |c| c.name == name } ||
|
340
|
+
fail("Unknown #{what} '#{name}'")
|
341
|
+
}
|
342
|
+
end
|
343
|
+
|
344
|
+
def by_name(what, obj = what)
|
345
|
+
proc { |name, *_|
|
346
|
+
client.send(:"#{obj}_by_name", name) ||
|
347
|
+
fail("Unknown #{what} '#{name}'")
|
348
|
+
}
|
349
|
+
end
|
350
|
+
|
351
|
+
def find_by_name_insensitive(what)
|
352
|
+
proc { |name, choices|
|
353
|
+
choices.find { |c| c.name.upcase == name.upcase } ||
|
354
|
+
fail("Unknown #{what} '#{name}'")
|
355
|
+
}
|
356
|
+
end
|
327
357
|
end
|
328
358
|
end
|
329
359
|
end
|
data/vmc-ng/lib/vmc/cli/app.rb
CHANGED
@@ -35,21 +35,6 @@ module VMC
|
|
35
35
|
}
|
36
36
|
|
37
37
|
|
38
|
-
def self.find_by_name(what)
|
39
|
-
proc { |name, choices|
|
40
|
-
choices.find { |c| c.name == name } ||
|
41
|
-
fail("Unknown #{what} '#{name}'")
|
42
|
-
}
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.by_name(what)
|
46
|
-
proc { |name|
|
47
|
-
client.send(:"#{what}_by_name", name) ||
|
48
|
-
fail("Unknown #{what} '#{name}'")
|
49
|
-
}
|
50
|
-
end
|
51
|
-
|
52
|
-
|
53
38
|
desc "List your applications"
|
54
39
|
group :apps
|
55
40
|
input :space, :desc => "Show apps in given space",
|
@@ -73,6 +58,7 @@ module VMC
|
|
73
58
|
end
|
74
59
|
|
75
60
|
if apps.empty? and !quiet?
|
61
|
+
line
|
76
62
|
line "No applications."
|
77
63
|
return
|
78
64
|
end
|
@@ -83,7 +69,7 @@ module VMC
|
|
83
69
|
!app_matches(a, input)
|
84
70
|
end
|
85
71
|
|
86
|
-
spaced(apps) do |a|
|
72
|
+
spaced(apps.sort_by(&:name)) do |a|
|
87
73
|
display_app(a)
|
88
74
|
end
|
89
75
|
end
|
@@ -901,7 +887,7 @@ module VMC
|
|
901
887
|
end
|
902
888
|
|
903
889
|
def display_instance(i)
|
904
|
-
|
890
|
+
start_line "instance #{c("\##{i.index}", :instance)}: "
|
905
891
|
puts "#{b(c(i.state.downcase, state_color(i.state)))} "
|
906
892
|
|
907
893
|
indented do
|
@@ -2,27 +2,6 @@ require "vmc/cli"
|
|
2
2
|
|
3
3
|
module VMC
|
4
4
|
class Service < CLI
|
5
|
-
def self.find_by_name(what)
|
6
|
-
proc { |name, choices|
|
7
|
-
choices.find { |c| c.name == name } ||
|
8
|
-
fail("Unknown #{what} '#{name}'")
|
9
|
-
}
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.find_by_name_insensitive(what)
|
13
|
-
proc { |name, choices|
|
14
|
-
choices.find { |c| c.name.upcase == name.upcase } ||
|
15
|
-
fail("Unknown #{what} '#{name}'")
|
16
|
-
}
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.by_name(what, obj = what)
|
20
|
-
proc { |name, *_|
|
21
|
-
client.send(:"#{obj}_by_name", name) ||
|
22
|
-
fail("Unknown #{what} '#{name}'")
|
23
|
-
}
|
24
|
-
end
|
25
|
-
|
26
5
|
desc "List your service instances"
|
27
6
|
group :services
|
28
7
|
input :name, :desc => "Filter by name"
|
data/vmc-ng/lib/vmc/cli/space.rb
CHANGED
@@ -149,6 +149,18 @@ module VMC
|
|
149
149
|
end
|
150
150
|
|
151
151
|
|
152
|
+
desc "Switch to a space, creating it if it doesn't exist"
|
153
|
+
group :spaces, :hidden => true
|
154
|
+
input :name, :argument => true, :desc => "Space name"
|
155
|
+
def take_space(input)
|
156
|
+
if space = client.space_by_name(input[:name])
|
157
|
+
invoke :target, :space => space
|
158
|
+
else
|
159
|
+
invoke :create_space, :name => input[:name], :target => true
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
|
152
164
|
desc "Delete a space and its contents"
|
153
165
|
group :spaces
|
154
166
|
input(:space, :argument => :optional, :from_given => space_by_name,
|
data/vmc-ng/lib/vmc/cli/start.rb
CHANGED
@@ -342,7 +342,7 @@ module VMC
|
|
342
342
|
|
343
343
|
def display_target
|
344
344
|
if quiet?
|
345
|
-
|
345
|
+
line client.target
|
346
346
|
else
|
347
347
|
line "target: #{c(client.target, :name)}"
|
348
348
|
end
|
@@ -363,7 +363,7 @@ module VMC
|
|
363
363
|
|
364
364
|
def display_runtime(r)
|
365
365
|
if quiet?
|
366
|
-
|
366
|
+
line r.name
|
367
367
|
else
|
368
368
|
line "#{c(r.name, :name)}:"
|
369
369
|
|
@@ -380,7 +380,7 @@ module VMC
|
|
380
380
|
|
381
381
|
def display_service(s)
|
382
382
|
if quiet?
|
383
|
-
|
383
|
+
line s.label
|
384
384
|
else
|
385
385
|
line "#{c(s.label, :name)}:"
|
386
386
|
|
@@ -403,7 +403,7 @@ module VMC
|
|
403
403
|
|
404
404
|
def display_framework(f)
|
405
405
|
if quiet?
|
406
|
-
|
406
|
+
line f.name
|
407
407
|
else
|
408
408
|
line "#{c(f.name, :name)}:"
|
409
409
|
|
data/vmc-ng/lib/vmc/version.rb
CHANGED
@@ -3,73 +3,67 @@ require "./helpers"
|
|
3
3
|
describe "App#apps" do
|
4
4
|
it "lists app names" do
|
5
5
|
with_random_apps do |apps|
|
6
|
-
|
7
|
-
apps.
|
6
|
+
running(:apps) do
|
7
|
+
apps.sort_by(&:name).each do |a|
|
8
|
+
outputs(a.name)
|
9
|
+
end
|
10
|
+
end
|
8
11
|
end
|
9
12
|
end
|
10
13
|
|
11
14
|
it "filters by name with --name" do
|
12
15
|
with_random_apps do |apps|
|
13
|
-
|
16
|
+
name = sample(apps).name
|
14
17
|
|
15
|
-
|
16
|
-
|
18
|
+
running(:apps, :name => name) do
|
19
|
+
apps.sort_by(&:name).each do |a|
|
20
|
+
if a.name == name
|
21
|
+
outputs(a.name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
17
25
|
end
|
18
26
|
end
|
19
27
|
|
20
28
|
it "filters by runtime with --runtime" do
|
21
29
|
with_random_apps do |apps|
|
22
|
-
|
30
|
+
runtime = sample(apps).runtime
|
23
31
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
32
|
+
running(:apps, :runtime => runtime.name) do
|
33
|
+
apps.sort_by(&:name).each do |a|
|
34
|
+
if a.runtime =~ /#{runtime}/
|
35
|
+
outputs(a.name)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
31
39
|
end
|
32
40
|
end
|
33
41
|
|
34
42
|
it "filters by framework with --framework" do
|
35
43
|
with_random_apps do |apps|
|
36
|
-
|
37
|
-
|
38
|
-
result = shell("apps", "--framework", app.framework.name).split("\n")
|
39
|
-
actual =
|
40
|
-
apps.select { |a|
|
41
|
-
/#{app.framework.name}/ =~ a.framework.name
|
42
|
-
}.collect(&:name)
|
44
|
+
framework = sample(apps).framework
|
43
45
|
|
44
|
-
|
46
|
+
running(:apps, :framework => framework.name) do
|
47
|
+
apps.sort_by(&:name).each do |a|
|
48
|
+
if a.framework == framework
|
49
|
+
outputs(a.name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
45
53
|
end
|
46
54
|
end
|
47
55
|
|
48
|
-
# TODO: use space other than current
|
49
56
|
it "can be told which space with --space" do
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
+
with_new_space do |space|
|
58
|
+
with_random_apps do |other_apps|
|
59
|
+
with_random_apps(space) do |apps|
|
60
|
+
running(:apps, :space => space) do
|
61
|
+
apps.sort_by(&:name).each do |a|
|
62
|
+
outputs(a.name)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
57
67
|
end
|
58
68
|
end
|
59
|
-
|
60
|
-
# TODO: v2
|
61
|
-
#it "filters by url with --url" do
|
62
|
-
#with_random_apps do |apps|
|
63
|
-
#app = apps[rand(apps.size)]
|
64
|
-
#url = app.urls[rand(app.urls.size)]
|
65
|
-
|
66
|
-
#result = shell("apps", "--url", url).split("\n")
|
67
|
-
#actual =
|
68
|
-
#apps.select { |a|
|
69
|
-
#a.urls.include? url
|
70
|
-
#}.collect(&:name)
|
71
|
-
|
72
|
-
#result.should =~ actual
|
73
|
-
#end
|
74
|
-
#end
|
75
69
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "./helpers"
|
2
|
+
|
3
|
+
describe "App#push" do
|
4
|
+
it "pushes interactively" do
|
5
|
+
name = "app-#{random_str}"
|
6
|
+
instances = rand(3) + 1
|
7
|
+
framework = sample(client.frameworks)
|
8
|
+
runtime = sample(client.runtimes)
|
9
|
+
url = "#{name}.fakecloud.com"
|
10
|
+
memory = sample([64, 128, 256, 512])
|
11
|
+
|
12
|
+
client.app_by_name(name).should_not be
|
13
|
+
|
14
|
+
begin
|
15
|
+
running(:push) do
|
16
|
+
asks("Name")
|
17
|
+
given(name)
|
18
|
+
has_input(:name, name)
|
19
|
+
|
20
|
+
asks("Instances")
|
21
|
+
given(instances)
|
22
|
+
has_input(:instance, instances)
|
23
|
+
|
24
|
+
asks("Framework")
|
25
|
+
given(framework.name)
|
26
|
+
has_input(:framework, framework)
|
27
|
+
|
28
|
+
asks("Runtime")
|
29
|
+
given(runtime.name)
|
30
|
+
has_input(:runtime, runtime)
|
31
|
+
|
32
|
+
asks("URL")
|
33
|
+
given(url)
|
34
|
+
has_input(:url, url)
|
35
|
+
|
36
|
+
asks("Memory Limit")
|
37
|
+
given("#{memory}M")
|
38
|
+
has_input(:memory, "#{memory}M")
|
39
|
+
|
40
|
+
asks("Create services for application?")
|
41
|
+
given("n")
|
42
|
+
has_input(:create_instances, false)
|
43
|
+
|
44
|
+
asks("Bind other services to application?")
|
45
|
+
given("n")
|
46
|
+
has_input(:bind_instances, false)
|
47
|
+
end
|
48
|
+
rescue VMC::UserError => e
|
49
|
+
unless e.to_s == "V2 API currently does not support uploading or starting apps."
|
50
|
+
raise
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
app = client.app_by_name(name)
|
55
|
+
|
56
|
+
begin
|
57
|
+
app.should be
|
58
|
+
app.name.should == name
|
59
|
+
app.instances.should == instances
|
60
|
+
app.framework.should == framework
|
61
|
+
app.runtime.should == runtime
|
62
|
+
#app.url.should == url # TODO v2
|
63
|
+
app.memory.should == memory
|
64
|
+
ensure
|
65
|
+
app.delete!
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require "thread"
|
2
|
+
|
3
|
+
class FakeTTY
|
4
|
+
attr_accessor :event
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@input = Queue.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def getc
|
11
|
+
@input.pop
|
12
|
+
end
|
13
|
+
|
14
|
+
def fake(input)
|
15
|
+
return if @input.nil?
|
16
|
+
|
17
|
+
input.each_char do |c|
|
18
|
+
@input << c
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def close
|
23
|
+
@input = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def tty?
|
27
|
+
true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class EventLog
|
32
|
+
attr_accessor :process
|
33
|
+
attr_reader :events, :interaction, :inputs
|
34
|
+
|
35
|
+
def initialize(input)
|
36
|
+
@input = input
|
37
|
+
|
38
|
+
@queue = Queue.new
|
39
|
+
@events = []
|
40
|
+
@inputs = {}
|
41
|
+
end
|
42
|
+
|
43
|
+
def finish_input
|
44
|
+
@input.close
|
45
|
+
end
|
46
|
+
|
47
|
+
def next_event
|
48
|
+
if @queue.empty?
|
49
|
+
if @process.status == false
|
50
|
+
raise "Expected more events, but the process has finished."
|
51
|
+
elsif @process.status == nil
|
52
|
+
begin
|
53
|
+
@process.join
|
54
|
+
rescue => e
|
55
|
+
raise "Expected more events, but process has thrown an exception: #{e}."
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
val = @queue.pop
|
61
|
+
@events << val
|
62
|
+
val
|
63
|
+
end
|
64
|
+
|
65
|
+
def pending_events
|
66
|
+
events = []
|
67
|
+
|
68
|
+
until @queue.empty?
|
69
|
+
events << @queue.pop
|
70
|
+
end
|
71
|
+
|
72
|
+
events
|
73
|
+
end
|
74
|
+
|
75
|
+
def wait_for_event(type)
|
76
|
+
val = next_event
|
77
|
+
|
78
|
+
until val.is_a?(type)
|
79
|
+
val = next_event
|
80
|
+
end
|
81
|
+
|
82
|
+
val
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def pick_random_option
|
87
|
+
options = @interaction.options
|
88
|
+
choices = options[:choices]
|
89
|
+
chosen = choices[rand(choices.size)]
|
90
|
+
|
91
|
+
if display = options[:display]
|
92
|
+
provide("#{display.call(chosen)}\n")
|
93
|
+
else
|
94
|
+
provide("#{chosen}\n")
|
95
|
+
end
|
96
|
+
|
97
|
+
chosen
|
98
|
+
end
|
99
|
+
|
100
|
+
def provide(input)
|
101
|
+
@input.fake(input)
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def printed(line)
|
106
|
+
@queue << Printed.new(line)
|
107
|
+
end
|
108
|
+
|
109
|
+
def asking(message, options = {})
|
110
|
+
@interaction = Asked.new(message, options)
|
111
|
+
@queue << @interaction
|
112
|
+
end
|
113
|
+
|
114
|
+
def got_input(name, val)
|
115
|
+
@inputs[name] = val
|
116
|
+
@queue << GotInput.new(name, val)
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
class Printed
|
121
|
+
attr_reader :line
|
122
|
+
|
123
|
+
def initialize(line)
|
124
|
+
@line = line
|
125
|
+
end
|
126
|
+
|
127
|
+
def to_s
|
128
|
+
"<Printed '#@line'>"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class Asked
|
133
|
+
attr_reader :message, :options
|
134
|
+
|
135
|
+
def initialize(message, options = {})
|
136
|
+
@message = message
|
137
|
+
@options = options
|
138
|
+
end
|
139
|
+
|
140
|
+
def to_s
|
141
|
+
"<Asked '#@message'>"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
class GotInput
|
146
|
+
attr_reader :name, :value
|
147
|
+
|
148
|
+
def initialize(name, value)
|
149
|
+
@name = name
|
150
|
+
@value = value
|
151
|
+
end
|
152
|
+
|
153
|
+
def to_s
|
154
|
+
"<GotInput #@name '#@value'>"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
data/vmc-ng/spec/helpers.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
require "cfoundry"
|
2
2
|
require "vmc"
|
3
3
|
|
4
|
+
require "./eventlog"
|
5
|
+
require "./patches"
|
6
|
+
|
7
|
+
|
4
8
|
TARGET = ENV["VMC_TEST_TARGET"] || "http://localhost:8181"
|
5
9
|
USER = ENV["VMC_TEST_USER"] || "sre@vmware.com"
|
6
10
|
PASSWORD = ENV["VMC_TEST_PASSWORD"] || "test"
|
@@ -45,13 +49,13 @@ module VMCHelpers
|
|
45
49
|
end
|
46
50
|
|
47
51
|
# create 2-5 random apps, call the block, and then delete them
|
48
|
-
def with_random_apps(num = rand(3) + 2)
|
52
|
+
def with_random_apps(space = client.current_space, num = rand(3) + 2)
|
49
53
|
apps = []
|
50
54
|
|
51
55
|
num.times do |n|
|
52
56
|
app = client.app
|
53
57
|
app.name = "app-#{n + 1}-#{random_str}"
|
54
|
-
app.space =
|
58
|
+
app.space = space
|
55
59
|
app.instances = rand(2)
|
56
60
|
|
57
61
|
app.framework = sample(frameworks)
|
@@ -67,31 +71,223 @@ module VMCHelpers
|
|
67
71
|
apps.each(&:delete!)
|
68
72
|
end
|
69
73
|
|
70
|
-
|
71
|
-
|
74
|
+
def with_new_space(org = client.current_organization)
|
75
|
+
space = client.space
|
76
|
+
space.name = "space-#{random_str}"
|
77
|
+
space.organization = org
|
78
|
+
space.create!
|
79
|
+
|
80
|
+
yield space
|
81
|
+
ensure
|
82
|
+
space.delete!
|
83
|
+
end
|
84
|
+
|
85
|
+
def running(command, inputs = {})
|
86
|
+
VMC::CLI.new.exit_status 0
|
87
|
+
|
88
|
+
before_in = $stdin
|
72
89
|
before_out = $stdout
|
73
90
|
before_err = $stderr
|
91
|
+
before_event = $vmc_event
|
92
|
+
|
93
|
+
tty = FakeTTY.new
|
94
|
+
|
95
|
+
$vmc_event = EventLog.new(tty)
|
74
96
|
|
97
|
+
$stdin = tty
|
75
98
|
$stdout = StringIO.new
|
76
99
|
$stderr = StringIO.new
|
77
100
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
101
|
+
main = Thread.current
|
102
|
+
|
103
|
+
thd = Thread.new do
|
104
|
+
begin
|
105
|
+
VMC::CLI.new.invoke(command, inputs)
|
106
|
+
rescue SystemExit => e
|
107
|
+
unless e.status == 0
|
108
|
+
raise <<EOF
|
109
|
+
execution failed with status #{e.status}!
|
110
|
+
|
111
|
+
stdout:
|
112
|
+
#{$stdout.string.inspect}
|
113
|
+
|
114
|
+
stderr:
|
115
|
+
#{$stderr.string}
|
116
|
+
EOF
|
117
|
+
end
|
118
|
+
rescue => e
|
119
|
+
main.raise(e)
|
83
120
|
end
|
84
121
|
end
|
85
122
|
|
86
|
-
|
123
|
+
begin
|
124
|
+
$vmc_event.process = thd
|
125
|
+
|
126
|
+
yield $vmc_event
|
127
|
+
|
128
|
+
$vmc_event.should complete
|
129
|
+
ensure
|
130
|
+
thd.kill
|
131
|
+
end
|
87
132
|
ensure
|
133
|
+
$stdin = before_in
|
88
134
|
$stdout = before_out
|
89
135
|
$stderr = before_err
|
136
|
+
$vmc_event = before_event
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
module VMCMatchers
|
141
|
+
class Contain
|
142
|
+
def initialize(content)
|
143
|
+
@content = content
|
144
|
+
end
|
145
|
+
|
146
|
+
def matches?(actual)
|
147
|
+
@actual = actual
|
148
|
+
true
|
149
|
+
end
|
150
|
+
|
151
|
+
def failure_message
|
152
|
+
"expected '#@content' to be in the output"
|
153
|
+
end
|
154
|
+
|
155
|
+
def negative_failure_message
|
156
|
+
"expected '#@content' to NOT be in the output"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def contain(content)
|
161
|
+
Contain.new(content)
|
162
|
+
end
|
163
|
+
|
164
|
+
class Ask
|
165
|
+
def initialize(message)
|
166
|
+
@message = message
|
167
|
+
end
|
168
|
+
|
169
|
+
def matches?(log)
|
170
|
+
ev = log.wait_for_event(EventLog::Asked)
|
171
|
+
|
172
|
+
@actual = ev.message
|
173
|
+
@actual == @message
|
174
|
+
end
|
175
|
+
|
176
|
+
def failure_message
|
177
|
+
"expected to be asked '#@message', got '#@actual'"
|
178
|
+
end
|
179
|
+
|
180
|
+
def negative_failure_message
|
181
|
+
"expected to NOT be asked for #@message"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def ask(message)
|
186
|
+
Ask.new(message)
|
187
|
+
end
|
188
|
+
|
189
|
+
class HaveInput
|
190
|
+
def initialize(name, value = nil)
|
191
|
+
@name = name
|
192
|
+
@expected = value
|
193
|
+
end
|
194
|
+
|
195
|
+
def matches?(log)
|
196
|
+
@actual = log.wait_for_event(EventLog::GotInput).value
|
197
|
+
@actual == @expected
|
198
|
+
end
|
199
|
+
|
200
|
+
def failure_message
|
201
|
+
"expected to have input '#@name' as '#@expected', but got '#@actual'"
|
202
|
+
end
|
203
|
+
|
204
|
+
def negative_failure_message
|
205
|
+
"expected not to have input '#@name', but had it as '#@actual'"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def have_input(name, value = nil)
|
210
|
+
HaveInput.new(name, value)
|
211
|
+
end
|
212
|
+
|
213
|
+
class Output
|
214
|
+
def initialize(line)
|
215
|
+
@expected = line
|
216
|
+
end
|
217
|
+
|
218
|
+
def matches?(log)
|
219
|
+
@actual = log.wait_for_event(EventLog::Printed).line
|
220
|
+
@actual == @expected
|
221
|
+
end
|
222
|
+
|
223
|
+
def failure_message
|
224
|
+
"expected '#@expected' to be in the output, but got '#@actual'"
|
225
|
+
end
|
226
|
+
|
227
|
+
def negative_failure_message
|
228
|
+
"expected '#@expected' NOT to be in the output, but it was"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def output(line)
|
233
|
+
Output.new(line)
|
234
|
+
end
|
235
|
+
|
236
|
+
class Complete
|
237
|
+
def matches?(log)
|
238
|
+
@log = log
|
239
|
+
|
240
|
+
log.process.join(1)
|
241
|
+
|
242
|
+
log.process.status == false
|
243
|
+
end
|
244
|
+
|
245
|
+
def failure_message
|
246
|
+
pending = @log.pending_events
|
247
|
+
|
248
|
+
if @exception
|
249
|
+
"process existed with an exception: #@exception"
|
250
|
+
elsif !pending.empty?
|
251
|
+
"expected process to complete, but it's pending events #{pending}"
|
252
|
+
else
|
253
|
+
"process is blocked; status: #{@log.process.status}"
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def negative_failure_message
|
258
|
+
"expected process to still be running, but it's completed"
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def complete
|
263
|
+
Complete.new
|
264
|
+
end
|
265
|
+
|
266
|
+
|
267
|
+
def asks(what)
|
268
|
+
$vmc_event.should ask(what)
|
269
|
+
end
|
270
|
+
|
271
|
+
def given(what)
|
272
|
+
$vmc_event.provide("#{what}\n")
|
273
|
+
end
|
274
|
+
|
275
|
+
def has_input(name, value = nil)
|
276
|
+
$vmc_event.should have_input(name, value)
|
277
|
+
end
|
278
|
+
|
279
|
+
def finish
|
280
|
+
$vmc_event.should complete
|
281
|
+
end
|
282
|
+
|
283
|
+
def outputs(what)
|
284
|
+
$vmc_event.should output(what)
|
90
285
|
end
|
91
286
|
end
|
92
287
|
|
93
288
|
RSpec.configure do |c|
|
94
289
|
c.include VMCHelpers
|
290
|
+
c.include VMCMatchers
|
95
291
|
|
96
292
|
c.before(:all) do
|
97
293
|
VMC::CLI.client = CFoundry::Client.new(TARGET)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# [EventLog]
|
2
|
+
$vmc_event = nil
|
3
|
+
|
4
|
+
class VMC::CLI
|
5
|
+
def ask(*args)
|
6
|
+
$vmc_event.asking(*args) if $vmc_event
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def line(*args)
|
11
|
+
$vmc_event.printed(*args) if $vmc_event
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def force?
|
16
|
+
false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Mothership::Inputs
|
21
|
+
alias_method :vmc_spec_get, :[]
|
22
|
+
|
23
|
+
def [](name, *args)
|
24
|
+
val = vmc_spec_get(name, *args)
|
25
|
+
$vmc_event.got_input(name, val) if $vmc_event
|
26
|
+
val
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Interactive
|
31
|
+
def set_input_state(input)
|
32
|
+
end
|
33
|
+
|
34
|
+
def restore_input_state(input, before)
|
35
|
+
end
|
36
|
+
end
|
@@ -2,7 +2,9 @@ require "./helpers"
|
|
2
2
|
|
3
3
|
describe "Start#target" do
|
4
4
|
it "shows target url with no arguments" do
|
5
|
-
|
5
|
+
running(:target) do
|
6
|
+
outputs(client.target)
|
7
|
+
end
|
6
8
|
end
|
7
9
|
|
8
10
|
describe "switching target url" do
|
@@ -25,20 +27,27 @@ describe "Start#target" do
|
|
25
27
|
end
|
26
28
|
|
27
29
|
it "switches target url if given one argument" do
|
28
|
-
|
29
|
-
|
30
|
+
running(:target, :url => "http://api.cloudfoundry.com") do
|
31
|
+
finish
|
32
|
+
client.target.should == "http://api.cloudfoundry.com"
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
32
36
|
it "defaults to https if supported by remote" do
|
33
|
-
|
34
|
-
|
37
|
+
running(:target, :url => "api.cloudfoundry.com") do
|
38
|
+
finish
|
39
|
+
client.target.should == "https://api.cloudfoundry.com"
|
40
|
+
end
|
35
41
|
end
|
36
42
|
|
37
43
|
# TODO: this assumes locally running cc without https support
|
38
44
|
it "defaults to http if not supported by remote" do
|
39
45
|
base_target = client.target.sub(/^https?:\/\//, "")
|
40
|
-
|
41
|
-
|
46
|
+
|
47
|
+
running(:target, :url => base_target) do
|
48
|
+
finish
|
49
|
+
client.target.should == "http://#{base_target}"
|
50
|
+
end
|
42
51
|
end
|
43
52
|
end
|
44
53
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vmc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 62196447
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 4
|
9
9
|
- 0
|
10
10
|
- beta
|
11
|
-
-
|
12
|
-
version: 0.4.0.beta.
|
11
|
+
- 30
|
12
|
+
version: 0.4.0.beta.30
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- VMware
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2012-
|
20
|
+
date: 2012-08-06 00:00:00 Z
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
23
|
name: json_pure
|
@@ -249,12 +249,12 @@ dependencies:
|
|
249
249
|
requirements:
|
250
250
|
- - ~>
|
251
251
|
- !ruby/object:Gem::Version
|
252
|
-
hash:
|
252
|
+
hash: 53
|
253
253
|
segments:
|
254
254
|
- 0
|
255
255
|
- 3
|
256
|
-
-
|
257
|
-
version: 0.3.
|
256
|
+
- 19
|
257
|
+
version: 0.3.19
|
258
258
|
type: :runtime
|
259
259
|
version_requirements: *id014
|
260
260
|
- !ruby/object:Gem::Dependency
|
@@ -387,7 +387,10 @@ files:
|
|
387
387
|
- vmc-ng/lib/vmc/version.rb
|
388
388
|
- vmc-ng/lib/vmc.rb
|
389
389
|
- vmc-ng/spec/app/apps_spec.rb
|
390
|
+
- vmc-ng/spec/app/push_spec.rb
|
391
|
+
- vmc-ng/spec/eventlog.rb
|
390
392
|
- vmc-ng/spec/helpers.rb
|
393
|
+
- vmc-ng/spec/patches.rb
|
391
394
|
- vmc-ng/spec/Rakefile
|
392
395
|
- vmc-ng/spec/start/target_spec.rb
|
393
396
|
- vmc-ng/bin/vmc
|