vmc 0.5.0.beta.7 → 0.5.0.beta.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/LICENSE +1277 -746
  2. data/Rakefile +22 -23
  3. data/lib/vmc/cli.rb +21 -27
  4. data/lib/vmc/cli/app/push.rb +1 -0
  5. data/lib/vmc/cli/app/push/create.rb +3 -2
  6. data/lib/vmc/cli/app/push/sync.rb +11 -8
  7. data/lib/vmc/cli/app/scale.rb +19 -17
  8. data/lib/vmc/cli/domain/map.rb +55 -0
  9. data/lib/vmc/cli/domain/unmap.rb +56 -0
  10. data/lib/vmc/cli/route/map.rb +74 -0
  11. data/lib/vmc/cli/route/unmap.rb +94 -0
  12. data/lib/vmc/cli/service/create.rb +4 -1
  13. data/lib/vmc/cli/start/base.rb +2 -2
  14. data/lib/vmc/cli/start/login.rb +5 -2
  15. data/lib/vmc/cli/start/target.rb +4 -3
  16. data/lib/vmc/cli/user/base.rb +19 -0
  17. data/lib/vmc/cli/user/passwd.rb +7 -19
  18. data/lib/vmc/cli/{start → user}/register.rb +12 -23
  19. data/lib/vmc/constants.rb +1 -1
  20. data/lib/vmc/test_support.rb +4 -0
  21. data/lib/vmc/test_support/command_helper.rb +38 -0
  22. data/{spec/support → lib/vmc/test_support}/common_input_examples.rb +0 -0
  23. data/lib/vmc/test_support/fake_home_dir.rb +16 -0
  24. data/lib/vmc/test_support/interact_helper.rb +29 -0
  25. data/lib/vmc/version.rb +1 -1
  26. data/spec/features/new_user_flow_spec.rb +43 -51
  27. data/spec/spec_helper.rb +24 -12
  28. data/spec/vmc/cli/app/instances_spec.rb +3 -8
  29. data/spec/vmc/cli/app/push/create_spec.rb +10 -7
  30. data/spec/vmc/cli/app/push_spec.rb +1 -1
  31. data/spec/vmc/cli/app/rename_spec.rb +1 -1
  32. data/spec/vmc/cli/app/scale_spec.rb +81 -0
  33. data/spec/vmc/cli/app/stats_spec.rb +3 -7
  34. data/spec/vmc/cli/domain/map_spec.rb +140 -0
  35. data/spec/vmc/cli/domain/unmap_spec.rb +73 -0
  36. data/spec/vmc/cli/organization/orgs_spec.rb +13 -16
  37. data/spec/vmc/cli/organization/rename_spec.rb +1 -1
  38. data/spec/vmc/cli/route/map_spec.rb +142 -0
  39. data/spec/vmc/cli/route/unmap_spec.rb +215 -0
  40. data/spec/vmc/cli/service/rename_spec.rb +1 -1
  41. data/spec/vmc/cli/space/rename_spec.rb +15 -18
  42. data/spec/vmc/cli/space/spaces_spec.rb +18 -25
  43. data/spec/vmc/cli/start/info_spec.rb +44 -46
  44. data/spec/vmc/cli/start/login_spec.rb +40 -0
  45. data/spec/vmc/cli/user/create_spec.rb +54 -0
  46. data/spec/vmc/cli/user/passwd_spec.rb +7 -14
  47. data/spec/vmc/cli/{start → user}/register_spec.rb +26 -22
  48. data/spec/vmc/cli_spec.rb +164 -6
  49. metadata +46 -39
  50. data/lib/vmc/cli/app/routes.rb +0 -100
  51. data/lib/vmc/cli/domain/add_domain.rb +0 -25
  52. data/lib/vmc/cli/domain/create_domain.rb +0 -28
  53. data/lib/vmc/cli/domain/delete_domain.rb +0 -56
  54. data/lib/vmc/cli/domain/remove_domain.rb +0 -28
  55. data/lib/vmc/cli/route/create_route.rb +0 -49
  56. data/lib/vmc/cli/route/delete.rb +0 -47
  57. data/spec/support/feature_helpers.rb +0 -16
  58. data/spec/support/interact_helpers.rb +0 -27
  59. data/spec/vmc/cli/route/delete_route_spec.rb +0 -162
@@ -2,15 +2,25 @@ SPEC_ROOT = File.dirname(__FILE__).freeze
2
2
 
3
3
  require "rspec"
4
4
  require "cfoundry"
5
- require "cfoundry/spec_helper"
5
+ require "cfoundry/test_support"
6
6
  require "vmc"
7
+ require "vmc/test_support"
7
8
 
8
9
  Dir[File.expand_path('../support/**/*.rb', __FILE__)].each do |file|
9
10
  require file
10
11
  end
11
12
 
12
13
  RSpec.configure do |c|
14
+ c.include Fake::FakeMethods
13
15
  c.mock_with :rr
16
+
17
+ c.include VMC::TestSupport::FakeHomeDir
18
+ c.include VMC::TestSupport::CommandHelper
19
+ c.include VMC::TestSupport::InteractHelper
20
+
21
+ c.before do
22
+ VMC::CLI.send(:class_variable_set, :@@client, nil)
23
+ end
14
24
  end
15
25
 
16
26
  class String
@@ -25,17 +35,6 @@ class String
25
35
  end
26
36
  end
27
37
 
28
- def with_output_to(output = StringIO.new)
29
- old_out = $stdout
30
- old_err = $stderr
31
- $stdout = output
32
- $stderr = output
33
- yield output
34
- ensure
35
- $stdout = old_out
36
- $stderr = old_err
37
- end
38
-
39
38
  def name_list(xs)
40
39
  if xs.empty?
41
40
  "none"
@@ -43,3 +42,16 @@ def name_list(xs)
43
42
  xs.collect(&:name).join(", ")
44
43
  end
45
44
  end
45
+
46
+ def invoke_cli(cli, *args)
47
+ stub.proxy(cli).invoke.with_any_args
48
+ stub(cli.class).new { cli }
49
+ cli.invoke(*args)
50
+ end
51
+
52
+ def stub_output(cli)
53
+ stub(cli).print
54
+ stub(cli).puts
55
+ stub(Interact::Progress::Dots).start!
56
+ stub(Interact::Progress::Dots).stop!
57
+ end
@@ -5,7 +5,6 @@ describe VMC::App::Stats do
5
5
  let(:global) { { :color => false } }
6
6
  let(:inputs) { {:app => apps[0]} }
7
7
  let(:given) { {} }
8
- let(:output) { StringIO.new }
9
8
  let(:client) { fake_client(:apps => apps) }
10
9
  let(:apps) { [fake(:app, :name => "basic_app")] }
11
10
  let(:time) { Time.local(2012,11,1,2,30)}
@@ -25,7 +24,7 @@ describe VMC::App::Stats do
25
24
  end
26
25
 
27
26
  subject do
28
- with_output_to output do
27
+ capture_output do
29
28
  Mothership.new.invoke(:instances, inputs, given, global)
30
29
  end
31
30
  end
@@ -51,16 +50,12 @@ describe VMC::App::Stats do
51
50
 
52
51
  it 'prints out the instances in the correct order' do
53
52
  subject
54
-
55
- output.rewind
56
- expect(output.string).to match /.*instance \#1.*instance \#2.*instance \#12.*/m
53
+ expect(stdout.string).to match /.*instance \#1.*instance \#2.*instance \#12.*/m
57
54
  end
58
55
 
59
56
  it 'prints out one of the instances correctly' do
60
57
  subject
61
-
62
- output.rewind
63
- expect(output.string).to include <<-OUT.strip_heredoc
58
+ expect(stdout.string).to include <<-OUT.strip_heredoc
64
59
  instance #2: started
65
60
  started: #{time.strftime("%F %r")}
66
61
  debugger: port bar at foo
@@ -46,7 +46,8 @@ describe VMC::App::Create do
46
46
  :framework => framework,
47
47
  :runtime => runtime,
48
48
  :memory => "1G",
49
- :command => "ruby main.rb"
49
+ :command => "ruby main.rb",
50
+ :buildpack => "git://example.com"
50
51
  }
51
52
  end
52
53
 
@@ -59,6 +60,7 @@ describe VMC::App::Create do
59
60
  its([:command]) { should eq "ruby main.rb" }
60
61
  its([:runtime]) { should eq runtime }
61
62
  its([:memory]) { should eq 1024 }
63
+ its([:buildpack]) { should eq "git://example.com" }
62
64
  end
63
65
 
64
66
  context 'when certain inputs are not given' do
@@ -279,7 +281,8 @@ describe VMC::App::Create do
279
281
  :framework => framework,
280
282
  :runtime => runtime,
281
283
  :production => false,
282
- :memory => 1024
284
+ :memory => 1024,
285
+ :buildpack => "git://example.com"
283
286
  }
284
287
  end
285
288
 
@@ -288,15 +291,15 @@ describe VMC::App::Create do
288
291
  subject { create.create_app(attributes) }
289
292
 
290
293
  it 'creates an app based on the resulting inputs' do
291
- attributes.each do |key, val|
292
- mock(app).__send__(:"#{key}=", val)
293
- end
294
-
295
294
  mock(create).filter(:create_app, app) { app }
296
295
 
297
296
  mock(app).create!
298
297
 
299
298
  subject
299
+
300
+ attributes.each do |key, val|
301
+ expect(app.send(key)).to eq val
302
+ end
300
303
  end
301
304
  end
302
305
 
@@ -337,7 +340,7 @@ describe VMC::App::Create do
337
340
  mock_ask('URL', anything) { url_choices.first }
338
341
 
339
342
  mock(create).invoke(:map, :app => app, :url => url_choices.first) do
340
- raise CFoundry::RouteHostTaken.new(nil, nil, "foo", 1234)
343
+ raise CFoundry::RouteHostTaken.new("foo", 1234)
341
344
  end
342
345
  end
343
346
 
@@ -120,7 +120,7 @@ describe VMC::App::Push do
120
120
 
121
121
  it 'outputs the changed instances' do
122
122
  mock(push).line("Changes:")
123
- mock(push).line("instances: 1 -> 2")
123
+ mock(push).line("total_instances: 1 -> 2")
124
124
  stub(app).update!
125
125
  subject
126
126
  end
@@ -95,7 +95,7 @@ describe VMC::App::Rename do
95
95
 
96
96
  context 'and the name already exists' do
97
97
  it 'fails' do
98
- mock(renamed_app).update! { raise CFoundry::AppNameTaken.new(nil, nil, "Bad Name", 404) }
98
+ mock(renamed_app).update! { raise CFoundry::AppNameTaken.new("Bad Name", 404) }
99
99
  expect { subject }.to raise_error(CFoundry::AppNameTaken)
100
100
  end
101
101
  end
@@ -0,0 +1,81 @@
1
+ require "spec_helper"
2
+ require "webmock/rspec"
3
+
4
+ describe VMC::App::Scale do
5
+ let(:global) { { :color => false } }
6
+ let(:given) { {} }
7
+ let(:client) { fake_client }
8
+ let!(:cli) { described_class.new }
9
+
10
+ before do
11
+ stub(cli).client { client }
12
+ stub_output(cli)
13
+ end
14
+
15
+ subject { invoke_cli(cli, :scale, inputs, given, global) }
16
+
17
+ context "when the --disk flag is given" do
18
+ let(:before_value) { 512 }
19
+ let(:app) { fake :app, :disk_quota => before_value }
20
+ let(:inputs) { { :app => app, :disk => "1G" } }
21
+
22
+ it "changes the application's disk quota" do
23
+ mock(app).update!
24
+ expect { subject }.to change(app, :disk_quota).from(before_value).to(1024)
25
+ end
26
+ end
27
+
28
+ context "when the --memory flag is given" do
29
+ let(:before_value) { 512 }
30
+ let(:app) { fake :app, :memory => before_value }
31
+ let(:inputs) { { :app => app, :memory => "1G" } }
32
+
33
+ it "changes the application's memory" do
34
+ mock(app).update!
35
+ expect { subject }.to change(app, :memory).from(before_value).to(1024)
36
+ end
37
+
38
+ context "if --restart is true" do
39
+ it "restarts the application" do
40
+ stub(app).update!
41
+ stub(app).started? { true }
42
+ mock(cli).invoke :restart, :app => app
43
+ subject
44
+ end
45
+ end
46
+ end
47
+
48
+ context "when the --instances flag is given" do
49
+ let(:before_value) { 3 }
50
+ let(:app) { fake :app, :total_instances => before_value }
51
+
52
+ let(:inputs) { { :app => app, :instances => 5 } }
53
+
54
+ it "changes the application's number of instances" do
55
+ mock(app).update!
56
+ expect { subject }.to change(app, :total_instances).from(before_value).to(5)
57
+ end
58
+ end
59
+
60
+ context "when the --plan flag is given" do
61
+ context "when the plan name begins with a 'p'" do
62
+ let(:app) { fake :app, :production => false }
63
+ let(:inputs) { { :app => app, :plan => "P100" } }
64
+
65
+ it "changes the application's 'production' flag to true" do
66
+ mock(app).update!
67
+ expect { subject }.to change(app, :production).from(false).to(true)
68
+ end
69
+ end
70
+
71
+ context "when the plan name does not begin with a 'p'" do
72
+ let(:app) { fake :app, :production => true }
73
+ let(:inputs) { { :app => app, :plan => "D100" } }
74
+
75
+ it "changes the application's 'production' flag to false" do
76
+ mock(app).update!
77
+ expect { subject }.to change(app, :production).from(true).to(false)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -5,7 +5,6 @@ describe VMC::App::Stats do
5
5
  let(:global) { { :color => false } }
6
6
  let(:inputs) { {:app => apps[0]} }
7
7
  let(:given) { {} }
8
- let(:output) { StringIO.new }
9
8
  let(:client) { fake_client(:apps => apps) }
10
9
  let(:apps) { [fake(:app, :name => "basic_app")] }
11
10
 
@@ -33,9 +32,7 @@ describe VMC::App::Stats do
33
32
  end
34
33
 
35
34
  subject do
36
- with_output_to output do
37
- Mothership.new.invoke(:stats, inputs, given, global)
38
- end
35
+ capture_output { Mothership.new.invoke(:stats, inputs, given, global) }
39
36
  end
40
37
 
41
38
  describe 'metadata' do
@@ -59,8 +56,7 @@ describe VMC::App::Stats do
59
56
 
60
57
  it 'prints out the stats' do
61
58
  subject
62
-
63
- output.rewind
64
- expect(output.readlines.last).to match /.*0\s+0\.0% of\s+cores\s+29\.9M of 288M\s+14\.9M of 256M.*/
59
+ stdout.rewind
60
+ expect(stdout.readlines.last).to match /.*0\s+0\.0% of\s+cores\s+29\.9M of 288M\s+14\.9M of 256M.*/
65
61
  end
66
62
  end
@@ -0,0 +1,140 @@
1
+ require 'spec_helper'
2
+
3
+ describe VMC::Domain::Map do
4
+ let(:global) { { :color => false } }
5
+ let(:given) { {} }
6
+ let(:client) { fake_client :current_organization => organization, :current_space => space }
7
+ let!(:cli) { described_class.new }
8
+
9
+ before do
10
+ stub(cli).client { client }
11
+ stub_output(cli)
12
+ end
13
+
14
+ let(:organization) { fake(:organization) }
15
+ let(:space) { fake(:space) }
16
+ let(:domain) { fake(:domain, :name => domain_name) }
17
+ let(:domain_name) { "some.domain.com" }
18
+
19
+ subject { invoke_cli(cli, :map_domain, inputs, given, global) }
20
+
21
+ shared_examples "binding a domain to a space" do
22
+ it "adds the domain to the space's organization" do
23
+ mock(space.organization).add_domain(domain)
24
+ stub(space).add_domain(domain)
25
+ subject
26
+ end
27
+
28
+ it 'adds the domain to the space' do
29
+ stub(space.organization).add_domain(domain)
30
+ mock(space).add_domain(domain)
31
+ subject
32
+ end
33
+ end
34
+
35
+ shared_examples "binding a domain to an organization" do
36
+ it 'does NOT add the domain to a space' do
37
+ any_instance_of(space.class) do |space|
38
+ dont_allow(space).add_domain(domain)
39
+ end
40
+ end
41
+
42
+ it 'adds the domain to the organization' do
43
+ mock(organization).add_domain(domain)
44
+ subject
45
+ end
46
+ end
47
+
48
+ shared_examples "mapping a domain to a space" do
49
+ context "when the domain does NOT exist" do
50
+ before do
51
+ stub(client).domain { domain }
52
+ stub(domain).create!
53
+ stub(space.organization).add_domain(domain)
54
+ stub(space).add_domain(domain)
55
+ end
56
+
57
+ it 'creates the domain' do
58
+ mock(domain).create!
59
+ subject
60
+ expect(domain.name).to eq domain_name
61
+ expect(domain.owning_organization).to eq organization
62
+ end
63
+
64
+ include_examples "binding a domain to a space"
65
+ end
66
+
67
+ context "when the domain already exists" do
68
+ let(:client) {
69
+ fake_client :domains => [domain],
70
+ :current_organization => organization,
71
+ :current_space => space
72
+ }
73
+
74
+ include_examples "binding a domain to a space"
75
+ end
76
+ end
77
+
78
+ context 'when a domain and a space are passed' do
79
+ let(:inputs) { { :space => space, :name => domain_name } }
80
+
81
+ include_examples "mapping a domain to a space"
82
+ end
83
+
84
+ context 'when a domain and an organization are passed' do
85
+ let(:inputs) { { :organization => organization, :name => domain_name } }
86
+
87
+ context "and the domain does NOT exist" do
88
+ before do
89
+ stub(client).domain { domain }
90
+ stub(domain).create!
91
+ stub(organization).add_domain(domain)
92
+ end
93
+
94
+ include_examples "binding a domain to an organization"
95
+
96
+ it 'adds the domain to the organization' do
97
+ mock(organization).add_domain(domain)
98
+ subject
99
+ end
100
+
101
+ context "and the --shared option is passed" do
102
+ let(:inputs) { { :organization => organization, :name => domain_name, :shared => true } }
103
+
104
+ it 'adds the domain to the organization' do
105
+ mock(domain).create!
106
+ subject
107
+ expect(domain.name).to eq domain_name
108
+ end
109
+
110
+ it "does not add the domain to a specific organization" do
111
+ stub(domain).create!
112
+ subject
113
+ expect(domain.owning_organization).to be_nil
114
+ end
115
+ end
116
+ end
117
+
118
+ context "and the domain already exists" do
119
+ let(:client) {
120
+ fake_client :domains => [domain],
121
+ :current_organization => organization,
122
+ :current_space => space
123
+ }
124
+
125
+ include_examples "binding a domain to an organization"
126
+ end
127
+ end
128
+
129
+ context 'when a domain, organization, and space is passed' do
130
+ let(:inputs) { { :name => domain_name, :organization => organization, :space => space } }
131
+
132
+ include_examples "mapping a domain to a space"
133
+ end
134
+
135
+ context 'when only a domain is passed' do
136
+ let(:inputs) { { :name => domain_name } }
137
+
138
+ include_examples "mapping a domain to a space"
139
+ end
140
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe VMC::Domain::Unmap do
4
+ let(:global) { { :color => false } }
5
+ let(:given) { {} }
6
+ let(:client) { fake_client :current_organization => organization, :current_space => space }
7
+ let!(:cli) { described_class.new }
8
+
9
+ before do
10
+ stub(cli).client { client }
11
+ stub_output(cli)
12
+ end
13
+
14
+ let(:organization) { fake(:organization) }
15
+ let(:space) { fake(:space) }
16
+ let(:domain) { fake(:domain, :name => domain_name) }
17
+ let(:domain_name) { "some.domain.com" }
18
+
19
+ subject { invoke_cli(cli, :unmap_domain, inputs, given, global) }
20
+
21
+ context "when the --delete flag is given" do
22
+ let(:inputs) { { :domain => domain, :delete => true } }
23
+
24
+ it "asks for a confirmation" do
25
+ mock_ask("Really delete #{domain_name}?", :default => false) { false }
26
+ stub(domain).delete!
27
+ subject
28
+ end
29
+
30
+ context "and the user answers 'no' to the confirmation" do
31
+ it "does NOT delete the domain" do
32
+ stub_ask("Really delete #{domain_name}?", anything) { false }
33
+ dont_allow(domain).delete!
34
+ subject
35
+ end
36
+ end
37
+
38
+ context "and the user answers 'yes' to the confirmation" do
39
+ it "deletes the domain" do
40
+ stub_ask("Really delete #{domain_name}?", anything) { true }
41
+ mock(domain).delete!
42
+ subject
43
+ end
44
+ end
45
+ end
46
+
47
+ context "when a space is given" do
48
+ let(:inputs) { { :domain => domain, :space => space } }
49
+
50
+ it "unmaps the domain from the space" do
51
+ mock(space).remove_domain(domain)
52
+ subject
53
+ end
54
+ end
55
+
56
+ context "when an organization is given" do
57
+ let(:inputs) { { :domain => domain, :organization => organization } }
58
+
59
+ it "unmaps the domain from the organization" do
60
+ mock(organization).remove_domain(domain)
61
+ subject
62
+ end
63
+ end
64
+
65
+ context "when only the domain is given" do
66
+ let(:inputs) { { :domain => domain } }
67
+
68
+ it "unmaps the domain from the current space" do
69
+ mock(client.current_space).remove_domain(domain)
70
+ subject
71
+ end
72
+ end
73
+ end