cfoundry 0.5.1.rc2 → 0.5.1.rc3

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