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.
@@ -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