cfoundry 0.2.0 → 0.2.1

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/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