vmc 0.0.8 → 0.2.4

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.
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