cfoundry-IronFoundry 0.3.34
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 +40 -0
- data/lib/cfoundry.rb +2 -0
- data/lib/cfoundry/baseclient.rb +235 -0
- data/lib/cfoundry/chatty_hash.rb +34 -0
- data/lib/cfoundry/client.rb +25 -0
- data/lib/cfoundry/errors.rb +106 -0
- data/lib/cfoundry/uaaclient.rb +111 -0
- data/lib/cfoundry/upload_helpers.rb +100 -0
- data/lib/cfoundry/v1/app.rb +562 -0
- data/lib/cfoundry/v1/base.rb +209 -0
- data/lib/cfoundry/v1/client.rb +232 -0
- data/lib/cfoundry/v1/framework.rb +21 -0
- data/lib/cfoundry/v1/runtime.rb +20 -0
- data/lib/cfoundry/v1/service.rb +25 -0
- data/lib/cfoundry/v1/service_instance.rb +112 -0
- data/lib/cfoundry/v1/user.rb +89 -0
- data/lib/cfoundry/v2/app.rb +328 -0
- data/lib/cfoundry/v2/base.rb +175 -0
- data/lib/cfoundry/v2/client.rb +198 -0
- data/lib/cfoundry/v2/domain.rb +8 -0
- data/lib/cfoundry/v2/framework.rb +12 -0
- data/lib/cfoundry/v2/model.rb +268 -0
- data/lib/cfoundry/v2/organization.rb +13 -0
- data/lib/cfoundry/v2/route.rb +9 -0
- data/lib/cfoundry/v2/runtime.rb +9 -0
- data/lib/cfoundry/v2/service.rb +17 -0
- data/lib/cfoundry/v2/service_auth_token.rb +9 -0
- data/lib/cfoundry/v2/service_binding.rb +8 -0
- data/lib/cfoundry/v2/service_instance.rb +10 -0
- data/lib/cfoundry/v2/service_plan.rb +10 -0
- data/lib/cfoundry/v2/space.rb +14 -0
- data/lib/cfoundry/v2/user.rb +58 -0
- data/lib/cfoundry/version.rb +4 -0
- data/lib/cfoundry/zip.rb +56 -0
- data/spec/Rakefile +14 -0
- data/spec/client_spec.rb +206 -0
- data/spec/helpers.rb +29 -0
- metadata +169 -0
@@ -0,0 +1,209 @@
|
|
1
|
+
require "multi_json"
|
2
|
+
|
3
|
+
require "cfoundry/baseclient"
|
4
|
+
require "cfoundry/uaaclient"
|
5
|
+
|
6
|
+
require "cfoundry/errors"
|
7
|
+
|
8
|
+
module CFoundry::V1
|
9
|
+
class Base < CFoundry::BaseClient
|
10
|
+
attr_accessor :target, :token, :proxy, :trace
|
11
|
+
|
12
|
+
def initialize(
|
13
|
+
target = "https://api.cloudfoundry.com",
|
14
|
+
token = nil)
|
15
|
+
@target = target
|
16
|
+
@token = token
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
# invalidate token data when changing token
|
21
|
+
def token=(t)
|
22
|
+
@token = t
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# The UAA used for this client.
|
27
|
+
#
|
28
|
+
# `false` if no UAA (legacy)
|
29
|
+
def uaa
|
30
|
+
return @uaa unless @uaa.nil?
|
31
|
+
|
32
|
+
endpoint = info[:authorization_endpoint]
|
33
|
+
return @uaa = false unless endpoint
|
34
|
+
|
35
|
+
@uaa = CFoundry::UAAClient.new(endpoint)
|
36
|
+
@uaa.trace = @trace
|
37
|
+
@uaa.token = @token
|
38
|
+
@uaa
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# Cloud metadata
|
43
|
+
def info
|
44
|
+
get("info", nil => :json)
|
45
|
+
end
|
46
|
+
|
47
|
+
def system_services
|
48
|
+
get("info", "services", nil => :json)
|
49
|
+
end
|
50
|
+
|
51
|
+
def system_runtimes
|
52
|
+
get("info", "runtimes", nil => :json)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Users
|
56
|
+
def users
|
57
|
+
get("users", nil => :json)
|
58
|
+
end
|
59
|
+
|
60
|
+
def create_user(payload)
|
61
|
+
post(payload, "users", :json => nil)
|
62
|
+
end
|
63
|
+
|
64
|
+
def user(email)
|
65
|
+
get("users", email, nil => :json)
|
66
|
+
end
|
67
|
+
|
68
|
+
def delete_user(email)
|
69
|
+
delete("users", email, nil => :json)
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
73
|
+
def update_user(email, payload)
|
74
|
+
put(payload, "users", email, :json => nil)
|
75
|
+
end
|
76
|
+
|
77
|
+
def create_token(payload, email)
|
78
|
+
post(payload, "users", email, "tokens", :json => :json)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Applications
|
82
|
+
def apps
|
83
|
+
get("apps", nil => :json)
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_app(payload)
|
87
|
+
post(payload, "apps", :json => :json)
|
88
|
+
end
|
89
|
+
|
90
|
+
def app(name)
|
91
|
+
get("apps", name, nil => :json)
|
92
|
+
end
|
93
|
+
|
94
|
+
def instances(name)
|
95
|
+
get("apps", name, "instances", nil => :json)[:instances]
|
96
|
+
end
|
97
|
+
|
98
|
+
def crashes(name)
|
99
|
+
get("apps", name, "crashes", nil => :json)[:crashes]
|
100
|
+
end
|
101
|
+
|
102
|
+
def files(name, instance, *path)
|
103
|
+
get("apps", name, "instances", instance, "files", *path)
|
104
|
+
end
|
105
|
+
alias :file :files
|
106
|
+
|
107
|
+
def update_app(name, payload)
|
108
|
+
put(payload, "apps", name, :json => nil)
|
109
|
+
end
|
110
|
+
|
111
|
+
def delete_app(name)
|
112
|
+
delete("apps", name)
|
113
|
+
true
|
114
|
+
end
|
115
|
+
|
116
|
+
def stats(name)
|
117
|
+
get("apps", name, "stats", nil => :json)
|
118
|
+
end
|
119
|
+
|
120
|
+
def check_resources(fingerprints)
|
121
|
+
post(fingerprints, "resources", :json => :json)
|
122
|
+
end
|
123
|
+
|
124
|
+
def upload_app(name, zipfile, resources = [])
|
125
|
+
payload = {
|
126
|
+
:_method => "put",
|
127
|
+
:resources => MultiJson.dump(resources),
|
128
|
+
:multipart => true,
|
129
|
+
:application =>
|
130
|
+
if zipfile.is_a? File
|
131
|
+
zipfile
|
132
|
+
elsif zipfile.is_a? String
|
133
|
+
File.new(zipfile, "rb")
|
134
|
+
end
|
135
|
+
}
|
136
|
+
|
137
|
+
post(payload, "apps", name, "application")
|
138
|
+
rescue RestClient::ServerBrokeConnection
|
139
|
+
retry
|
140
|
+
end
|
141
|
+
|
142
|
+
# Services
|
143
|
+
def services
|
144
|
+
get("services", nil => :json)
|
145
|
+
end
|
146
|
+
|
147
|
+
def create_service(manifest)
|
148
|
+
post(manifest, "services", :json => :json)
|
149
|
+
end
|
150
|
+
|
151
|
+
def service(name)
|
152
|
+
get("services", name, nil => :json)
|
153
|
+
end
|
154
|
+
|
155
|
+
def delete_service(name)
|
156
|
+
delete("services", name, nil => :json)
|
157
|
+
true
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def handle_response(response, accept)
|
163
|
+
json = accept == :json
|
164
|
+
|
165
|
+
case response.code
|
166
|
+
when 200, 204, 302
|
167
|
+
if accept == :headers
|
168
|
+
return response.headers
|
169
|
+
end
|
170
|
+
|
171
|
+
if json
|
172
|
+
if response.code == 204
|
173
|
+
raise "Expected JSON response, got 204 No Content"
|
174
|
+
end
|
175
|
+
|
176
|
+
parse_json(response)
|
177
|
+
else
|
178
|
+
response
|
179
|
+
end
|
180
|
+
|
181
|
+
when 400, 403
|
182
|
+
info = parse_json(response)
|
183
|
+
raise CFoundry::Denied.new(403, info[:description])
|
184
|
+
|
185
|
+
when 404
|
186
|
+
raise CFoundry::NotFound
|
187
|
+
|
188
|
+
when 411, 500, 504
|
189
|
+
begin
|
190
|
+
raise_error(parse_json(response))
|
191
|
+
rescue MultiJson::DecodeError
|
192
|
+
raise CFoundry::BadResponse.new(response.code, response)
|
193
|
+
end
|
194
|
+
|
195
|
+
else
|
196
|
+
raise CFoundry::BadResponse.new(response.code, response)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def raise_error(info)
|
201
|
+
case info[:code]
|
202
|
+
when 402
|
203
|
+
raise CFoundry::UploadFailed.new(info[:description])
|
204
|
+
else
|
205
|
+
raise CFoundry::APIError.new(info[:code], info[:description])
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
require "cfoundry/v1/base"
|
2
|
+
require "cfoundry/v1/app"
|
3
|
+
require "cfoundry/v1/service"
|
4
|
+
require "cfoundry/v1/service_instance"
|
5
|
+
require "cfoundry/v1/user"
|
6
|
+
|
7
|
+
|
8
|
+
module CFoundry::V1
|
9
|
+
# The primary API entrypoint. Wraps a BaseClient to provide nicer return
|
10
|
+
# values. Initialize with the target and, optionally, an auth token. These
|
11
|
+
# are the only two internal states.
|
12
|
+
class Client
|
13
|
+
attr_reader :base
|
14
|
+
|
15
|
+
# Create a new Client for interfacing with the given target.
|
16
|
+
#
|
17
|
+
# A token may also be provided to skip the login step.
|
18
|
+
def initialize(target = "http://api.cloudfoundry.com", token = nil)
|
19
|
+
@base = Base.new(target, token)
|
20
|
+
end
|
21
|
+
|
22
|
+
# The current target URL of the client.
|
23
|
+
def target
|
24
|
+
@base.target
|
25
|
+
end
|
26
|
+
|
27
|
+
# Current proxy user. Usually nil.
|
28
|
+
def proxy
|
29
|
+
@base.proxy
|
30
|
+
end
|
31
|
+
|
32
|
+
# Set the proxy user for the client. Must be authorized as an
|
33
|
+
# administrator for this to have any effect.
|
34
|
+
def proxy=(email)
|
35
|
+
@base.proxy = email
|
36
|
+
end
|
37
|
+
|
38
|
+
# Is the client tracing API requests?
|
39
|
+
def trace
|
40
|
+
@base.trace
|
41
|
+
end
|
42
|
+
|
43
|
+
# Set the tracing flag; if true, API requests and responses will be
|
44
|
+
# printed out.
|
45
|
+
def trace=(bool)
|
46
|
+
@base.trace = bool
|
47
|
+
end
|
48
|
+
|
49
|
+
# The currently authenticated user.
|
50
|
+
def current_user
|
51
|
+
if user = info[:user]
|
52
|
+
user(user)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def current_space
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def current_organization
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Retrieve target metadata.
|
66
|
+
def info
|
67
|
+
@base.info
|
68
|
+
end
|
69
|
+
|
70
|
+
# Retrieve available services.
|
71
|
+
def services
|
72
|
+
services = []
|
73
|
+
|
74
|
+
@base.system_services.each do |type, vendors|
|
75
|
+
vendors.each do |vendor, versions|
|
76
|
+
versions.each do |num, meta|
|
77
|
+
services <<
|
78
|
+
Service.new(vendor.to_s, num.to_s, meta[:description], type)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
services
|
84
|
+
end
|
85
|
+
|
86
|
+
# Retrieve available runtimes.
|
87
|
+
def runtimes
|
88
|
+
runtimes = []
|
89
|
+
|
90
|
+
@base.system_runtimes.each do |name, meta|
|
91
|
+
runtimes <<
|
92
|
+
Runtime.new(name.to_s, meta[:version], meta[:debug_modes])
|
93
|
+
end
|
94
|
+
|
95
|
+
runtimes
|
96
|
+
end
|
97
|
+
|
98
|
+
def runtime_by_name(name)
|
99
|
+
runtimes.find { |r| r.name == name }
|
100
|
+
end
|
101
|
+
|
102
|
+
# Retrieve available frameworks.
|
103
|
+
def frameworks
|
104
|
+
fs = info[:frameworks]
|
105
|
+
return unless fs
|
106
|
+
|
107
|
+
frameworks = []
|
108
|
+
fs.each do |name, meta|
|
109
|
+
runtimes = meta[:runtimes].collect do |r|
|
110
|
+
Runtime.new(r[:name], r[:description])
|
111
|
+
end
|
112
|
+
|
113
|
+
frameworks <<
|
114
|
+
Framework.new(name.to_s, nil, runtimes, meta[:detection])
|
115
|
+
end
|
116
|
+
|
117
|
+
frameworks
|
118
|
+
end
|
119
|
+
|
120
|
+
def framework_by_name(name)
|
121
|
+
frameworks.find { |f| f.name == name }
|
122
|
+
end
|
123
|
+
|
124
|
+
# Retrieve user list. Admin-only.
|
125
|
+
def users
|
126
|
+
@base.users.collect do |json|
|
127
|
+
User.new(
|
128
|
+
json[:email],
|
129
|
+
self,
|
130
|
+
{ :email => json[:email],
|
131
|
+
:admin => json[:admin] })
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Construct a User object. The return value is lazy, and no requests are
|
136
|
+
# made from this alone.
|
137
|
+
#
|
138
|
+
# This should be used for both user creation (after calling User#create!)
|
139
|
+
# and retrieval.
|
140
|
+
def user(email)
|
141
|
+
User.new(email, self)
|
142
|
+
end
|
143
|
+
|
144
|
+
# Create a user on the target and return a User object representing them.
|
145
|
+
def register(email, password)
|
146
|
+
@base.create_user(:email => email, :password => password)
|
147
|
+
user(email)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Login prompts
|
151
|
+
def login_prompts
|
152
|
+
if @base.uaa
|
153
|
+
@base.uaa.prompts
|
154
|
+
else
|
155
|
+
{ :username => ["text", "Email"],
|
156
|
+
:password => ["password", "Password"]
|
157
|
+
}
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Authenticate with the target. Sets the client token.
|
162
|
+
#
|
163
|
+
# Credentials is a hash, typically containing :username and :password
|
164
|
+
# keys.
|
165
|
+
#
|
166
|
+
# The values in the hash should mirror the prompts given by
|
167
|
+
# `login_prompts`.
|
168
|
+
def login(credentials)
|
169
|
+
@base.token =
|
170
|
+
if @base.uaa
|
171
|
+
@base.uaa.authorize(credentials)
|
172
|
+
else
|
173
|
+
@base.create_token(
|
174
|
+
{ :password => credentials[:password] },
|
175
|
+
credentials[:username])[:token]
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# Clear client token. No requests are made for this.
|
180
|
+
def logout
|
181
|
+
@base.token = nil
|
182
|
+
end
|
183
|
+
|
184
|
+
# Is an authentication token set on the client?
|
185
|
+
def logged_in?
|
186
|
+
!!@base.token
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
# Retreive all of the current user's applications.
|
191
|
+
def apps(depth = 1, query = {})
|
192
|
+
@base.apps.collect do |json|
|
193
|
+
App.new(json[:name], self, json)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Construct an App object. The return value is lazy, and no requests are
|
198
|
+
# made from this method alone.
|
199
|
+
#
|
200
|
+
# This should be used for both app creation (after calling App#create!)
|
201
|
+
# and retrieval.
|
202
|
+
def app(name = nil)
|
203
|
+
App.new(name, self)
|
204
|
+
end
|
205
|
+
|
206
|
+
def app_by_name(name)
|
207
|
+
app = app(name)
|
208
|
+
app if app.exists?
|
209
|
+
end
|
210
|
+
|
211
|
+
# Retrieve all of the current user's services.
|
212
|
+
def service_instances(depth = 1, query = {})
|
213
|
+
@base.services.collect do |json|
|
214
|
+
ServiceInstance.new(json[:name], self, json)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# Construct a Service object. The return value is lazy, and no requests are
|
219
|
+
# made from this method alone.
|
220
|
+
#
|
221
|
+
# This should be used for both service creation (after calling
|
222
|
+
# Service#create!) and retrieval.
|
223
|
+
def service_instance(name = nil)
|
224
|
+
ServiceInstance.new(name, self)
|
225
|
+
end
|
226
|
+
|
227
|
+
def service_instance_by_name(name)
|
228
|
+
service = service_instance(name)
|
229
|
+
service if service.exists?
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module CFoundry::V1
|
2
|
+
class Framework
|
3
|
+
attr_accessor :name, :description, :runtimes, :detection
|
4
|
+
|
5
|
+
def initialize(name, description = nil, runtimes = [], detection = nil)
|
6
|
+
@name = name
|
7
|
+
@description = description
|
8
|
+
@runtimes = runtimes
|
9
|
+
@detection = detection
|
10
|
+
end
|
11
|
+
|
12
|
+
def eql?(other)
|
13
|
+
other.is_a?(self.class) && other.name == @name
|
14
|
+
end
|
15
|
+
alias :== :eql?
|
16
|
+
|
17
|
+
def apps
|
18
|
+
[] # not supported by v1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|