cfoundry 0.5.1.rc2 → 0.5.1.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/lib/cc_api_stub.rb +17 -0
  2. data/lib/cc_api_stub/applications.rb +53 -0
  3. data/lib/cc_api_stub/domains.rb +16 -0
  4. data/lib/cc_api_stub/frameworks.rb +22 -0
  5. data/lib/cc_api_stub/helper.rb +131 -0
  6. data/lib/cc_api_stub/login.rb +21 -0
  7. data/lib/cc_api_stub/organization_users.rb +21 -0
  8. data/lib/cc_api_stub/organizations.rb +70 -0
  9. data/lib/cc_api_stub/routes.rb +26 -0
  10. data/lib/cc_api_stub/runtimes.rb +22 -0
  11. data/lib/cc_api_stub/service_bindings.rb +22 -0
  12. data/lib/cc_api_stub/service_instances.rb +22 -0
  13. data/lib/cc_api_stub/services.rb +25 -0
  14. data/lib/cc_api_stub/spaces.rb +49 -0
  15. data/lib/cc_api_stub/users.rb +84 -0
  16. data/lib/cfoundry/baseclient.rb +24 -0
  17. data/lib/cfoundry/errors.rb +16 -133
  18. data/lib/cfoundry/v1/app.rb +6 -2
  19. data/lib/cfoundry/v2/app.rb +16 -4
  20. data/lib/cfoundry/v2/base.rb +10 -11
  21. data/lib/cfoundry/v2/client.rb +4 -0
  22. data/lib/cfoundry/version.rb +1 -1
  23. data/spec/cc_api_stub/applications_spec.rb +69 -0
  24. data/spec/cc_api_stub/domains_spec.rb +19 -0
  25. data/spec/cc_api_stub/frameworks_spec.rb +19 -0
  26. data/spec/cc_api_stub/login_spec.rb +20 -0
  27. data/spec/cc_api_stub/organization_users_spec.rb +19 -0
  28. data/spec/cc_api_stub/organizations_spec.rb +103 -0
  29. data/spec/cc_api_stub/routes_spec.rb +19 -0
  30. data/spec/cc_api_stub/runtimes_spec.rb +19 -0
  31. data/spec/cc_api_stub/service_bindings_spec.rb +13 -0
  32. data/spec/cc_api_stub/service_instances_spec.rb +19 -0
  33. data/spec/cc_api_stub/services_spec.rb +12 -0
  34. data/spec/cc_api_stub/spaces_spec.rb +38 -0
  35. data/spec/cc_api_stub/users_spec.rb +107 -0
  36. data/spec/cfoundry/baseclient_spec.rb +42 -2
  37. data/spec/cfoundry/v2/app_spec.rb +95 -0
  38. data/spec/fixtures/fake_cc_application.json +24 -0
  39. data/spec/fixtures/fake_cc_application_summary.json +57 -0
  40. data/spec/fixtures/fake_cc_created_application.json +11 -0
  41. data/spec/fixtures/fake_cc_created_domain.json +10 -0
  42. data/spec/fixtures/fake_cc_created_organization.json +11 -0
  43. data/spec/fixtures/fake_cc_created_route.json +13 -0
  44. data/spec/fixtures/fake_cc_created_service_instance.json +11 -0
  45. data/spec/fixtures/fake_cc_created_space.json +11 -0
  46. data/spec/fixtures/fake_cc_created_user.json +11 -0
  47. data/spec/fixtures/fake_cc_empty_search.json +7 -0
  48. data/spec/fixtures/fake_cc_frameworks.json +20 -0
  49. data/spec/fixtures/fake_cc_organization.json +144 -0
  50. data/spec/fixtures/fake_cc_organization_domains.json +34 -0
  51. data/spec/fixtures/fake_cc_organization_search.json +37 -0
  52. data/spec/fixtures/fake_cc_organization_summary.json +19 -0
  53. data/spec/fixtures/fake_cc_organization_users.json +81 -0
  54. data/spec/fixtures/fake_cc_runtimes.json +20 -0
  55. data/spec/fixtures/fake_cc_service_binding.json +22 -0
  56. data/spec/fixtures/fake_cc_service_bindings.json +24 -0
  57. data/spec/fixtures/fake_cc_service_instance.json +81 -0
  58. data/spec/fixtures/fake_cc_service_instances.json +0 -0
  59. data/spec/fixtures/fake_cc_service_types.json +124 -0
  60. data/spec/fixtures/fake_cc_space.json +45 -0
  61. data/spec/fixtures/fake_cc_space_summary.json +86 -0
  62. data/spec/fixtures/fake_cc_stats.json +29 -0
  63. data/spec/fixtures/fake_cc_user.json +112 -0
  64. data/spec/fixtures/fake_cc_user_organizations.json +92 -0
  65. data/spec/fixtures/fake_cc_user_with_managers.json +85 -0
  66. data/spec/spec_helper.rb +3 -0
  67. data/spec/support/fake_helper.rb +0 -36
  68. data/spec/support/shared_examples/cc_api_stub_request_examples.rb +79 -0
  69. metadata +254 -144
@@ -0,0 +1,25 @@
1
+ module CcApiStub
2
+ module Services
3
+ extend Helper
4
+
5
+ class << self
6
+ def succeed_to_load
7
+ stub_get(collection_endpoint, {}, response(200, services_fixture))
8
+ end
9
+
10
+ def service_fixture_hash
11
+ MultiJson.load(services_fixture["resources"].first.to_json, :symbolize_keys => true)
12
+ end
13
+
14
+ private
15
+
16
+ def collection_endpoint
17
+ %r{/v2/services\?inline-relations-depth=1}
18
+ end
19
+
20
+ def services_fixture
21
+ Helper.load_fixtures("fake_cc_service_types")
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,49 @@
1
+ module CcApiStub
2
+ module Spaces
3
+ extend Helper
4
+
5
+ class << self
6
+ def succeed_to_load(options={})
7
+ response_body = Helper.load_fixtures(options.delete(:fixture) || "fake_cc_#{object_name}", options)
8
+ stub_get(object_endpoint, {}, response(200, response_body))
9
+ end
10
+
11
+ def succeed_to_create
12
+ response_body = Helper.load_fixtures("fake_cc_created_space")
13
+ stub_post(collection_endpoint, {}, response(201, response_body))
14
+ end
15
+
16
+ def summary_fixture
17
+ Helper.load_fixtures("fake_cc_space_summary")
18
+ end
19
+
20
+ def succeed_to_load_summary(options={})
21
+ response_body = summary_fixture
22
+ response_body["services"] = [] if options.delete(:no_services)
23
+ stub_get(%r{/v2/spaces/[^/]+/summary$}, {}, response(200, response_body))
24
+ end
25
+
26
+ def space_fixture_hash
27
+ {
28
+ :metadata => {
29
+ :guid => "space-id-1",
30
+ :url => "/v2/spaces/space-id-1"
31
+ },
32
+ :entity => {
33
+ :name => "space-name-1"
34
+ }
35
+ }
36
+ end
37
+
38
+ private
39
+
40
+ def collection_endpoint
41
+ %r{/v2/spaces$}
42
+ end
43
+
44
+ def object_endpoint
45
+ %r{/v2/spaces/[^/]+$}
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,84 @@
1
+ module CcApiStub
2
+ module Users
3
+ extend Helper
4
+
5
+ class << self
6
+ def succeed_to_load(options={})
7
+ response_body = Helper.load_fixtures(options[:fixture] || "fake_cc_user")
8
+ response_body["metadata"]["guid"] = options[:id] || "user-id-1"
9
+
10
+ if options[:no_organizations]
11
+ response_body["entity"]["organizations"] = []
12
+ else
13
+ def space(space_id) {"metadata" => { "guid" => space_id }, "entity" => {}} end
14
+
15
+ organization = response_body["entity"]["organizations"].first
16
+ organization["metadata"]["guid"] = options[:organization_id] || "organization-id-1"
17
+ organization["entity"]["spaces"] = [] if options[:no_spaces]
18
+
19
+ permissions = options[:permissions] || [:organization_manager]
20
+
21
+ response_body["entity"]["managed_organizations"] << organization if permissions.include?(:organization_manager)
22
+ response_body["entity"]["billing_managed_organizations"] << organization if permissions.include?(:organization_billing_manager)
23
+ response_body["entity"]["audited_organizations"] << organization if permissions.include?(:organization_auditor)
24
+
25
+ unless options[:no_spaces]
26
+ space = space("space-id-1")
27
+ response_body["entity"]["spaces"] << space if permissions.include?(:space_developer)
28
+ response_body["entity"]["managed_spaces"] << space if permissions.include?(:space_manager)
29
+ response_body["entity"]["audited_spaces"] << space if permissions.include?(:space_auditor)
30
+
31
+ space2 = space("space-id-2")
32
+ response_body["entity"]["spaces"] << space2 if permissions.include?(:space2_developer)
33
+ response_body["entity"]["managed_spaces"] << space2 if permissions.include?(:space2_manager)
34
+ response_body["entity"]["audited_spaces"] << space2 if permissions.include?(:space2_auditor)
35
+ end
36
+ end
37
+
38
+ stub_get(%r{/v2/users/[^/]+\?inline-relations-depth=2$}, {}, response(200, response_body))
39
+ end
40
+
41
+ def fail_to_find
42
+ stub_get(object_endpoint, {}, response(404, {:code => 20003, :description => "The user could not be found"}))
43
+ end
44
+
45
+ def succeed_to_create
46
+ response_body = Helper.load_fixtures("fake_cc_created_user")
47
+ stub_post(collection_endpoint, {}, response(201, response_body))
48
+ end
49
+
50
+ def fail_to_create
51
+ CcApiStub::Helper.fail_request(:post, 500, {}, /users/)
52
+ end
53
+
54
+ def succeed_to_replace_permissions
55
+ stub_put(object_endpoint, {}, response(200, ""))
56
+ end
57
+
58
+ def fail_to_replace_permissions
59
+ stub_put(object_endpoint, {}, response(500))
60
+ end
61
+
62
+ def organizations_fixture
63
+ Helper.load_fixtures("fake_cc_user")["entity"]["organizations"]
64
+ end
65
+
66
+ def organization_fixture_hash(options={})
67
+ fixture = organizations_fixture.first
68
+ fixture["entity"].delete("spaces") if options[:no_spaces]
69
+ fixture["entity"].delete("managers") if options[:no_managers]
70
+ MultiJson.load(fixture.to_json, :symbolize_keys => true)
71
+ end
72
+
73
+ private
74
+
75
+ def collection_endpoint
76
+ %r{/v2/users$}
77
+ end
78
+
79
+ def object_endpoint
80
+ %r{/v2/users/[^/]+$}
81
+ end
82
+ end
83
+ end
84
+ end
@@ -93,6 +93,30 @@ module CFoundry
93
93
  self.token = uaa.try_to_refresh_token!
94
94
  end
95
95
 
96
+ def stream_url(url, &blk)
97
+ uri = URI.parse(url)
98
+
99
+ Net::HTTP.start(uri.host, uri.port) do |http|
100
+ http.read_timeout = 5
101
+
102
+ req = Net::HTTP::Get.new(uri.request_uri)
103
+ req["Authorization"] = token.auth_header if token
104
+
105
+ http.request(req) do |response|
106
+ case response
107
+ when Net::HTTPOK
108
+ response.read_body(&blk)
109
+ when Net::HTTPNotFound
110
+ raise CFoundry::NotFound.new(response.body, 404)
111
+ when Net::HTTPForbidden
112
+ raise CFoundry::Denied.new(response.body, 403)
113
+ else
114
+ raise CFoundry::BadResponse.new(response.body, response.code)
115
+ end
116
+ end
117
+ end
118
+ end
119
+
96
120
  private
97
121
 
98
122
  def needs_token_refresh?
@@ -126,7 +126,7 @@ module CFoundry
126
126
  class UAAError < APIError
127
127
  end
128
128
 
129
- def self.define_error(class_name, *codes)
129
+ def self.define_error(class_name, code)
130
130
  base =
131
131
  case class_name
132
132
  when /NotFound$/
@@ -135,142 +135,25 @@ module CFoundry
135
135
  APIError
136
136
  end
137
137
 
138
- klass = Class.new(base)
138
+ klass =
139
+ if const_defined?(class_name)
140
+ const_get(class_name)
141
+ else
142
+ Class.new(base)
143
+ end
139
144
 
140
- codes.each do |code|
141
- APIError.error_classes[code] = klass
142
- end
145
+ APIError.error_classes[code] = klass
143
146
 
144
- const_set(class_name, klass)
147
+ unless const_defined?(class_name)
148
+ const_set(class_name, klass)
149
+ end
145
150
  end
146
151
 
152
+ VENDOR_DIR = File.expand_path("../../../vendor", __FILE__)
147
153
 
148
- [
149
- ["InvalidAuthToken", 100],
150
-
151
- ["QuotaDeclined", 1000],
152
- ["MessageParseError", 1001],
153
- ["InvalidRelation", 1002],
154
-
155
- ["UserInvalid", 20001],
156
- ["UaaIdTaken", 20002],
157
- ["UserNotFound", 20003, 201],
158
-
159
- ["OrganizationInvalid", 30001],
160
- ["OrganizationNameTaken", 30002],
161
- ["OrganizationNotFound", 30003],
162
-
163
- ["SpaceInvalid", 40001],
164
- ["SpaceNameTaken", 40002],
165
- ["SpaceUserNotInOrg", 40003],
166
- ["SpaceNotFound", 40004],
167
-
168
- ["ServiceAuthTokenInvalid", 50001],
169
- ["ServiceAuthTokenLabelTaken", 50002],
170
- ["ServiceAuthTokenNotFound", 50003],
171
-
172
- ["ServiceInstanceNameInvalid", 60001],
173
- ["ServiceInstanceNameTaken", 60002],
174
- ["ServiceInstanceServiceBindingWrongSpace", 60003],
175
- ["ServiceInstanceInvalid", 60003],
176
- ["ServiceInstanceNotFound", 60004],
177
-
178
- ["RuntimeInvalid", 70001],
179
- ["RuntimeNameTaken", 70002],
180
- ["RuntimeNotFound", 70003],
181
-
182
- ["FrameworkInvalid", 80001],
183
- ["FrameworkNameTaken", 80002],
184
- ["FrameworkNotFound", 80003],
185
-
186
- ["ServiceBindingInvalid", 90001],
187
- ["ServiceBindingDifferentSpaces", 90002],
188
- ["ServiceBindingAppServiceTaken", 90003],
189
- ["ServiceBindingNotFound", 90004],
190
-
191
- ["AppInvalid", 100001, 300],
192
- ["AppNameTaken", 100002],
193
- ["AppNotFound", 100004, 301],
194
-
195
- ["ServicePlanInvalid", 110001],
196
- ["ServicePlanNameTaken", 110002],
197
- ["ServicePlanNotFound", 110003],
198
-
199
- ["ServiceInvalid", 120001],
200
- ["ServiceLabelTaken", 120002],
201
- ["ServiceNotFound", 120003, 500],
202
-
203
- ["DomainInvalid", 130001],
204
- ["DomainNotFound", 130002],
205
- ["DomainNameTaken", 130003],
206
-
207
- ["LegacyApiWithoutDefaultSpace", 140001],
208
-
209
- ["AppPackageInvalid", 150001],
210
- ["AppPackageNotFound", 150002],
211
-
212
- ["AppBitsUploadInvalid", 160001],
213
-
214
- ["StagingError", 170001],
215
-
216
- ["SnapshotNotFound", 180001],
217
- ["ServiceGatewayError", 180002, 503],
218
- ["ServiceNotImplemented", 180003],
219
- ["SDSNotAvailable", 180004],
220
-
221
- ["FileError", 190001],
222
-
223
- ["StatsError", 200001],
224
-
225
- ["RouteInvalid", 210001],
226
- ["RouteNotFound", 210002],
227
- ["RouteHostTaken", 210003],
228
-
229
- ["InstancesError", 220001],
230
-
231
- ["BillingEventQueryInvalid", 230001],
232
-
233
- # V1 Errors
234
- ["BadRequest", 100],
235
- ["DatabaseError", 101],
236
- ["LockingError", 102],
237
- ["SystemError", 111],
238
-
239
- ["Forbidden", 200],
240
- ["HttpsRequired", 202],
241
-
242
- ["AppNoResources", 302],
243
- ["AppFileNotFound", 303],
244
- ["AppInstanceNotFound", 304],
245
- ["AppStopped", 305],
246
- ["AppFileError", 306],
247
- ["AppInvalidRuntime", 307],
248
- ["AppInvalidFramework", 308],
249
- ["AppDebugDisallowed", 309],
250
- ["AppStagingError", 310],
251
-
252
- ["ResourcesUnknownPackageType", 400],
253
- ["ResourcesMissingResource", 401],
254
- ["ResourcesPackagingFailed", 402],
255
-
256
- ["BindingNotFound", 501],
257
- ["TokenNotFound", 502],
258
- ["AccountTooManyServices", 504],
259
- ["ExtensionNotImpl", 505],
260
- ["UnsupportedVersion", 506],
261
- ["SdsError", 507],
262
- ["SdsNotFound", 508],
263
-
264
- ["AccountNotEnoughMemory", 600],
265
- ["AccountAppsTooMany", 601],
266
- ["AccountAppTooManyUris", 602],
267
-
268
- ["UriInvalid", 700],
269
- ["UriAlreadyTaken", 701],
270
- ["UriNotAllowed", 702],
271
- ["StagingTimedOut", 800],
272
- ["StagingFailed", 801]
273
- ].each do |args|
274
- define_error(*args)
154
+ %w{errors/v1.yml errors/v2.yml}.each do |errors|
155
+ YAML.load_file("#{VENDOR_DIR}/#{errors}").each do |code, meta|
156
+ define_error(meta["name"], code)
157
+ end
275
158
  end
276
159
  end
@@ -116,17 +116,21 @@ module CFoundry::V1
116
116
  end
117
117
 
118
118
  # Start the application.
119
- def start!
119
+ def start!(async = false)
120
120
  self.state = "STARTED"
121
121
  update!
122
122
  end
123
123
 
124
124
  # Restart the application.
125
- def restart!
125
+ def restart!(async = false)
126
126
  stop!
127
127
  start!
128
128
  end
129
129
 
130
+ def update!(async = false)
131
+ super()
132
+ end
133
+
130
134
  # Determine application health.
131
135
  #
132
136
  # If all instances are running, returns "RUNNING". If only some are
@@ -189,15 +189,27 @@ module CFoundry::V2
189
189
  end
190
190
 
191
191
  # Start the application.
192
- def start!
192
+ def start!(async = false, &blk)
193
193
  self.state = "STARTED"
194
- update!
194
+ update!(async, &blk)
195
195
  end
196
196
 
197
197
  # Restart the application.
198
- def restart!
198
+ def restart!(async = false, &blk)
199
199
  stop!
200
- start!
200
+ start!(async, &blk)
201
+ end
202
+
203
+ def update!(async = false)
204
+ response = @client.base.update_app(@guid, @diff, async)
205
+
206
+ yield response[:headers]["x-app-staging-log"] if block_given?
207
+
208
+ @manifest = @client.base.send(:parse_json, response[:body])
209
+
210
+ @diff.clear
211
+
212
+ true
201
213
  end
202
214
 
203
215
  # Determine application health.
@@ -38,21 +38,12 @@ module CFoundry::V2
38
38
  end
39
39
  alias :file :files
40
40
 
41
- def stream_file(guid, instance, *path)
41
+ def stream_file(guid, instance, *path, &blk)
42
42
  path_and_options = path + [{:return_response => true, :follow_redirects => false}]
43
43
  redirect = get("v2", "apps", guid, "instances", instance, "files", *path_and_options)
44
44
 
45
45
  if location = redirect[:headers]["location"]
46
- uri = URI.parse(location + "&tail")
47
-
48
- Net::HTTP.start(uri.host, uri.port) do |http|
49
- req = Net::HTTP::Get.new(uri.request_uri)
50
- req["Authorization"] = token.auth_header if token
51
-
52
- http.request(req) do |response|
53
- response.read_body { |chunk| yield chunk }
54
- end
55
- end
46
+ stream_url(location + "&tail", &blk)
56
47
  else
57
48
  yield redirect[:body]
58
49
  end
@@ -70,6 +61,14 @@ module CFoundry::V2
70
61
  get("v2", "apps", guid, "stats", :accept => :json)
71
62
  end
72
63
 
64
+ def update_app(guid, diff, async = false)
65
+ put("v2", "apps", guid,
66
+ :content => :json,
67
+ :payload => diff,
68
+ :return_response => true,
69
+ :params => { :stage_async => !!async })
70
+ end
71
+
73
72
  def all_pages(paginated)
74
73
  payload = paginated[:resources]
75
74