cfoundry 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/cfoundry/app.rb CHANGED
@@ -6,23 +6,67 @@ require "tmpdir"
6
6
  require "cfoundry/zip"
7
7
 
8
8
  module CFoundry
9
+ # Class for representing a user's application on a given target (via
10
+ # Client).
11
+ #
12
+ # Goes not guarantee that the app exists; used for both app creation and
13
+ # retrieval, as the attributes are all lazily retrieved. Setting attributes
14
+ # does not perform any requests; use #update! to commit your changes.
9
15
  class App
16
+ # Application name.
10
17
  attr_reader :name
11
18
 
19
+ # Application instance count.
20
+ attr_accessor :total_instances
21
+
22
+ # Services bound to the application.
23
+ attr_accessor :services
24
+
25
+ # Application environment variables.
26
+ attr_accessor :env
27
+
28
+ # Application memory limit.
29
+ attr_accessor :memory
30
+
31
+ # Application framework.
32
+ attr_accessor :framework
33
+
34
+ # Application runtime.
35
+ attr_accessor :runtime
36
+
37
+ # Application startup command.
38
+ #
39
+ # Used for standalone apps.
40
+ attr_accessor :command
41
+
42
+ # Application debug mode.
43
+ attr_accessor :debug_mode
44
+
45
+ # Application state.
46
+ attr_accessor :state
47
+ alias_method :status, :state
48
+
49
+ # URIs mapped to the application.
50
+ attr_accessor :uris
51
+ alias_method :urls, :uris
52
+
53
+
54
+ # Create an App object.
55
+ #
56
+ # You'll usually call Client#app instead
12
57
  def initialize(name, client, manifest = nil)
13
58
  @name = name
14
59
  @client = client
15
60
  @manifest = manifest
16
61
  end
17
62
 
18
- def inspect
63
+ def inspect # :nodoc:
19
64
  "#<App '#@name'>"
20
65
  end
21
66
 
22
- def manifest
23
- @manifest ||= @client.rest.app(@name)
24
- end
25
-
67
+ # Delete the application from the target.
68
+ #
69
+ # Keeps the metadata, but clears target-specific state from it.
26
70
  def delete!
27
71
  @client.rest.delete_app(@name)
28
72
 
@@ -33,11 +77,15 @@ module CFoundry
33
77
  end
34
78
  end
35
79
 
80
+ # Create the application on the target.
81
+ #
82
+ # Call this after setting the various attributes.
36
83
  def create!
37
84
  @client.rest.create_app(@manifest.merge("name" => @name))
38
85
  @manifest = nil
39
86
  end
40
87
 
88
+ # Check if the application exists on the target.
41
89
  def exists?
42
90
  @client.rest.app(@name)
43
91
  true
@@ -45,16 +93,19 @@ module CFoundry
45
93
  false
46
94
  end
47
95
 
96
+ # Retrieve all of the instances of the app, as Instance objects.
48
97
  def instances
49
98
  @client.rest.instances(@name).collect do |m|
50
99
  Instance.new(@name, m["index"], @client, m)
51
100
  end
52
101
  end
53
102
 
103
+ # Retrieve application statistics, e.g. CPU load and memory usage.
54
104
  def stats
55
105
  @client.rest.stats(@name)
56
106
  end
57
107
 
108
+ # Update application attributes. Does not restart the application.
58
109
  def update!(what = {})
59
110
  # TODO: hacky; can we not just set in meta field?
60
111
  # we write to manifest["debug"] but read from manifest["meta"]["debug"]
@@ -64,19 +115,28 @@ module CFoundry
64
115
  @manifest = nil
65
116
  end
66
117
 
118
+ # Stop the application.
67
119
  def stop!
68
120
  update! "state" => "STOPPED"
69
121
  end
70
122
 
123
+ # Start the application.
71
124
  def start!
72
125
  update! "state" => "STARTED"
73
126
  end
74
127
 
128
+ # Restart the application.
75
129
  def restart!
76
130
  stop!
77
131
  start!
78
132
  end
79
133
 
134
+ # Determine application health.
135
+ #
136
+ # If all instances are running, returns "RUNNING". If only some are
137
+ # started, returns the precentage of them that are healthy.
138
+ #
139
+ # Otherwise, returns application's status.
80
140
  def health
81
141
  s = state
82
142
  if s == "STARTED"
@@ -97,20 +157,26 @@ module CFoundry
97
157
  end
98
158
  end
99
159
 
160
+ # Check that all application instances are running.
100
161
  def healthy?
101
162
  # invalidate cache so the check is fresh
102
163
  @manifest = nil
103
164
  health == "RUNNING"
104
165
  end
166
+ alias_method :running?, :healthy?
105
167
 
168
+ # Is the application stopped?
106
169
  def stopped?
107
170
  state == "STOPPED"
108
171
  end
109
172
 
173
+ # Is the application started?
174
+ #
175
+ # Note that this does not imply that all instances are running. See
176
+ # #healthy?
110
177
  def started?
111
178
  state == "STARTED"
112
179
  end
113
- alias_method :running?, :started?
114
180
 
115
181
  { :total_instances => "instances",
116
182
  :state => "state",
@@ -130,10 +196,12 @@ module CFoundry
130
196
  end
131
197
  end
132
198
 
199
+ # Shortcut for uris[0]
133
200
  def uri
134
201
  uris[0]
135
202
  end
136
203
 
204
+ # Shortcut for uris = [x]
137
205
  def uri=(x)
138
206
  self.uris = [x]
139
207
  end
@@ -141,12 +209,12 @@ module CFoundry
141
209
  alias :url :uri
142
210
  alias :url= :uri=
143
211
 
144
- def framework
212
+ def framework # :nodoc:
145
213
  manifest["staging"]["framework"] ||
146
214
  manifest["staging"]["model"]
147
215
  end
148
216
 
149
- def framework=(v)
217
+ def framework=(v) # :nodoc:
150
218
  @manifest ||= {}
151
219
  @manifest["staging"] ||= {}
152
220
 
@@ -157,12 +225,12 @@ module CFoundry
157
225
  end
158
226
  end
159
227
 
160
- def runtime
228
+ def runtime # :nodoc:
161
229
  manifest["staging"]["runtime"] ||
162
230
  manifest["staging"]["stack"]
163
231
  end
164
232
 
165
- def runtime=(v)
233
+ def runtime=(v) # :nodoc:
166
234
  @manifest ||= {}
167
235
  @manifest["staging"] ||= {}
168
236
 
@@ -173,39 +241,47 @@ module CFoundry
173
241
  end
174
242
  end
175
243
 
176
- def command
244
+
245
+ def command # :nodoc:
177
246
  manifest["staging"]["command"]
178
247
  end
179
248
 
180
- def command=(v)
249
+ def command=(v) # :nodoc:
181
250
  @manifest ||= {}
182
251
  @manifest["staging"] ||= {}
183
252
  @manifest["staging"]["command"] = v
184
253
  end
185
254
 
186
- def memory
255
+
256
+ def memory # :nodoc:
187
257
  manifest["resources"]["memory"]
188
258
  end
189
259
 
190
- def memory=(v)
260
+ def memory=(v) # :nodoc:
191
261
  @manifest ||= {}
192
262
  @manifest["resources"] ||= {}
193
263
  @manifest["resources"]["memory"] = v
194
264
  end
195
265
 
196
- def debug_mode
197
- manifest.fetch("debug") { manifest["meta"] && manifest["meta"]["debug"] }
266
+
267
+ def debug_mode # :nodoc:
268
+ manifest.fetch("debug") do
269
+ manifest["meta"] && manifest["meta"]["debug"]
270
+ end
198
271
  end
199
272
 
200
- def debug_mode=(v)
273
+ def debug_mode=(v) # :nodoc:
201
274
  @manifest ||= {}
202
275
  @manifest["debug"] = v
203
276
  end
204
277
 
278
+
279
+ # Bind services to application.
205
280
  def bind(*service_names)
206
281
  update!("services" => services + service_names)
207
282
  end
208
283
 
284
+ # Unbind services from application.
209
285
  def unbind(*service_names)
210
286
  update!("services" =>
211
287
  services.reject { |s|
@@ -213,16 +289,46 @@ module CFoundry
213
289
  })
214
290
  end
215
291
 
292
+ # Retrieve file listing under path for the first instance of the application.
293
+ #
294
+ # [path]
295
+ # A sequence of strings representing path segments.
296
+ #
297
+ # For example, <code>files("foo", "bar")</code> for +foo/bar+.
216
298
  def files(*path)
217
299
  Instance.new(@name, 0, @client).files(*path)
218
300
  end
219
301
 
302
+ # Retrieve file contents for the first instance of the application.
303
+ #
304
+ # [path]
305
+ # A sequence of strings representing path segments.
306
+ #
307
+ # For example, <code>files("foo", "bar")</code> for +foo/bar+.
220
308
  def file(*path)
221
309
  Instance.new(@name, 0, @client).file(*path)
222
310
  end
223
311
 
312
+ # Default paths to exclude from upload payload.
313
+ #
314
+ # Value: .git, _darcs, .svn
224
315
  UPLOAD_EXCLUDE = %w{.git _darcs .svn}
225
316
 
317
+ # Upload application's code to target. Do this after #create! and before
318
+ # #start!
319
+ #
320
+ # [path]
321
+ # A path pointing to either a directory, or a .jar, .war, or .zip
322
+ # file.
323
+ #
324
+ # If a .vmcignore file is detected under the given path, it will be used
325
+ # to exclude paths from the payload, similar to a .gitignore.
326
+ #
327
+ # [check_resources]
328
+ # If set to `false`, the entire payload will be uploaded
329
+ # without checking the resource cache.
330
+ #
331
+ # Only do this if you know what you're doing.
226
332
  def upload(path, check_resources = true)
227
333
  unless File.exist? path
228
334
  raise "invalid application path '#{path}'"
@@ -248,6 +354,10 @@ module CFoundry
248
354
 
249
355
  private
250
356
 
357
+ def manifest
358
+ @manifest ||= @client.rest.app(@name)
359
+ end
360
+
251
361
  def prepare_package(path, to)
252
362
  if path =~ /\.(jar|war|zip)$/
253
363
  CFoundry::Zip.unpack(path, to)
@@ -291,6 +401,9 @@ module CFoundry
291
401
  end
292
402
  end
293
403
 
404
+ # Minimum size for an application payload to bother checking resources.
405
+ #
406
+ # Value: 64kb
294
407
  RESOURCE_CHECK_LIMIT = 64 * 1024
295
408
 
296
409
  def determine_resources(path)
@@ -349,9 +462,17 @@ module CFoundry
349
462
  files && files.select { |f| File.socket? f }
350
463
  end
351
464
 
465
+ # Class represnting a running instance of an application.
352
466
  class Instance
353
- attr_reader :app, :index, :manifest
467
+ # The application this instance belongs to.
468
+ attr_reader :app
354
469
 
470
+ # Application instance number.
471
+ attr_reader :index
472
+
473
+ # Create an Instance object.
474
+ #
475
+ # You'll usually call App#instances instead
355
476
  def initialize(appname, index, client, manifest = {})
356
477
  @app = appname
357
478
  @index = index
@@ -359,33 +480,43 @@ module CFoundry
359
480
  @manifest = manifest
360
481
  end
361
482
 
362
- def inspect
483
+ def inspect # :nodoc:
363
484
  "#<App::Instance '#@app' \##@index>"
364
485
  end
365
486
 
487
+ # Instance state.
366
488
  def state
367
489
  @manifest["state"]
368
490
  end
369
491
  alias_method :status, :state
370
492
 
493
+ # Instance start time.
371
494
  def since
372
495
  Time.at(@manifest["since"])
373
496
  end
374
497
 
498
+ # Instance debugger data. If instance is in debug mode, returns a hash
499
+ # containing :ip and :port keys.
375
500
  def debugger
376
501
  return unless @manifest["debug_ip"] and @manifest["debug_port"]
377
- { "ip" => @manifest["debug_ip"],
378
- "port" => @manifest["debug_port"]
502
+
503
+ { :ip => @manifest["debug_ip"],
504
+ :port => @manifest["debug_port"]
379
505
  }
380
506
  end
381
507
 
508
+ # Instance console data. If instance has a console, returns a hash
509
+ # containing :ip and :port keys.
382
510
  def console
383
511
  return unless @manifest["console_ip"] and @manifest["console_port"]
384
- { "ip" => @manifest["console_ip"],
385
- "port" => @manifest["console_port"]
512
+
513
+ { :ip => @manifest["console_ip"],
514
+ :port => @manifest["console_port"]
386
515
  }
387
516
  end
388
517
 
518
+ # True if instance is starting or running, false if it's down or
519
+ # flapping.
389
520
  def healthy?
390
521
  case state
391
522
  when "STARTING", "RUNNING"
@@ -395,12 +526,24 @@ module CFoundry
395
526
  end
396
527
  end
397
528
 
529
+ # Retrieve file listing under path for this instance.
530
+ #
531
+ # [path]
532
+ # A sequence of strings representing path segments.
533
+ #
534
+ # For example, <code>files("foo", "bar")</code> for +foo/bar+.
398
535
  def files(*path)
399
536
  @client.rest.files(@app, @index, *path).split("\n").collect do |entry|
400
537
  path + [entry.split(/\s+/, 2)[0]]
401
538
  end
402
539
  end
403
540
 
541
+ # Retrieve file contents for this instance.
542
+ #
543
+ # [path]
544
+ # A sequence of strings representing path segments.
545
+ #
546
+ # For example, <code>files("foo", "bar")</code> for +foo/bar+.
404
547
  def file(*path)
405
548
  @client.rest.files(@app, @index, *path)
406
549
  end
@@ -5,39 +5,53 @@ require "cfoundry/user"
5
5
 
6
6
 
7
7
  module CFoundry
8
+ # The primary API entrypoint. Wraps RESTClient to provide nicer return
9
+ # values. Initialize with the target and, optionally, an auth token. These
10
+ # are the only two internal states.
8
11
  class Client
9
- attr_reader :rest
12
+ attr_reader :rest #:nodoc:
10
13
 
11
- def initialize(*args)
14
+ # Create a new Client for interfacing with the given target.
15
+ #
16
+ # A token may also be provided to skip the login step.
17
+ def initialize(target = "http://api.cloudfoundry.com", token = nil)
12
18
  @rest = RESTClient.new(*args)
13
19
  end
14
20
 
21
+ # The current target URL of the client.
15
22
  def target
16
23
  @rest.target
17
24
  end
18
25
 
26
+ # Current proxy user. Usually nil.
19
27
  def proxy
20
28
  @rest.proxy
21
29
  end
22
30
 
23
- def proxy=(x)
24
- @rest.proxy = x
31
+ # Set the proxy user for the client. Must be authorized as an
32
+ # administrator for this to have any effect.
33
+ def proxy=(email)
34
+ @rest.proxy = email
25
35
  end
26
36
 
37
+ # Is the client tracing API requests?
27
38
  def trace
28
39
  @rest.trace
29
40
  end
30
41
 
31
- def trace=(x)
32
- @rest.trace = x
42
+ # Set the tracing flag; if true, API requests and responses will be
43
+ # printed out.
44
+ def trace=(bool)
45
+ @rest.trace = bool
33
46
  end
34
47
 
35
48
 
36
- # Cloud metadata
49
+ # Retrieve target metadata.
37
50
  def info
38
51
  @rest.info
39
52
  end
40
53
 
54
+ # Retrieve available services. Returned as a Hash from vendor => metadata.
41
55
  def system_services
42
56
  services = {}
43
57
 
@@ -55,12 +69,13 @@ module CFoundry
55
69
  services
56
70
  end
57
71
 
72
+ # Retrieve available runtimes.
58
73
  def system_runtimes
59
74
  @rest.system_runtimes
60
75
  end
61
76
 
62
77
 
63
- # Users
78
+ # Retrieve user list. Admin-only.
64
79
  def users
65
80
  @rest.users.collect do |json|
66
81
  CFoundry::User.new(
@@ -71,47 +86,67 @@ module CFoundry
71
86
  end
72
87
  end
73
88
 
89
+ # Construct a User object. The return value is lazy, and no requests are
90
+ # made from this alone.
91
+ #
92
+ # This should be used for both user creation (after calling User#create!)
93
+ # and retrieval.
74
94
  def user(email)
75
95
  CFoundry::User.new(email, self)
76
96
  end
77
97
 
98
+ # Create a user on the target and return a User object representing them.
78
99
  def register(email, password)
79
100
  @rest.create_user(:email => email, :password => password)
80
101
  user(email)
81
102
  end
82
103
 
104
+ # Authenticate with the target. Sets the client token.
83
105
  def login(email, password)
84
106
  @rest.token =
85
107
  @rest.create_token({ :password => password }, email)["token"]
86
108
  end
87
109
 
110
+ # Clear client token. No requests are made for this.
88
111
  def logout
89
112
  @rest.token = nil
90
113
  end
91
114
 
115
+ # Is an authentication token set on the client?
92
116
  def logged_in?
93
117
  !!@rest.token
94
118
  end
95
119
 
96
120
 
97
- # Applications
121
+ # Retreive all of the current user's applications.
98
122
  def apps
99
123
  @rest.apps.collect do |json|
100
124
  CFoundry::App.new(json["name"], self, json)
101
125
  end
102
126
  end
103
127
 
128
+ # Construct an App object. The return value is lazy, and no requests are
129
+ # made from this method alone.
130
+ #
131
+ # This should be used for both app creation (after calling App#create!)
132
+ # and retrieval.
104
133
  def app(name)
105
134
  CFoundry::App.new(name, self)
106
135
  end
107
136
 
108
- # Services
137
+
138
+ # Retrieve all of the current user's services.
109
139
  def services
110
140
  @rest.services.collect do |json|
111
141
  CFoundry::Service.new(json["name"], self, json)
112
142
  end
113
143
  end
114
144
 
145
+ # Construct a Service object. The return value is lazy, and no requests are
146
+ # made from this method alone.
147
+ #
148
+ # This should be used for both service creation (after calling
149
+ # Service#create!) and retrieval.
115
150
  def service(name)
116
151
  CFoundry::Service.new(name, self)
117
152
  end
@@ -1,28 +1,32 @@
1
1
  module CFoundry
2
+ # Exception representing errors returned by the API.
2
3
  class APIError < RuntimeError
3
- class << self
4
- attr_reader :error_code, :description
4
+ class << self # :nodoc:
5
+ attr_reader :error_code, :description # :nodoc:
5
6
 
6
- def setup(code, description = nil)
7
+ def setup(code, description = nil) # :nodoc:
7
8
  @error_code = code
8
9
  @description = description
9
10
  end
10
11
  end
11
12
 
13
+ # Create an APIError with a given error code and description.
12
14
  def initialize(error_code = nil, description = nil)
13
15
  @error_code = error_code
14
16
  @description = description
15
17
  end
16
18
 
19
+ # A number representing the error.
17
20
  def error_code
18
21
  @error_code || self.class.error_code
19
22
  end
20
23
 
24
+ # A description of the error.
21
25
  def description
22
26
  @description || self.class.description
23
27
  end
24
28
 
25
- def to_s
29
+ def to_s # :nodoc:
26
30
  if error_code
27
31
  "#{error_code}: #{description}"
28
32
  else
@@ -31,31 +35,40 @@ module CFoundry
31
35
  end
32
36
  end
33
37
 
38
+ # Generic exception thrown when accessing something that doesn't exist (e.g.
39
+ # getting info of unknown application).
34
40
  class NotFound < APIError
35
41
  setup(404, "entity not found or inaccessible")
36
42
  end
37
43
 
44
+ # Lower-level exception for when we cannot connect to the target.
38
45
  class TargetRefused < APIError
39
46
  @description = "target refused connection"
40
47
 
48
+ # Error message.
41
49
  attr_reader :message
42
50
 
51
+ # Message varies as this represents various network errors.
43
52
  def initialize(message)
44
53
  @message = message
45
54
  end
46
55
 
47
- def to_s
56
+ def to_s # :nodoc:
48
57
  "#{description} (#{@message})"
49
58
  end
50
59
  end
51
60
 
61
+ # Exception raised when an application payload fails to upload.
52
62
  class UploadFailed < APIError
53
63
  setup(402)
54
64
  end
55
65
 
66
+ # Exception raised when access is denied to something, either because the
67
+ # user is not logged in or is not an administrator.
56
68
  class Denied < APIError
57
- attr_reader :error_code, :description
69
+ attr_reader :error_code, :description # :nodoc:
58
70
 
71
+ # Initialize, with a default error code and message.
59
72
  def initialize(
60
73
  error_code = 200,
61
74
  description = "Operation not permitted")
@@ -64,13 +77,16 @@ module CFoundry
64
77
  end
65
78
  end
66
79
 
80
+ # Exception raised when the response is unexpected; usually from a server
81
+ # error.
67
82
  class BadResponse < StandardError
83
+ # Initialize, with the HTTP response code and body.
68
84
  def initialize(code, body = nil)
69
85
  @code = code
70
86
  @body = body
71
87
  end
72
88
 
73
- def to_s
89
+ def to_s # :nodoc:
74
90
  "target failed to handle our request due to an internal error (#{@code})"
75
91
  end
76
92
  end
@@ -5,7 +5,7 @@ require "cfoundry/errors"
5
5
 
6
6
 
7
7
  module CFoundry
8
- class RESTClient
8
+ class RESTClient # :nodoc:
9
9
  attr_accessor :target, :token, :proxy, :trace
10
10
 
11
11
  def initialize(
@@ -1,29 +1,58 @@
1
1
  module CFoundry
2
+ # Class for representing a user's service on a given target (via Client).
3
+ #
4
+ # Goes 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.
2
8
  class Service
9
+ # Service name.
3
10
  attr_reader :name
4
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.
5
33
  def initialize(name, client, manifest = nil)
6
34
  @name = name
7
35
  @client = client
8
36
  @manifest = manifest
9
37
  end
10
38
 
11
- def inspect
39
+ def inspect # :nodoc:
12
40
  "#<Service '#@name'>"
13
41
  end
14
42
 
15
- def manifest
16
- @manifest ||= @client.rest.service(@name)
17
- end
18
-
43
+ # Delete the service from the target.
19
44
  def delete!
20
45
  @client.rest.delete_service(@name)
21
46
  end
22
47
 
48
+ # Create the service on the target.
49
+ #
50
+ # Call this after setting the various attributes.
23
51
  def create!
24
52
  @client.rest.create_service(@manifest.merge("name" => @name))
25
53
  end
26
54
 
55
+ # Check if the service exists on the target.
27
56
  def exists?
28
57
  @client.rest.service(@name)
29
58
  true
@@ -31,10 +60,12 @@ module CFoundry
31
60
  false
32
61
  end
33
62
 
63
+ # Timestamp of when the service was created.
34
64
  def created
35
65
  Time.at(meta["created"])
36
66
  end
37
67
 
68
+ # Timestamp of when the service was last updated.
38
69
  def updated
39
70
  Time.at(meta["updated"])
40
71
  end
@@ -55,5 +86,11 @@ module CFoundry
55
86
  @manifest[attr] = v
56
87
  end
57
88
  end
89
+
90
+ private
91
+
92
+ def manifest
93
+ @manifest ||= @client.rest.service(@name)
94
+ end
58
95
  end
59
96
  end
data/lib/cfoundry/user.rb CHANGED
@@ -1,34 +1,46 @@
1
1
  module CFoundry
2
+ # Class for representing a user on a given target (via Client).
3
+ #
4
+ # Goes 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.
2
7
  class User
8
+ # User email.
3
9
  attr_reader :email
4
10
 
11
+
12
+ # Create a User object.
13
+ #
14
+ # You'll usually call Client#user instead
5
15
  def initialize(email, client, manifest = nil)
6
16
  @email = email
7
17
  @client = client
8
18
  @manifest = manifest
9
19
  end
10
20
 
11
- def inspect
21
+ def inspect # :nodoc:
12
22
  "#<User '#@email'>"
13
23
  end
14
24
 
15
- def manifest
16
- @manifest ||= @client.rest.user(@email)
17
- end
18
-
25
+ # Delete the user from the target.
19
26
  def delete!
20
27
  @client.rest.delete_user(@email)
21
28
  end
22
29
 
30
+ # Create the user on the target.
31
+ #
32
+ # Call this after setting the various attributes.
23
33
  def create!
24
34
  @client.rest.create_user(@manifest.merge("email" => @email))
25
35
  end
26
36
 
37
+ # Update user attributes.
27
38
  def update!(what = {})
28
39
  @client.rest.update_user(@email, manifest.merge(what))
29
40
  @manifest = nil
30
41
  end
31
42
 
43
+ # Check if the user exists on the target.
32
44
  def exists?
33
45
  @client.rest.user(@email)
34
46
  true
@@ -36,12 +48,22 @@ module CFoundry
36
48
  false
37
49
  end
38
50
 
51
+ # Check if the user is an administrator.
39
52
  def admin?
40
53
  manifest["admin"]
41
54
  end
42
55
 
56
+ # Set the user's password.
57
+ #
58
+ # Call #update! after using this.
43
59
  def password=(str)
44
60
  manifest["password"] = str
45
61
  end
62
+
63
+ private
64
+
65
+ def manifest
66
+ @manifest ||= @client.rest.user(@email)
67
+ end
46
68
  end
47
69
  end
@@ -1,3 +1,4 @@
1
- module CFoundry
2
- VERSION = "0.2.0"
1
+ module CFoundry # :nodoc:
2
+ # CFoundry library version number.
3
+ VERSION = "0.2.1"
3
4
  end
data/lib/cfoundry/zip.rb CHANGED
@@ -1,11 +1,16 @@
1
- require 'zip/zipfilesystem'
1
+ require "zip/zipfilesystem"
2
2
 
3
3
  module CFoundry
4
+ # Generic Zpi API. Uses rubyzip underneath, but may be changed in the future
5
+ # to use system zip command if necessary.
4
6
  module Zip
7
+ # Directory entries to exclude from packing.
5
8
  PACK_EXCLUSION_GLOBS = ['..', '.', '*~', '#*#', '*.log']
6
9
 
7
10
  module_function
8
11
 
12
+ # Get the entries in the zip file. Returns an array of the entire
13
+ # contents, recursively (not just top-level).
9
14
  def entry_lines(file)
10
15
  entries = []
11
16
  ::Zip::ZipFile.foreach(file) do |zentry|
@@ -14,6 +19,7 @@ module CFoundry
14
19
  entries
15
20
  end
16
21
 
22
+ # Unpack a zip +file+ to directory +dest+.
17
23
  def unpack(file, dest)
18
24
  ::Zip::ZipFile.foreach(file) do |zentry|
19
25
  epath = "#{dest}/#{zentry}"
@@ -23,6 +29,7 @@ module CFoundry
23
29
  end
24
30
  end
25
31
 
32
+ # Determine what files in +dir+ to pack.
26
33
  def files_to_pack(dir)
27
34
  Dir.glob("#{dir}/**/*", File::FNM_DOTMATCH).select do |f|
28
35
  File.exists?(f) &&
@@ -32,6 +39,7 @@ module CFoundry
32
39
  end
33
40
  end
34
41
 
42
+ # Package directory +dir+ as file +zipfile+.
35
43
  def pack(dir, zipfile)
36
44
  files = files_to_pack(dir)
37
45
  return false if files.empty?
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cfoundry
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 0
10
- version: 0.2.0
9
+ - 1
10
+ version: 0.2.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Alex Suraci
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-05-31 00:00:00 Z
18
+ date: 2012-06-02 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rest-client