vmc 0.4.0.beta.29 → 0.4.0.beta.30
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/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
|