cfoundry-IronFoundry 0.3.34

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ module CFoundry::V1
2
+ class Runtime
3
+ attr_accessor :name, :description, :debug_modes
4
+
5
+ def initialize(name, description = nil, debug_modes = nil)
6
+ @name = name
7
+ @description = description
8
+ @debug_modes = debug_modes
9
+ end
10
+
11
+ def eql?(other)
12
+ other.is_a?(self.class) && other.name == @name
13
+ end
14
+ alias :== :eql?
15
+
16
+ def apps
17
+ [] # not supported by v1
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ module CFoundry::V1
2
+ class Service
3
+ attr_accessor :label, :version, :description, :type
4
+
5
+ def initialize(label, version = nil, description = nil, type = nil)
6
+ @label = label
7
+ @description = description
8
+ @version = version
9
+ @type = nil
10
+ end
11
+
12
+ def eql?(other)
13
+ other.is_a?(self.class) && other.label == @label
14
+ end
15
+ alias :== :eql?
16
+
17
+ def provider
18
+ "core"
19
+ end
20
+
21
+ def active
22
+ true
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,112 @@
1
+ module CFoundry::V1
2
+ # Class for representing a user's service on a given target (via Client).
3
+ #
4
+ # Does not guarantee that the service exists; used for both service creation
5
+ # and retrieval, as the attributes are all lazily retrieved. Setting
6
+ # attributes does not perform any requests; use #update! to commit your
7
+ # changes.
8
+ class ServiceInstance
9
+ # Service name.
10
+ attr_accessor :name
11
+
12
+ # Service type (e.g. key-value).
13
+ attr_accessor :type
14
+
15
+ # Service vendor (redis, mysql, etc.).
16
+ attr_accessor :vendor
17
+
18
+ # Service version.
19
+ attr_accessor :version
20
+
21
+ # Service properties.
22
+ attr_accessor :properties
23
+
24
+ # Service tier. Usually "free" for now.
25
+ attr_accessor :tier
26
+
27
+ # Service metadata.
28
+ attr_accessor :meta
29
+
30
+ # Create a Service object.
31
+ #
32
+ # You'll usually call Client#service instead.
33
+ def initialize(name, client, manifest = nil)
34
+ @name = name
35
+ @client = client
36
+ @manifest = manifest
37
+ end
38
+
39
+ # Show string representing the service.
40
+ def inspect
41
+ "#<ServiceInstance '#@name'>"
42
+ end
43
+
44
+ # Basic equality test by name.
45
+ def eql?(other)
46
+ other.is_a?(self.class) && other.name == @name
47
+ end
48
+ alias :== :eql?
49
+
50
+ # Delete the service from the target.
51
+ def delete!
52
+ @client.base.delete_service(@name)
53
+ end
54
+
55
+ # Create the service on the target.
56
+ #
57
+ # Call this after setting the various attributes.
58
+ def create!
59
+ @client.base.create_service(@manifest.merge(:name => @name))
60
+ end
61
+
62
+ # Check if the service exists on the target.
63
+ def exists?
64
+ @client.base.service(@name)
65
+ true
66
+ rescue CFoundry::NotFound
67
+ false
68
+ end
69
+
70
+ # Timestamp of when the service was created.
71
+ def created
72
+ Time.at(meta[:created])
73
+ end
74
+
75
+ # Timestamp of when the service was last updated.
76
+ def updated
77
+ Time.at(meta[:updated])
78
+ end
79
+
80
+ def invalidate!
81
+ @manifest = nil
82
+ end
83
+
84
+ def eql?(other)
85
+ other.is_a?(self.class) && @name == other.name
86
+ end
87
+ alias :== :eql?
88
+
89
+ { :type => :type,
90
+ :vendor => :vendor,
91
+ :version => :version,
92
+ :properties => :properties,
93
+ :tier => :tier,
94
+ :meta => :meta
95
+ }.each do |meth, attr|
96
+ define_method(meth) do
97
+ manifest[attr]
98
+ end
99
+
100
+ define_method(:"#{meth}=") do |v|
101
+ @manifest ||= {}
102
+ @manifest[attr] = v
103
+ end
104
+ end
105
+
106
+ private
107
+
108
+ def manifest
109
+ @manifest ||= @client.base.service(@name)
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,89 @@
1
+ module CFoundry::V1
2
+ # Class for representing a user on a given target (via Client).
3
+ #
4
+ # Does not guarantee that the user exists; used for both user creation and
5
+ # retrieval, as the attributes are all lazily retrieved. Setting attributes
6
+ # does not perform any requests; use #update! to commit your changes.
7
+ class User
8
+ # User email.
9
+ attr_reader :email
10
+
11
+
12
+ # Create a User object.
13
+ #
14
+ # You'll usually call Client#user instead
15
+ def initialize(email, client, manifest = nil)
16
+ @email = email
17
+ @client = client
18
+ @manifest = manifest
19
+ end
20
+
21
+ # Show string representing the user.
22
+ def inspect
23
+ "#<User '#@email'>"
24
+ end
25
+
26
+ # Basic equality test by email.
27
+ def eql?(other)
28
+ other.is_a?(self.class) && other.email == @email
29
+ end
30
+ alias :== :eql?
31
+
32
+ # Delete the user from the target.
33
+ def delete!
34
+ @client.base.delete_user(@email)
35
+ end
36
+
37
+ # Create the user on the target.
38
+ #
39
+ # Call this after setting the various attributes.
40
+ def create!
41
+ @client.base.create_user(@manifest.merge(:email => @email))
42
+ end
43
+
44
+ # Update user attributes.
45
+ def update!(what = {})
46
+ @client.base.update_user(@email, manifest.merge(what))
47
+ @manifest = nil
48
+ end
49
+
50
+ # Check if the user exists on the target.
51
+ def exists?
52
+ @client.base.user(@email)
53
+ true
54
+ rescue CFoundry::Denied
55
+ false
56
+ end
57
+
58
+ # Check if the user is an administrator.
59
+ def admin?
60
+ manifest[:admin]
61
+ end
62
+
63
+ # Set the user's password.
64
+ #
65
+ # Call #update! after using this.
66
+ def password=(str)
67
+ manifest[:password] = str
68
+ end
69
+
70
+ def guid
71
+ @guid ||= @client.base.token_data[:user_id]
72
+ end
73
+
74
+ def change_password!(new, old)
75
+ if @client.base.uaa
76
+ @client.base.uaa.change_password(guid, new, old)
77
+ else
78
+ self.password = new
79
+ update!
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def manifest
86
+ @manifest ||= @client.base.user(@email)
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,328 @@
1
+ require "tmpdir"
2
+ require "multi_json"
3
+
4
+ require "cfoundry/zip"
5
+ require "cfoundry/upload_helpers"
6
+ require "cfoundry/chatty_hash"
7
+
8
+ require "cfoundry/v2/model"
9
+
10
+ module CFoundry::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 CFoundry::UploadHelpers
19
+
20
+ attribute :name, :string
21
+ attribute :production, :boolean, :default => false
22
+ to_one :space
23
+ to_one :runtime
24
+ to_one :framework
25
+ attribute :environment_json, :hash, :default => {}
26
+ attribute :memory, :integer, :default => 256
27
+ attribute :instances, :integer, :default => 1
28
+ attribute :file_descriptors, :integer, :default => 256
29
+ attribute :disk_quota, :integer, :default => 256
30
+ attribute :state, :integer, :default => "STOPPED"
31
+ to_many :service_bindings
32
+ to_many :routes
33
+
34
+ alias :total_instances :instances
35
+ alias :total_instances= :instances=
36
+
37
+ private :environment_json
38
+
39
+ def instances
40
+ @client.base.instances(@guid).collect do |i, m|
41
+ Instance.new(self, i.to_s, @client, m)
42
+ end
43
+ end
44
+
45
+ def stats
46
+ @client.base.stats(@guid)
47
+ end
48
+
49
+ def services
50
+ service_bindings.collect(&:service_instance)
51
+ end
52
+
53
+ def env
54
+ @env ||= CFoundry::ChattyHash.new(
55
+ method(:env=),
56
+ environment_json)
57
+ end
58
+
59
+ alias :env= :environment_json=
60
+
61
+ def command # TODO v2
62
+ nil
63
+ end
64
+
65
+ def debug_mode # TODO v2
66
+ nil
67
+ end
68
+
69
+ def console # TODO v2
70
+ nil
71
+ end
72
+
73
+ def uris
74
+ routes.collect do |r|
75
+ "#{r.host}.#{r.domain.name}"
76
+ end
77
+ end
78
+ alias :urls :uris
79
+
80
+ def uris=(uris)
81
+ raise "App#uris= is invalid against V2 APIs. Use add/remove_route."
82
+ end
83
+ alias :urls= :uris=
84
+
85
+ def create_routes(*uris)
86
+ uris.each do |uri|
87
+ host, domain_name = uri.split(".", 2)
88
+
89
+ domain =
90
+ @client.current_space.domains.find { |d|
91
+ d.name == domain_name
92
+ }
93
+
94
+ raise "Invalid domain '#{domain_name}'" unless domain
95
+
96
+ route = @client.routes.find { |r|
97
+ r.host == host && r.domain == domain
98
+ }
99
+
100
+ unless route
101
+ route = @client.route
102
+ route.host = host
103
+ route.domain = domain
104
+ route.organization = @client.current_organization
105
+ route.create!
106
+ end
107
+
108
+ add_route(route)
109
+ end
110
+ end
111
+ alias :create_route :create_routes
112
+
113
+ def uri
114
+ uris[0]
115
+ end
116
+ alias :url :uri
117
+
118
+ def uri=(x)
119
+ self.uris = [x]
120
+ end
121
+ alias :url= :uri=
122
+
123
+ # Stop the application.
124
+ def stop!
125
+ update! :state => "STOPPED"
126
+ end
127
+
128
+ # Start the application.
129
+ def start!
130
+ update! :state => "STARTED"
131
+ end
132
+
133
+ # Restart the application.
134
+ def restart!
135
+ stop!
136
+ start!
137
+ end
138
+
139
+ # Determine application health.
140
+ #
141
+ # If all instances are running, returns "RUNNING". If only some are
142
+ # started, returns the precentage of them that are healthy.
143
+ #
144
+ # Otherwise, returns application's status.
145
+ def health
146
+ state
147
+ end
148
+
149
+ # Check that all application instances are running.
150
+ def healthy?
151
+ # invalidate cache so the check is fresh
152
+ @manifest = nil
153
+
154
+ case health
155
+ when "RUNNING", "STARTED"
156
+ true
157
+ end
158
+ end
159
+ alias_method :running?, :healthy?
160
+
161
+ # Is the application stopped?
162
+ def stopped?
163
+ state == "STOPPED"
164
+ end
165
+
166
+ # Is the application started?
167
+ #
168
+ # Note that this does not imply that all instances are running. See
169
+ # #healthy?
170
+ def started?
171
+ state == "STARTED"
172
+ end
173
+
174
+ # Bind services to application.
175
+ def bind(*instances)
176
+ instances.each do |i|
177
+ binding = @client.service_binding
178
+ binding.app = self
179
+ binding.service_instance = i
180
+ binding.create!
181
+ end
182
+
183
+ self
184
+ end
185
+
186
+ # Unbind services from application.
187
+ def unbind(*instances)
188
+ service_bindings.each do |b|
189
+ if instances.include? b.service_instance
190
+ b.delete!
191
+ end
192
+ end
193
+
194
+ self
195
+ end
196
+
197
+ def binds?(instance)
198
+ service_bindings.any? { |b|
199
+ b.service_instance == instance
200
+ }
201
+ end
202
+
203
+ # Upload application's code to target. Do this after #create! and before
204
+ # #start!
205
+ #
206
+ # [path]
207
+ # A path pointing to either a directory, or a .jar, .war, or .zip
208
+ # file.
209
+ #
210
+ # If a .vmcignore file is detected under the given path, it will be used
211
+ # to exclude paths from the payload, similar to a .gitignore.
212
+ #
213
+ # [check_resources]
214
+ # If set to `false`, the entire payload will be uploaded
215
+ # without checking the resource cache.
216
+ #
217
+ # Only do this if you know what you're doing.
218
+ def upload(path, check_resources = true)
219
+ unless File.exist? path
220
+ raise "invalid application path '#{path}'"
221
+ end
222
+
223
+ zipfile = "#{Dir.tmpdir}/#{@guid}.zip"
224
+ tmpdir = "#{Dir.tmpdir}/.vmc_#{@guid}_files"
225
+
226
+ FileUtils.rm_f(zipfile)
227
+ FileUtils.rm_rf(tmpdir)
228
+
229
+ prepare_package(path, tmpdir)
230
+
231
+ resources = determine_resources(tmpdir) if check_resources
232
+
233
+ packed = CFoundry::Zip.pack(tmpdir, zipfile)
234
+
235
+ @client.base.upload_app(@guid, packed && zipfile, resources || [])
236
+ ensure
237
+ FileUtils.rm_f(zipfile) if zipfile
238
+ FileUtils.rm_rf(tmpdir) if tmpdir
239
+ end
240
+
241
+ def files(*path)
242
+ Instance.new(self, "0", @client).files(*path)
243
+ end
244
+
245
+ def file(*path)
246
+ Instance.new(self, "0", @client).file(*path)
247
+ end
248
+
249
+ class Instance
250
+ attr_reader :app, :id
251
+
252
+ def initialize(app, id, client, manifest = {})
253
+ @app = app
254
+ @id = id
255
+ @client = client
256
+ @manifest = manifest
257
+ end
258
+
259
+ def inspect
260
+ "#<App::Instance '#{@app.name}' \##@id>"
261
+ end
262
+
263
+ def state
264
+ @manifest[:state]
265
+ end
266
+ alias_method :status, :state
267
+
268
+ def since
269
+ Time.at(@manifest[:since])
270
+ end
271
+
272
+ def debugger
273
+ return unless @manifest[:debug_ip] and @manifest[:debug_port]
274
+
275
+ { :ip => @manifest[:debug_ip],
276
+ :port => @manifest[:debug_port]
277
+ }
278
+ end
279
+
280
+ def console
281
+ return unless @manifest[:console_ip] and @manifest[:console_port]
282
+
283
+ { :ip => @manifest[:console_ip],
284
+ :port => @manifest[:console_port]
285
+ }
286
+ end
287
+
288
+ def healthy?
289
+ case state
290
+ when "STARTING", "RUNNING"
291
+ true
292
+ when "DOWN", "FLAPPING"
293
+ false
294
+ end
295
+ end
296
+
297
+ def files(*path)
298
+ @client.base.files(@app.guid, @id, *path).split("\n").collect do |entry|
299
+ path + [entry.split(/\s+/, 2)[0]]
300
+ end
301
+ end
302
+
303
+ def file(*path)
304
+ @client.base.files(@app.guid, @id, *path)
305
+ end
306
+ end
307
+
308
+ private
309
+
310
+ # Minimum size for an application payload to bother checking resources.
311
+ RESOURCE_CHECK_LIMIT = 64 * 1024
312
+
313
+ def determine_resources(path)
314
+ fingerprints, total_size = make_fingerprints(path)
315
+
316
+ return if total_size <= RESOURCE_CHECK_LIMIT
317
+
318
+ resources = @client.base.resource_match(fingerprints)
319
+
320
+ resources.each do |resource|
321
+ FileUtils.rm_f resource[:fn]
322
+ resource[:fn].sub!("#{path}/", "")
323
+ end
324
+
325
+ resources
326
+ end
327
+ end
328
+ end