vmc 0.0.8 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/LICENSE +8 -3
  2. data/README.md +83 -0
  3. data/Rakefile +11 -65
  4. data/bin/vmc +3 -2
  5. data/lib/cli/commands/admin.rb +57 -0
  6. data/lib/cli/commands/apps.rb +828 -0
  7. data/lib/cli/commands/base.rb +56 -0
  8. data/lib/cli/commands/misc.rb +99 -0
  9. data/lib/cli/commands/services.rb +84 -0
  10. data/lib/cli/commands/user.rb +60 -0
  11. data/lib/cli/config.rb +109 -0
  12. data/lib/cli/core_ext.rb +119 -0
  13. data/lib/cli/errors.rb +19 -0
  14. data/lib/cli/frameworks.rb +97 -0
  15. data/lib/cli/runner.rb +437 -0
  16. data/lib/cli/services_helper.rb +74 -0
  17. data/lib/cli/usage.rb +94 -0
  18. data/lib/cli/version.rb +5 -0
  19. data/lib/cli/zip_util.rb +61 -0
  20. data/lib/cli.rb +30 -0
  21. data/lib/vmc/client.rb +415 -0
  22. data/lib/vmc/const.rb +19 -0
  23. data/lib/vmc.rb +2 -1589
  24. data/spec/assets/app_info.txt +9 -0
  25. data/spec/assets/app_listings.txt +9 -0
  26. data/spec/assets/bad_create_app.txt +9 -0
  27. data/spec/assets/delete_app.txt +9 -0
  28. data/spec/assets/global_service_listings.txt +9 -0
  29. data/spec/assets/good_create_app.txt +9 -0
  30. data/spec/assets/good_create_service.txt +9 -0
  31. data/spec/assets/info_authenticated.txt +27 -0
  32. data/spec/assets/info_return.txt +15 -0
  33. data/spec/assets/info_return_bad.txt +16 -0
  34. data/spec/assets/login_fail.txt +9 -0
  35. data/spec/assets/login_success.txt +9 -0
  36. data/spec/assets/sample_token.txt +1 -0
  37. data/spec/assets/service_already_exists.txt +9 -0
  38. data/spec/assets/service_listings.txt +9 -0
  39. data/spec/assets/service_not_found.txt +9 -0
  40. data/spec/assets/user_info.txt +9 -0
  41. data/spec/spec_helper.rb +11 -0
  42. data/spec/unit/cli_opts_spec.rb +73 -0
  43. data/spec/unit/client_spec.rb +284 -0
  44. metadata +114 -71
  45. data/README +0 -58
  46. data/lib/parse.rb +0 -719
  47. data/lib/vmc_base.rb +0 -205
  48. data/vendor/gems/httpclient/VERSION +0 -1
  49. data/vendor/gems/httpclient/lib/http-access2/cookie.rb +0 -1
  50. data/vendor/gems/httpclient/lib/http-access2/http.rb +0 -1
  51. data/vendor/gems/httpclient/lib/http-access2.rb +0 -53
  52. data/vendor/gems/httpclient/lib/httpclient/auth.rb +0 -522
  53. data/vendor/gems/httpclient/lib/httpclient/cacert.p7s +0 -1579
  54. data/vendor/gems/httpclient/lib/httpclient/cacert_sha1.p7s +0 -1579
  55. data/vendor/gems/httpclient/lib/httpclient/connection.rb +0 -84
  56. data/vendor/gems/httpclient/lib/httpclient/cookie.rb +0 -562
  57. data/vendor/gems/httpclient/lib/httpclient/http.rb +0 -867
  58. data/vendor/gems/httpclient/lib/httpclient/session.rb +0 -864
  59. data/vendor/gems/httpclient/lib/httpclient/ssl_config.rb +0 -417
  60. data/vendor/gems/httpclient/lib/httpclient/timeout.rb +0 -136
  61. data/vendor/gems/httpclient/lib/httpclient/util.rb +0 -86
  62. data/vendor/gems/httpclient/lib/httpclient.rb +0 -1020
  63. data/vendor/gems/httpclient/lib/tags +0 -908
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 200 OK
2
+ Server: nginx/0.7.65
3
+ Date: Fri, 04 Mar 2011 02:56:21 GMT
4
+ Content-Type: application/json
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 243
8
+
9
+ {"resources":{"memory":64},"uris":["foo.vcap.me"],"staging":{"stack":"ruby foo.rb","model":"http://b20nine.com/unknown"},"state":"STARTED","instances":1,"name":"foo","meta":{"version":1,"created":1299207348},"services":[],"runningInstances":1}
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 200 OK
2
+ Server: nginx/0.7.65
3
+ Date: Thu, 03 Mar 2011 19:46:19 GMT
4
+ Content-Type: application/json
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 251
8
+
9
+ [{"resources":{"memory":128},"uris":["r.vcap.me"],"staging":{"stack":"ruby redis_sample.rb","model":"http://b20nine.com/unknown"},"state":"STARTED","instances":1,"name":"r","meta":{"version":1,"created":1298681379},"services":[],"runningInstances":1}]
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 400 Bad Request
2
+ Server: nginx/0.7.65
3
+ Date: Thu, 03 Mar 2011 23:37:51 GMT
4
+ Content-Type: text/html;charset=utf-8
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 157
8
+
9
+ {"code":10050,"description":"Invalid number of instances: \"'', App instances not presentApp instances is not a numberInstances must be between 1 and 100\""}
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 204
2
+ Server: nginx/0.7.65
3
+ Date: Fri, 04 Mar 2011 00:07:10 GMT
4
+ Content-Type: text/html;charset=utf-8
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Location: http://api.vcap.me/apps/foo
8
+ Content-Length: 0
9
+
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 200 OK
2
+ Server: nginx/0.7.65
3
+ Date: Thu, 03 Mar 2011 20:20:15 GMT
4
+ Content-Type: application/json
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 381
8
+
9
+ {"key-value":{"redis":{"2":{"type":"key-value","tiers":{"free":{"order":1,"description":"Free offering (64MiB)"}},"version":"2","vendor":"redis","description":"Redis key-value store service"}}},"database":{"mysql":{"5.1":{"type":"database","tiers":{"free":{"order":1,"description":"Free offering (1GiB)"}},"version":"5.1","description":"MySQL database service","vendor":"mysql"}}}}
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 302 Moved Temporarily
2
+ Server: nginx/0.7.65
3
+ Date: Fri, 04 Mar 2011 00:07:10 GMT
4
+ Content-Type: text/html;charset=utf-8
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Location: http://api.vcap.me/apps/foo
8
+ Content-Length: 0
9
+
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 302 Moved Temporarily
2
+ Server: nginx/0.7.65
3
+ Date: Fri, 04 Mar 2011 02:15:55 GMT
4
+ Content-Type: text/html;charset=utf-8
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Location: http://api.vcap.me/services/redis-86b7a8655555
8
+ Content-Length: 0
9
+
@@ -0,0 +1,27 @@
1
+ HTTP/1.1 200 OK
2
+ Server: nginx/0.7.65
3
+ Date: Thu, 03 Mar 2011 19:25:34 GMT
4
+ Content-Type: application/json
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 380
8
+
9
+ {
10
+ "name": "vcap",
11
+ "build": "3465a13ab528443f1afcd3c9c2861a078549b8e5",
12
+ "support": "ac-support@vmware.com",
13
+ "version": 0.999,
14
+ "limits": {
15
+ "apps": 50,
16
+ "memory": 8192,
17
+ "app_uris": 4,
18
+ "services": 4
19
+ },
20
+ "user": "derek@gmail.com",
21
+ "description": "VMware's Cloud Application Platform",
22
+ "usage": {
23
+ "apps": 1,
24
+ "memory": 128,
25
+ "services": 0
26
+ }
27
+ }
@@ -0,0 +1,15 @@
1
+ HTTP/1.1 200 OK
2
+ Server: nginx/0.7.65
3
+ Date: Thu, 03 Mar 2011 19:04:04 GMT
4
+ Content-Type: application/json
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 189
8
+
9
+ {
10
+ "name": "vcap",
11
+ "build": "3465a13ab528443f1afcd3c9c2861a078549b8e5",
12
+ "support": "ac-support@vmware.com",
13
+ "version": 0.999,
14
+ "description": "VMware's Cloud Application Platform"
15
+ }
@@ -0,0 +1,16 @@
1
+ HTTP/1.1 301 Moved Permanently
2
+ Location: http://www.google.com/
3
+ Content-Type: text/html; charset=UTF-8
4
+ Date: Thu, 03 Mar 2011 19:06:04 GMT
5
+ Expires: Sat, 02 Apr 2011 19:06:04 GMT
6
+ Cache-Control: public, max-age=2592000
7
+ Server: gws
8
+ Content-Length: 219
9
+ X-XSS-Protection: 1; mode=block
10
+
11
+ <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
12
+ <TITLE>301 Moved</TITLE></HEAD><BODY>
13
+ <H1>301 Moved</H1>
14
+ The document has moved
15
+ <A HREF="http://www.google.com/">here</A>.
16
+ </BODY></HTML>
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 403 Forbidden
2
+ Server: nginx/0.7.65
3
+ Date: Thu, 03 Mar 2011 18:29:40 GMT
4
+ Content-Type: application/json
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 43
8
+
9
+ {"code":2002,"description":"Invalid token"}
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 200 OK
2
+ Server: nginx/0.7.65
3
+ Date: Thu, 03 Mar 2011 18:26:45 GMT
4
+ Content-Type: application/json
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 112
8
+
9
+ {"token":"04085b082214646572656b40676d61696c2e636f6d6c2b07e517794d22198e59d96b40ccbc3625964dfb8dcca21174835d7e"}
@@ -0,0 +1 @@
1
+ 04085b082214646572656b40676d61696c2e636f6d6c2b07f014794d2219b3dd205faeaefc0a8c70bb3ba786628c8cb8d667
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 400 Bad Request
2
+ Server: nginx/0.7.65
3
+ Date: Fri, 04 Mar 2011 02:19:28 GMT
4
+ Content-Type: text/html;charset=utf-8
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 93
8
+
9
+ {"code":20001,"description":"A service with the name: \"redis-86b7a8655555\" already exists"}
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 200 OK
2
+ Server: nginx/0.7.65
3
+ Date: Thu, 03 Mar 2011 21:46:29 GMT
4
+ Content-Type: application/json
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 313
8
+
9
+ [{"type":"key-value","vendor":"redis","version":"2","options":{"name":"redis-83ddf593-0690-4856-baba-24cc7ad9b1b0","port":6148,"node_id":"redis_node_1","hostname":"127.0.0.1","password":"2167d1f8-c251-46a8-8eed-7d390ab74757"},"tier":"free","name":"redis-7ed7da9","meta":{"version":1,"created":1299188448},"id":3}]
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 404 Not Found
2
+ Server: nginx/0.7.65
3
+ Date: Fri, 04 Mar 2011 02:26:39 GMT
4
+ Content-Type: text/html;charset=utf-8
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 75
8
+
9
+ {"code":21100,"description":"Service provision call failed due to timeout"}
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 200 OK
2
+ Server: nginx/0.7.65
3
+ Date: Thu, 03 Mar 2011 19:38:32 GMT
4
+ Content-Type: application/json
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 69
8
+
9
+ {"meta":{"version":1,"created":1298681367},"email":"derek@gmail.com"}
@@ -0,0 +1,11 @@
1
+
2
+ $:.unshift('./lib')
3
+ require 'vmc'
4
+ require 'cli'
5
+
6
+ require 'spec'
7
+ require 'webmock/rspec'
8
+
9
+ def spec_asset(filename)
10
+ File.expand_path(File.join(File.dirname(__FILE__), "assets", filename))
11
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'VMC::Cli::Runner' do
4
+
5
+ it 'should parse email and password correctly' do
6
+ args = "--email derek@gmail.com --password foo"
7
+ cli = VMC::Cli::Runner.new(args.split).parse_options!
8
+ cli.options.should have(3).items
9
+ cli.options.should have_key :email
10
+ cli.options[:email].should == 'derek@gmail.com'
11
+ cli.options[:password].should == 'foo'
12
+ end
13
+
14
+ it 'should parse multiple variations of password' do
15
+ args = "--password foo"
16
+ cli = VMC::Cli::Runner.new(args.split).parse_options!
17
+ cli.options[:password].should == 'foo'
18
+
19
+ args = "--pass foo"
20
+ cli = VMC::Cli::Runner.new(args.split).parse_options!
21
+ cli.options[:password].should == 'foo'
22
+
23
+ args = "--passwd foo"
24
+ cli = VMC::Cli::Runner.new(args.split).parse_options!
25
+ cli.options[:password].should == 'foo'
26
+ end
27
+
28
+ it 'should parse name and bind args correctly' do
29
+ args = "--name foo --bind bar"
30
+ cli = VMC::Cli::Runner.new(args.split).parse_options!
31
+ cli.options[:name].should == 'foo'
32
+ cli.options[:bind].should == 'bar'
33
+ end
34
+
35
+ it 'should parse instance and instances correctly into numbers' do
36
+ args = "--instances 1 --instance 2"
37
+ cli = VMC::Cli::Runner.new(args.split).parse_options!
38
+ cli.options[:instances].should == 1
39
+ cli.options[:instance].should == 2
40
+ end
41
+
42
+ it 'should complain if instance arg is not a number' do
43
+ args = "--instance foo"
44
+ expect { VMC::Cli::Runner.new(args.split).parse_options! }.to raise_error
45
+ end
46
+
47
+ it 'should parse url, mem, path correctly' do
48
+ args = "--mem 64 --url http://foo.vcap.me --path ~derek"
49
+ cli = VMC::Cli::Runner.new(args.split).parse_options!
50
+ cli.options[:mem].should == '64'
51
+ cli.options[:url].should == 'http://foo.vcap.me'
52
+ cli.options[:path].should == '~derek'
53
+ end
54
+
55
+ it 'should parse multiple forms of nostart correctly' do
56
+ cli = VMC::Cli::Runner.new().parse_options!
57
+ cli.options[:nostart].should_not be
58
+ args = "--nostart"
59
+ cli = VMC::Cli::Runner.new(args.split).parse_options!
60
+ cli.options[:nostart].should be_true
61
+ args = "--no-start"
62
+ cli = VMC::Cli::Runner.new(args.split).parse_options!
63
+ cli.options[:nostart].should be_true
64
+ end
65
+
66
+ it 'should parse force and all correctly' do
67
+ args = "--force --all"
68
+ cli = VMC::Cli::Runner.new(args.split).parse_options!
69
+ cli.options[:force].should be_true
70
+ cli.options[:all].should be_true
71
+ end
72
+
73
+ end
@@ -0,0 +1,284 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'VMC::Client' do
4
+ include WebMock::API
5
+
6
+ before(:all) do
7
+ @target = VMC::DEFAULT_TARGET
8
+ @local_target = VMC::DEFAULT_LOCAL_TARGET
9
+ @user = 'derek@gmail.com'
10
+ @password = 'foo'
11
+ @auth_token = spec_asset('sample_token.txt')
12
+ end
13
+
14
+ it 'should report its version' do
15
+ VMC::Client.version.should =~ /\d.\d.\d/
16
+ end
17
+
18
+ it 'should default to local target' do
19
+ client = VMC::Client.new
20
+ client.target.should == VMC::DEFAULT_TARGET
21
+ end
22
+
23
+ it 'should normalize target with no scheme' do
24
+ client = VMC::Client.new('api.cloudfoundry.com')
25
+ client.target.should == @target
26
+ end
27
+
28
+ it 'should properly initialize with auth_token' do
29
+ client = VMC::Client.new(@target, @auth_token)
30
+ client.target.should == @target
31
+ client.auth_token.should == @auth_token
32
+ end
33
+
34
+ it 'should allow login correctly and return an auth_token' do
35
+ login_path = "#{@local_target}/users/#{@user}/tokens"
36
+ stub_request(:post, login_path).to_return(File.new(spec_asset('login_success.txt')))
37
+ client = VMC::Client.new(@local_target)
38
+ auth_token = client.login(@user, @password)
39
+ client.target.should == @local_target
40
+ client.user.should == @user
41
+ client.auth_token.should be
42
+ auth_token.should be
43
+ auth_token.should == client.auth_token
44
+ end
45
+
46
+ it 'should raise exception if login fails' do
47
+ login_path = "#{@local_target}/users/#{@user}/tokens"
48
+ stub_request(:post, login_path).to_return(File.new(spec_asset('login_fail.txt')))
49
+ client = VMC::Client.new(@local_target)
50
+ expect { client.login(@user, @password) }.to raise_error(VMC::Client::TargetError)
51
+ end
52
+
53
+ it 'should allow admin users to proxy for others' do
54
+ proxy = 'vadim@gmail.com'
55
+ client = VMC::Client.new(@target)
56
+ client.proxy_for(proxy)
57
+ client.proxy.should == proxy
58
+ end
59
+
60
+ it 'should properly get info for valid target cloud' do
61
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
62
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_return.txt')))
63
+ client = VMC::Client.new(@local_target)
64
+ info = client.info
65
+ a_request(:get, info_path).should have_been_made.once
66
+ info.should have_key :support
67
+ info.should have_key :description
68
+ info.should have_key :name
69
+ info.should have_key :version
70
+ info.should have_key :build
71
+ end
72
+
73
+ it 'should raise and exception for a bad target' do
74
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
75
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_return_bad.txt')))
76
+ client = VMC::Client.new(@local_target)
77
+ expect {info = client.info}.to raise_error(VMC::Client::BadResponse)
78
+ a_request(:get, info_path).should have_been_made.once
79
+ end
80
+
81
+ it 'should have target_valid? return true for a good target' do
82
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
83
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_return.txt')))
84
+ client = VMC::Client.new(@local_target)
85
+ client.target_valid?.should be_true
86
+ end
87
+
88
+ it 'should have target_valid? return false for a bad target' do
89
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
90
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_return_bad.txt')))
91
+ client = VMC::Client.new(@local_target)
92
+ client.target_valid?.should be_false
93
+ end
94
+
95
+ it 'should respond ok if properly logged in' do
96
+ login_path = "#{@local_target}/users/#{@user}/tokens"
97
+ stub_request(:post, login_path).to_return(File.new(spec_asset('login_success.txt')))
98
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
99
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
100
+ client = VMC::Client.new(@local_target)
101
+ client.login(@user, @password)
102
+ client.logged_in?.should be_true
103
+ end
104
+
105
+ it 'should fail when trying to change password unless logged in' do
106
+ login_path = "#{@local_target}/users/#{@user}/tokens"
107
+ stub_request(:post, login_path).to_return(File.new(spec_asset('login_success.txt')))
108
+ user_info_path = "#{@local_target}/users/#{@user}"
109
+ stub_request(:get, user_info_path).to_return(File.new(spec_asset('user_info.txt')))
110
+ stub_request(:put, user_info_path)
111
+ client = VMC::Client.new(@local_target)
112
+ client.login(@user, @password)
113
+ client.change_password('bar')
114
+ end
115
+
116
+ it 'should get a proper list of apps' do
117
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
118
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
119
+ apps_path = "#{@local_target}#{VMC::APPS_PATH}"
120
+ stub_request(:get, apps_path).to_return(File.new(spec_asset('app_listings.txt')))
121
+ client = VMC::Client.new(@local_target, @auth_token)
122
+ apps = client.apps
123
+ apps.should have(1).items
124
+ app = apps.first
125
+ app.should have_key :state
126
+ app.should have_key :uris
127
+ app.should have_key :name
128
+ app.should have_key :services
129
+ app.should have_key :instances
130
+ end
131
+
132
+ it 'should get a proper list of services' do
133
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
134
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
135
+ services_path = "#{@local_target}#{VMC::GLOBAL_SERVICES_PATH}"
136
+ stub_request(:get, services_path).to_return(File.new(spec_asset('global_service_listings.txt')))
137
+ client = VMC::Client.new(@local_target, @auth_token)
138
+ services = client.services_info
139
+ services.should have(2).items
140
+ # FIXME, add in more details.
141
+ end
142
+
143
+ it 'should get a proper list of provisioned services' do
144
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
145
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
146
+ services_path = "#{@local_target}#{VMC::SERVICES_PATH}"
147
+ stub_request(:get, services_path).to_return(File.new(spec_asset('service_listings.txt')))
148
+ client = VMC::Client.new(@local_target, @auth_token)
149
+ app_services = client.services
150
+ app_services.should have(1).items
151
+ redis = app_services.first
152
+ redis.should have_key :type
153
+ redis.should have_key :vendor
154
+ end
155
+
156
+ it 'should raise when trying to create an app with no manifest' do
157
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
158
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
159
+ app_path = "#{@local_target}#{VMC::APPS_PATH}"
160
+ stub_request(:post, app_path).to_return(File.new(spec_asset('bad_create_app.txt')))
161
+ client = VMC::Client.new(@local_target, @auth_token)
162
+ expect { client.create_app('foo') }.to raise_error(VMC::Client::NotFound)
163
+ end
164
+
165
+ it 'should create an app with a simple manifest' do
166
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
167
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
168
+ app_path = "#{@local_target}#{VMC::APPS_PATH}"
169
+ stub_request(:post, app_path).to_return(File.new(spec_asset('good_create_app.txt')))
170
+ client = VMC::Client.new(@local_target, @auth_token)
171
+ manifest = {
172
+ :name => 'foo',
173
+ :uris => ['foo.vcap.me'],
174
+ :instances => 1,
175
+ :staging => { :model => 'nodejs/1.0' },
176
+ :resources => { :memory => 64 }
177
+ }
178
+ client.create_app('foo', manifest)
179
+ end
180
+
181
+ it 'should allow us to delete an app we created' do
182
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
183
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
184
+ app_path = "#{@local_target}#{VMC::APPS_PATH}/foo"
185
+ stub_request(:delete, app_path).to_return(File.new(spec_asset('delete_app.txt')))
186
+ client = VMC::Client.new(@local_target, @auth_token)
187
+ client.delete_app('foo')
188
+ end
189
+
190
+ it 'should provision a service' do
191
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
192
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
193
+ global_services_path = "#{@local_target}#{VMC::GLOBAL_SERVICES_PATH}"
194
+ stub_request(:get, global_services_path).to_return(File.new(spec_asset('global_service_listings.txt')))
195
+ services_path = "#{@local_target}#{VMC::SERVICES_PATH}"
196
+ stub_request(:post, services_path).to_return(File.new(spec_asset('good_create_service.txt')))
197
+ client = VMC::Client.new(@local_target, @auth_token)
198
+ client.create_service('redis', 'foo')
199
+ end
200
+
201
+ it 'should complain if we try to provision a service that already exists with same name' do
202
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
203
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
204
+ global_services_path = "#{@local_target}#{VMC::GLOBAL_SERVICES_PATH}"
205
+ stub_request(:get, global_services_path).to_return(File.new(spec_asset('global_service_listings.txt')))
206
+ services_path = "#{@local_target}#{VMC::SERVICES_PATH}"
207
+ stub_request(:post, services_path).to_return(File.new(spec_asset('service_already_exists.txt')))
208
+ client = VMC::Client.new(@local_target, @auth_token)
209
+ expect { client.create_service('redis', 'foo') }.to raise_error(VMC::Client::NotFound)
210
+ end
211
+
212
+ it 'should complain if we try to provision a service that does not exist' do
213
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
214
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
215
+ global_services_path = "#{@local_target}#{VMC::GLOBAL_SERVICES_PATH}"
216
+ stub_request(:get, global_services_path).to_return(File.new(spec_asset('global_service_listings.txt')))
217
+ services_path = "#{@local_target}#{VMC::SERVICES_PATH}"
218
+ stub_request(:post, services_path).to_return(File.new(spec_asset('service_not_found.txt')))
219
+ client = VMC::Client.new(@local_target, @auth_token)
220
+ expect { client.create_service('redis', 'foo') }.to raise_error(VMC::Client::NotFound)
221
+ end
222
+
223
+ it 'should allow us to delete a provisioned service' do
224
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
225
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
226
+ services_path = "#{@local_target}#{VMC::SERVICES_PATH}"
227
+ stub_request(:get, services_path).to_return(File.new(spec_asset('service_listings.txt')))
228
+ services_path = "#{@local_target}#{VMC::SERVICES_PATH}/redis-7ed7da9"
229
+ stub_request(:delete, services_path)
230
+ client = VMC::Client.new(@local_target, @auth_token)
231
+ client.delete_service('redis-7ed7da9')
232
+ end
233
+
234
+ it 'should bind a service to an app' do
235
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
236
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
237
+ app_path = "#{@local_target}#{VMC::APPS_PATH}/foo"
238
+ stub_request(:get, app_path).to_return(File.new(spec_asset('app_info.txt')))
239
+ stub_request(:put, app_path)
240
+ client = VMC::Client.new(@local_target, @auth_token)
241
+ client.bind_service('my-redis', 'foo')
242
+ a_request(:get, app_path).should have_been_made.once
243
+ a_request(:put, app_path).should have_been_made.once
244
+ end
245
+
246
+ it 'should unbind an existing service from an app' do
247
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
248
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_authenticated.txt')))
249
+ app_path = "#{@local_target}#{VMC::APPS_PATH}/foo"
250
+ stub_request(:get, app_path).to_return(File.new(spec_asset('app_info.txt')))
251
+ stub_request(:put, app_path)
252
+ client = VMC::Client.new(@local_target, @auth_token)
253
+ client.unbind_service('my-redis', 'foo')
254
+ a_request(:get, app_path).should have_been_made.once
255
+ a_request(:put, app_path).should have_been_made.once
256
+ end
257
+
258
+ it 'should set a proxy if one is set' do
259
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
260
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_return.txt')))
261
+ proxy = 'http://proxy.vmware.com:3128'
262
+ ENV['http_proxy'] = proxy
263
+ client = VMC::Client.new(@local_target)
264
+ info = client.info
265
+ RestClient.proxy.should == proxy
266
+ ENV['http_proxy'] = nil
267
+ end
268
+
269
+ it 'should set a secure proxy over a normal proxy if one is set' do
270
+ info_path = "#{@local_target}#{VMC::INFO_PATH}"
271
+ stub_request(:get, info_path).to_return(File.new(spec_asset('info_return.txt')))
272
+ proxy = 'http://proxy.vmware.com:3128'
273
+ secure_proxy = 'https://proxy.vmware.com:3128'
274
+ ENV['http_proxy'] = proxy
275
+ ENV['https_proxy'] = secure_proxy
276
+ client = VMC::Client.new(@local_target)
277
+ info = client.info
278
+ RestClient.proxy.should == secure_proxy
279
+ ENV['http_proxy'] = ENV['https_proxy'] = nil
280
+ end
281
+
282
+ # WebMock.allow_net_connect!
283
+
284
+ end