jfoundry 0.1.0.pre
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.
- data/LICENSE +746 -0
- data/Rakefile +10 -0
- data/lib/cc_api_stub/applications.rb +53 -0
- data/lib/cc_api_stub/domains.rb +32 -0
- data/lib/cc_api_stub/frameworks.rb +22 -0
- data/lib/cc_api_stub/helper.rb +139 -0
- data/lib/cc_api_stub/login.rb +21 -0
- data/lib/cc_api_stub/organization_users.rb +21 -0
- data/lib/cc_api_stub/organizations.rb +70 -0
- data/lib/cc_api_stub/routes.rb +26 -0
- data/lib/cc_api_stub/runtimes.rb +22 -0
- data/lib/cc_api_stub/service_bindings.rb +22 -0
- data/lib/cc_api_stub/service_instances.rb +22 -0
- data/lib/cc_api_stub/services.rb +21 -0
- data/lib/cc_api_stub/spaces.rb +49 -0
- data/lib/cc_api_stub/users.rb +85 -0
- data/lib/cc_api_stub.rb +16 -0
- data/lib/jfoundry/auth_token.rb +63 -0
- data/lib/jfoundry/baseclient.rb +177 -0
- data/lib/jfoundry/chatty_hash.rb +46 -0
- data/lib/jfoundry/client.rb +39 -0
- data/lib/jfoundry/concerns/proxy_options.rb +17 -0
- data/lib/jfoundry/errors.rb +163 -0
- data/lib/jfoundry/rest_client.rb +331 -0
- data/lib/jfoundry/signature/version.rb +27 -0
- data/lib/jfoundry/signer.rb +13 -0
- data/lib/jfoundry/test_support.rb +3 -0
- data/lib/jfoundry/timer.rb +13 -0
- data/lib/jfoundry/trace_helpers.rb +64 -0
- data/lib/jfoundry/upload_helpers.rb +222 -0
- data/lib/jfoundry/v2/app.rb +357 -0
- data/lib/jfoundry/v2/app_event.rb +13 -0
- data/lib/jfoundry/v2/base.rb +92 -0
- data/lib/jfoundry/v2/client.rb +78 -0
- data/lib/jfoundry/v2/domain.rb +20 -0
- data/lib/jfoundry/v2/managed_service_instance.rb +13 -0
- data/lib/jfoundry/v2/model.rb +209 -0
- data/lib/jfoundry/v2/model_magic/attribute.rb +49 -0
- data/lib/jfoundry/v2/model_magic/client_extensions.rb +170 -0
- data/lib/jfoundry/v2/model_magic/has_summary.rb +49 -0
- data/lib/jfoundry/v2/model_magic/queryable_by.rb +39 -0
- data/lib/jfoundry/v2/model_magic/to_many.rb +138 -0
- data/lib/jfoundry/v2/model_magic/to_one.rb +81 -0
- data/lib/jfoundry/v2/model_magic.rb +93 -0
- data/lib/jfoundry/v2/organization.rb +22 -0
- data/lib/jfoundry/v2/quota_definition.rb +12 -0
- data/lib/jfoundry/v2/route.rb +25 -0
- data/lib/jfoundry/v2/service.rb +20 -0
- data/lib/jfoundry/v2/service_auth_token.rb +10 -0
- data/lib/jfoundry/v2/service_binding.rb +10 -0
- data/lib/jfoundry/v2/service_broker.rb +11 -0
- data/lib/jfoundry/v2/service_instance.rb +13 -0
- data/lib/jfoundry/v2/service_plan.rb +13 -0
- data/lib/jfoundry/v2/space.rb +18 -0
- data/lib/jfoundry/v2/stack.rb +10 -0
- data/lib/jfoundry/v2/user.rb +104 -0
- data/lib/jfoundry/v2/user_provided_service_instance.rb +7 -0
- data/lib/jfoundry/validator.rb +41 -0
- data/lib/jfoundry/version.rb +4 -0
- data/lib/jfoundry/zip.rb +56 -0
- data/lib/jfoundry.rb +5 -0
- data/lib/tasks/gem_release.rake +42 -0
- data/vendor/errors/README.md +3 -0
- data/vendor/errors/v1.yml +189 -0
- data/vendor/errors/v2.yml +470 -0
- metadata +269 -0
@@ -0,0 +1,357 @@
|
|
1
|
+
require "tmpdir"
|
2
|
+
require "multi_json"
|
3
|
+
|
4
|
+
require "jfoundry/zip"
|
5
|
+
require "jfoundry/upload_helpers"
|
6
|
+
require "jfoundry/chatty_hash"
|
7
|
+
|
8
|
+
require "jfoundry/v2/model"
|
9
|
+
|
10
|
+
module JFoundry::V2
|
11
|
+
# Class for representing a user's application on a given target (via
|
12
|
+
# Client).
|
13
|
+
#
|
14
|
+
# Does not guarantee that the app exists; used for both app creation and
|
15
|
+
# retrieval, as the attributes are all lazily retrieved. Setting attributes
|
16
|
+
# does not perform any requests; use #update! to commit your changes.
|
17
|
+
class App < Model
|
18
|
+
include JFoundry::UploadHelpers
|
19
|
+
|
20
|
+
attribute :name, :string
|
21
|
+
to_one :space
|
22
|
+
attribute :environment_json, :hash, :default => {}
|
23
|
+
attribute :memory, :integer, :default => 256
|
24
|
+
attribute :total_instances, :integer, :default => 1, :at => :instances
|
25
|
+
attribute :disk_quota, :integer, :default => 256
|
26
|
+
attribute :state, :string, :default => "STOPPED"
|
27
|
+
attribute :command, :string, :default => nil
|
28
|
+
attribute :console, :boolean, :default => false
|
29
|
+
attribute :buildpack, :string, :default => nil
|
30
|
+
to_one :stack, :default => nil
|
31
|
+
attribute :debug, :string, :default => nil
|
32
|
+
to_many :service_bindings
|
33
|
+
to_many :routes
|
34
|
+
to_many :events, :as => :app_event
|
35
|
+
|
36
|
+
scoped_to_space
|
37
|
+
|
38
|
+
queryable_by :name, :space_guid, :organization_guid
|
39
|
+
|
40
|
+
has_summary :urls => proc { |x| self.cache[:uris] = x },
|
41
|
+
:running_instances => proc { |x|
|
42
|
+
self.cache[:running_instances] = x
|
43
|
+
},
|
44
|
+
:instances => proc { |x|
|
45
|
+
self.total_instances = x
|
46
|
+
}
|
47
|
+
|
48
|
+
private :environment_json
|
49
|
+
|
50
|
+
def delete!(opts = {})
|
51
|
+
super(opts.merge(:recursive => true))
|
52
|
+
end
|
53
|
+
|
54
|
+
def instances
|
55
|
+
@client.base.instances(@guid).collect do |i, m|
|
56
|
+
Instance.new(self, i.to_s, @client, m)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def crashes
|
61
|
+
@client.base.crashes(@guid).collect do |m|
|
62
|
+
Instance.new(self, m[:instance], @client, m)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def stats
|
67
|
+
stats = {}
|
68
|
+
|
69
|
+
@client.base.stats(@guid).each do |idx, info|
|
70
|
+
stats[idx.to_s] = info
|
71
|
+
end
|
72
|
+
|
73
|
+
stats
|
74
|
+
end
|
75
|
+
|
76
|
+
def services
|
77
|
+
service_bindings.collect(&:service_instance)
|
78
|
+
end
|
79
|
+
|
80
|
+
def env
|
81
|
+
JFoundry::ChattyHash.new(
|
82
|
+
method(:env=),
|
83
|
+
stringify(environment_json))
|
84
|
+
end
|
85
|
+
|
86
|
+
def env=(x)
|
87
|
+
self.environment_json = stringify(x.to_hash)
|
88
|
+
end
|
89
|
+
|
90
|
+
alias :debug_mode :debug
|
91
|
+
|
92
|
+
def uris
|
93
|
+
return @cache[:uris] if @cache[:uris]
|
94
|
+
|
95
|
+
routes.collect do |r|
|
96
|
+
"#{r.host}.#{r.domain.name}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
alias :urls :uris
|
100
|
+
|
101
|
+
def uris=(uris)
|
102
|
+
raise JFoundry::Deprecated,
|
103
|
+
"App#uris= is invalid against V2 APIs; use add/remove_route"
|
104
|
+
end
|
105
|
+
alias :urls= :uris=
|
106
|
+
|
107
|
+
def uri
|
108
|
+
if uris = @cache[:uris]
|
109
|
+
return uris.first
|
110
|
+
end
|
111
|
+
|
112
|
+
if route = routes.first
|
113
|
+
"#{route.host}.#{route.domain.name}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
alias :url :uri
|
117
|
+
|
118
|
+
def host
|
119
|
+
return nil if routes.empty?
|
120
|
+
routes.first.host
|
121
|
+
end
|
122
|
+
|
123
|
+
def domain
|
124
|
+
return nil if routes.empty?
|
125
|
+
routes.first.domain.name
|
126
|
+
end
|
127
|
+
|
128
|
+
def uri=(x)
|
129
|
+
self.uris = [x]
|
130
|
+
end
|
131
|
+
alias :url= :uri=
|
132
|
+
|
133
|
+
# Stop the application.
|
134
|
+
def stop!
|
135
|
+
self.state = "STOPPED"
|
136
|
+
update!
|
137
|
+
end
|
138
|
+
|
139
|
+
# Start the application.
|
140
|
+
def start!(&blk)
|
141
|
+
self.state = "STARTED"
|
142
|
+
update!(&blk)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Restart the application.
|
146
|
+
def restart!(&blk)
|
147
|
+
stop!
|
148
|
+
start!(&blk)
|
149
|
+
end
|
150
|
+
|
151
|
+
def update!
|
152
|
+
response = @client.base.update_app(@guid, @diff)
|
153
|
+
|
154
|
+
yield response[:headers]["x-app-staging-log"] if block_given?
|
155
|
+
|
156
|
+
@manifest = @client.base.send(:parse_json, response[:body])
|
157
|
+
|
158
|
+
@diff.clear
|
159
|
+
|
160
|
+
true
|
161
|
+
end
|
162
|
+
|
163
|
+
def stream_update_log(log_url)
|
164
|
+
offset = 0
|
165
|
+
|
166
|
+
while true
|
167
|
+
begin
|
168
|
+
@client.stream_url(log_url + "&tail&tail_offset=#{offset}") do |out|
|
169
|
+
offset += out.size
|
170
|
+
yield out
|
171
|
+
end
|
172
|
+
rescue Timeout::Error
|
173
|
+
end
|
174
|
+
end
|
175
|
+
rescue JFoundry::APIError
|
176
|
+
end
|
177
|
+
|
178
|
+
# Determine application health.
|
179
|
+
#
|
180
|
+
# If all instances are running, returns "RUNNING". If only some are
|
181
|
+
# started, returns the percentage of them that are healthy.
|
182
|
+
#
|
183
|
+
# Otherwise, returns application's status.
|
184
|
+
def health
|
185
|
+
if state == "STARTED"
|
186
|
+
healthy_count = running_instances
|
187
|
+
expected = total_instances
|
188
|
+
|
189
|
+
if expected > 0
|
190
|
+
ratio = healthy_count / expected.to_f
|
191
|
+
if ratio == 1.0
|
192
|
+
"RUNNING"
|
193
|
+
else
|
194
|
+
"#{(ratio * 100).to_i}%"
|
195
|
+
end
|
196
|
+
else
|
197
|
+
"N/A"
|
198
|
+
end
|
199
|
+
else
|
200
|
+
state
|
201
|
+
end
|
202
|
+
rescue JFoundry::StagingError, JFoundry::NotStaged
|
203
|
+
"STAGING FAILED"
|
204
|
+
end
|
205
|
+
|
206
|
+
def running_instances
|
207
|
+
return @cache[:running_instances] if @cache[:running_instances]
|
208
|
+
|
209
|
+
running = 0
|
210
|
+
|
211
|
+
instances.each do |i|
|
212
|
+
running += 1 if i.state == "RUNNING"
|
213
|
+
end
|
214
|
+
|
215
|
+
running
|
216
|
+
end
|
217
|
+
|
218
|
+
# Check that all application instances are running.
|
219
|
+
def healthy?
|
220
|
+
# invalidate cache so the check is fresh
|
221
|
+
invalidate!
|
222
|
+
health == "RUNNING"
|
223
|
+
end
|
224
|
+
alias_method :running?, :healthy?
|
225
|
+
|
226
|
+
# Is the application stopped?
|
227
|
+
def stopped?
|
228
|
+
state == "STOPPED"
|
229
|
+
end
|
230
|
+
|
231
|
+
# Is the application started?
|
232
|
+
#
|
233
|
+
# Note that this does not imply that all instances are running. See
|
234
|
+
# #healthy?
|
235
|
+
def started?
|
236
|
+
state == "STARTED"
|
237
|
+
end
|
238
|
+
|
239
|
+
# Bind services to application.
|
240
|
+
def bind(*instances)
|
241
|
+
instances.each do |i|
|
242
|
+
binding = @client.service_binding
|
243
|
+
binding.app = self
|
244
|
+
binding.service_instance = i
|
245
|
+
binding.create!
|
246
|
+
end
|
247
|
+
|
248
|
+
self
|
249
|
+
end
|
250
|
+
|
251
|
+
# Unbind services from application.
|
252
|
+
def unbind(*instances)
|
253
|
+
service_bindings.each do |b|
|
254
|
+
if instances.include? b.service_instance
|
255
|
+
b.delete!
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
self
|
260
|
+
end
|
261
|
+
|
262
|
+
def binds?(instance)
|
263
|
+
service_bindings.any? { |b|
|
264
|
+
b.service_instance == instance
|
265
|
+
}
|
266
|
+
end
|
267
|
+
|
268
|
+
def files(*path)
|
269
|
+
Instance.new(self, "0", @client).files(*path)
|
270
|
+
end
|
271
|
+
|
272
|
+
def file(*path)
|
273
|
+
Instance.new(self, "0", @client).file(*path)
|
274
|
+
end
|
275
|
+
|
276
|
+
def stream_file(*path, &blk)
|
277
|
+
Instance.new(self, "0", @client).stream_file(*path, &blk)
|
278
|
+
end
|
279
|
+
|
280
|
+
private
|
281
|
+
|
282
|
+
def stringify(hash)
|
283
|
+
new = {}
|
284
|
+
|
285
|
+
hash.each do |k, v|
|
286
|
+
new[k.to_s] = v.to_s
|
287
|
+
end
|
288
|
+
|
289
|
+
new
|
290
|
+
end
|
291
|
+
|
292
|
+
class Instance
|
293
|
+
attr_reader :app, :id
|
294
|
+
|
295
|
+
def initialize(app, id, client, manifest = {})
|
296
|
+
@app = app
|
297
|
+
@id = id
|
298
|
+
@client = client
|
299
|
+
@manifest = manifest
|
300
|
+
end
|
301
|
+
|
302
|
+
def inspect
|
303
|
+
"#<App::Instance '#{@app.name}' \##@id>"
|
304
|
+
end
|
305
|
+
|
306
|
+
def state
|
307
|
+
@manifest[:state]
|
308
|
+
end
|
309
|
+
alias_method :status, :state
|
310
|
+
|
311
|
+
def since
|
312
|
+
if since = @manifest[:since]
|
313
|
+
Time.at(@manifest[:since])
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def debugger
|
318
|
+
return unless @manifest[:debug_ip] and @manifest[:debug_port]
|
319
|
+
|
320
|
+
{ :ip => @manifest[:debug_ip],
|
321
|
+
:port => @manifest[:debug_port]
|
322
|
+
}
|
323
|
+
end
|
324
|
+
|
325
|
+
def console
|
326
|
+
return unless @manifest[:console_ip] and @manifest[:console_port]
|
327
|
+
|
328
|
+
{ :ip => @manifest[:console_ip],
|
329
|
+
:port => @manifest[:console_port]
|
330
|
+
}
|
331
|
+
end
|
332
|
+
|
333
|
+
def healthy?
|
334
|
+
case state
|
335
|
+
when "STARTING", "RUNNING"
|
336
|
+
true
|
337
|
+
when "DOWN", "FLAPPING"
|
338
|
+
false
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
def files(*path)
|
343
|
+
@client.base.files(@app.guid, @id, *path).split("\n").collect do |entry|
|
344
|
+
path + [entry.split(/\s+/, 2)[0]]
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
def file(*path)
|
349
|
+
@client.base.files(@app.guid, @id, *path)
|
350
|
+
end
|
351
|
+
|
352
|
+
def stream_file(*path, &blk)
|
353
|
+
@client.base.stream_file(@app.guid, @id, *path, &blk)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "jfoundry/v2/model"
|
2
|
+
|
3
|
+
module JFoundry::V2
|
4
|
+
class AppEvent < Model
|
5
|
+
to_one :app
|
6
|
+
|
7
|
+
attribute :instance_guid, :string
|
8
|
+
attribute :instance_index, :integer
|
9
|
+
attribute :exit_status, :integer
|
10
|
+
attribute :exit_description, :string, :default => ""
|
11
|
+
attribute :timestamp, :string
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require "multi_json"
|
2
|
+
|
3
|
+
require "jfoundry/baseclient"
|
4
|
+
|
5
|
+
require "jfoundry/errors"
|
6
|
+
|
7
|
+
module JFoundry::V2
|
8
|
+
class Base < JFoundry::BaseClient
|
9
|
+
include BaseClientMethods
|
10
|
+
|
11
|
+
def resource_match(fingerprints)
|
12
|
+
put("v2", "resource_match", :content => :json, :accept => :json, :payload => fingerprints)
|
13
|
+
end
|
14
|
+
|
15
|
+
def upload_app(guid, zipfile = nil, resources = [])
|
16
|
+
payload = {}
|
17
|
+
payload[:resources] = MultiJson.dump(resources)
|
18
|
+
|
19
|
+
if zipfile
|
20
|
+
payload[:application] =
|
21
|
+
UploadIO.new(
|
22
|
+
if zipfile.is_a? File
|
23
|
+
zipfile
|
24
|
+
elsif zipfile.is_a? String
|
25
|
+
File.new(zipfile, "rb")
|
26
|
+
end,
|
27
|
+
"application/zip")
|
28
|
+
end
|
29
|
+
|
30
|
+
put("v2", "apps", guid, "bits", :payload => payload)
|
31
|
+
rescue EOFError
|
32
|
+
retry
|
33
|
+
end
|
34
|
+
|
35
|
+
def files(guid, instance, *path)
|
36
|
+
get("v2", "apps", guid, "instances", instance, "files", *path)
|
37
|
+
end
|
38
|
+
|
39
|
+
alias :file :files
|
40
|
+
|
41
|
+
def stream_file(guid, instance, *path, &blk)
|
42
|
+
path_and_options = path + [{:return_response => true, :follow_redirects => false}]
|
43
|
+
redirect = get("v2", "apps", guid, "instances", instance, "files", *path_and_options)
|
44
|
+
|
45
|
+
if location = redirect[:headers]["location"]
|
46
|
+
stream_url(location + "&tail", &blk)
|
47
|
+
else
|
48
|
+
yield redirect[:body]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def instances(guid)
|
53
|
+
get("v2", "apps", guid, "instances", :accept => :json)
|
54
|
+
end
|
55
|
+
|
56
|
+
def crashes(guid)
|
57
|
+
get("v2", "apps", guid, "crashes", :accept => :json)
|
58
|
+
end
|
59
|
+
|
60
|
+
def stats(guid)
|
61
|
+
get("v2", "apps", guid, "stats", :accept => :json)
|
62
|
+
end
|
63
|
+
|
64
|
+
def update_app(guid, diff)
|
65
|
+
put("v2", "apps", guid,
|
66
|
+
:content => :json,
|
67
|
+
:payload => diff,
|
68
|
+
:return_response => true)
|
69
|
+
end
|
70
|
+
|
71
|
+
def user_info
|
72
|
+
get("v2", "user_info", :accept => :json)
|
73
|
+
end
|
74
|
+
|
75
|
+
def for_each(paginated, &block)
|
76
|
+
paginated[:resources].each &block
|
77
|
+
|
78
|
+
while next_page = paginated[:next_url]
|
79
|
+
paginated = get(next_page, :accept => :json)
|
80
|
+
paginated[:resources].each &block
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def all_pages(paginated)
|
85
|
+
payload = []
|
86
|
+
for_each(paginated) do |resource|
|
87
|
+
payload << resource
|
88
|
+
end
|
89
|
+
payload
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
module JFoundry::V2
|
4
|
+
# The primary API entrypoint. Wraps a BaseClient to provide nicer return
|
5
|
+
# values. Initialize with the target and, optionally, an auth token. These
|
6
|
+
# are the only two internal states.
|
7
|
+
class Client
|
8
|
+
include ClientMethods
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
# Internal BaseClient instance. Normally won't be touching this.
|
12
|
+
attr_reader :base
|
13
|
+
|
14
|
+
# [Organization] Currently targeted organization.
|
15
|
+
attr_accessor :current_organization
|
16
|
+
|
17
|
+
# [Space] Currently targeted space.
|
18
|
+
attr_accessor :current_space
|
19
|
+
|
20
|
+
def_delegators :@base, :target, :target=, :access_key, :access_key=, :secret_key,
|
21
|
+
:secret_key=, :version, :version=, :http_proxy, :http_proxy=, :https_proxy,
|
22
|
+
:https_proxy=, :trace, :trace=, :log, :log=, :info
|
23
|
+
|
24
|
+
# Create a new Client for interfacing with the given target.
|
25
|
+
#
|
26
|
+
# A token may also be provided to skip the login step.
|
27
|
+
def initialize(target, access_key, secret_key, version)
|
28
|
+
@base = Base.new(target, access_key, secret_key, version)
|
29
|
+
end
|
30
|
+
|
31
|
+
def version
|
32
|
+
2
|
33
|
+
end
|
34
|
+
|
35
|
+
# The currently authenticated user.
|
36
|
+
def current_user
|
37
|
+
user = user(@base.access_key)
|
38
|
+
user_info = @base.user_info
|
39
|
+
if user_info && user_info.key?(:user)
|
40
|
+
user.emails = [{ :value => user_info[:user]}]
|
41
|
+
end
|
42
|
+
user
|
43
|
+
end
|
44
|
+
|
45
|
+
def query_target(klass)
|
46
|
+
if klass.scoped_space && space = current_space
|
47
|
+
space
|
48
|
+
elsif klass.scoped_organization && org = current_organization
|
49
|
+
org
|
50
|
+
else
|
51
|
+
self
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def stream_url(url, &blk)
|
56
|
+
@base.stream_url(url, &blk)
|
57
|
+
end
|
58
|
+
|
59
|
+
def service_instances(opts={})
|
60
|
+
opts[:user_provided] = true
|
61
|
+
super(opts)
|
62
|
+
end
|
63
|
+
|
64
|
+
def service_instances_from(path, *args)
|
65
|
+
opts = args.first || {}
|
66
|
+
opts[:user_provided] = true
|
67
|
+
super(path, opts, *args)
|
68
|
+
end
|
69
|
+
|
70
|
+
def make_service_instance(json)
|
71
|
+
klass = "JFoundry::V2::#{json[:entity][:type].camelize}".constantize
|
72
|
+
klass.new(
|
73
|
+
json[:metadata][:guid],
|
74
|
+
self,
|
75
|
+
json)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "jfoundry/v2/model"
|
2
|
+
|
3
|
+
module JFoundry::V2
|
4
|
+
class Domain < Model
|
5
|
+
validates_presence_of :name
|
6
|
+
validates_format_of :name, :with => /\A([^\.]+\.)+[^\.]+\Z/
|
7
|
+
validates_presence_of :owning_organization
|
8
|
+
|
9
|
+
attribute :name, :string
|
10
|
+
attribute :wildcard, :boolean
|
11
|
+
to_one :owning_organization, :as => :organization, :default => nil
|
12
|
+
to_many :spaces
|
13
|
+
|
14
|
+
queryable_by :name, :owning_organization_guid, :space_guid
|
15
|
+
|
16
|
+
def system?
|
17
|
+
guid.present? && !owning_organization.present?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "jfoundry/v2/service_instance"
|
2
|
+
|
3
|
+
module JFoundry::V2
|
4
|
+
class ManagedServiceInstance < ServiceInstance
|
5
|
+
attribute :dashboard_url, :string
|
6
|
+
attribute :credentials, :hash
|
7
|
+
to_one :service_plan
|
8
|
+
|
9
|
+
def self.object_name
|
10
|
+
'service_instance'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|