cfoundry 0.3.19 → 0.3.20

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,100 @@
1
+ require "fileutils"
2
+ require "pathname"
3
+ require "digest/sha1"
4
+
5
+ module CFoundry
6
+ module UploadHelpers
7
+ # Default paths to exclude from upload payload.
8
+ UPLOAD_EXCLUDE = %w{.git _darcs .svn}
9
+
10
+ def make_fingerprints(path)
11
+ fingerprints = []
12
+ total_size = 0
13
+
14
+ Dir.glob("#{path}/**/*", File::FNM_DOTMATCH) do |filename|
15
+ next if File.directory?(filename)
16
+
17
+ size = File.size(filename)
18
+
19
+ total_size += size
20
+
21
+ fingerprints << {
22
+ :size => size,
23
+ :sha1 => Digest::SHA1.file(filename).hexdigest,
24
+ :fn => filename
25
+ }
26
+ end
27
+
28
+ [fingerprints, total_size]
29
+ end
30
+
31
+ def prepare_package(path, to)
32
+ if path =~ /\.(jar|war|zip)$/
33
+ CFoundry::Zip.unpack(path, to)
34
+ elsif war_file = Dir.glob("#{path}/*.war").first
35
+ CFoundry::Zip.unpack(war_file, to)
36
+ else
37
+ check_unreachable_links(path)
38
+
39
+ FileUtils.mkdir(to)
40
+
41
+ files = Dir.glob("#{path}/{*,.[^\.]*}")
42
+
43
+ exclude = UPLOAD_EXCLUDE
44
+ if File.exists?("#{path}/.vmcignore")
45
+ exclude += File.read("#{path}/.vmcignore").split(/\n+/)
46
+ end
47
+
48
+ # prevent initial copying if we can, remove sub-files later
49
+ files.reject! do |f|
50
+ exclude.any? do |e|
51
+ File.fnmatch(f.sub(path + "/", ""), e)
52
+ end
53
+ end
54
+
55
+ FileUtils.cp_r(files, to)
56
+
57
+ find_sockets(to).each do |s|
58
+ File.delete s
59
+ end
60
+
61
+ # remove ignored globs more thoroughly
62
+ #
63
+ # note that the above file list only includes toplevel
64
+ # files/directories for cp_r, so this is where sub-files/etc. are
65
+ # removed
66
+ exclude.each do |e|
67
+ Dir.glob("#{to}/#{e}").each do |f|
68
+ FileUtils.rm_rf(f)
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def check_unreachable_links(path)
75
+ files = Dir.glob("#{path}/**/*", File::FNM_DOTMATCH)
76
+
77
+ # only used for friendlier error message
78
+ pwd = Pathname.pwd
79
+
80
+ abspath = File.expand_path(path)
81
+ unreachable = []
82
+ files.each do |f|
83
+ file = Pathname.new(f)
84
+ if file.symlink? && !file.realpath.to_s.start_with?(abspath)
85
+ unreachable << file.relative_path_from(pwd)
86
+ end
87
+ end
88
+
89
+ unless unreachable.empty?
90
+ root = Pathname.new(path).relative_path_from(pwd)
91
+ raise "Can't deploy application containing links '#{unreachable}' that reach outside its root '#{root}'"
92
+ end
93
+ end
94
+
95
+ def find_sockets(path)
96
+ files = Dir.glob("#{path}/**/*", File::FNM_DOTMATCH)
97
+ files && files.select { |f| File.socket? f }
98
+ end
99
+ end
100
+ end
@@ -1,9 +1,7 @@
1
- require "fileutils"
2
- require "digest/sha1"
3
- require "pathname"
4
1
  require "tmpdir"
5
2
 
6
3
  require "cfoundry/zip"
4
+ require "cfoundry/upload_helpers"
7
5
  require "cfoundry/chatty_hash"
8
6
 
9
7
  require "cfoundry/v1/framework"
@@ -17,6 +15,8 @@ module CFoundry::V1
17
15
  # retrieval, as the attributes are all lazily retrieved. Setting attributes
18
16
  # does not perform any requests; use #update! to commit your changes.
19
17
  class App
18
+ include CFoundry::UploadHelpers
19
+
20
20
  # Application name.
21
21
  attr_accessor :name
22
22
 
@@ -323,9 +323,6 @@ module CFoundry::V1
323
323
  Instance.new(@name, 0, @client).file(*path)
324
324
  end
325
325
 
326
- # Default paths to exclude from upload payload.
327
- UPLOAD_EXCLUDE = %w{.git _darcs .svn}
328
-
329
326
  # Upload application's code to target. Do this after #create! and before
330
327
  # #start!
331
328
  #
@@ -443,69 +440,11 @@ module CFoundry::V1
443
440
  }
444
441
  end
445
442
 
446
- def prepare_package(path, to)
447
- if path =~ /\.(jar|war|zip)$/
448
- CFoundry::Zip.unpack(path, to)
449
- elsif war_file = Dir.glob("#{path}/*.war").first
450
- CFoundry::Zip.unpack(war_file, to)
451
- else
452
- check_unreachable_links(path)
453
-
454
- FileUtils.mkdir(to)
455
-
456
- files = Dir.glob("#{path}/{*,.[^\.]*}")
457
-
458
- exclude = UPLOAD_EXCLUDE
459
- if File.exists?("#{path}/.vmcignore")
460
- exclude += File.read("#{path}/.vmcignore").split(/\n+/)
461
- end
462
-
463
- # prevent initial copying if we can, remove sub-files later
464
- files.reject! do |f|
465
- exclude.any? do |e|
466
- File.fnmatch(f.sub(path + "/", ""), e)
467
- end
468
- end
469
-
470
- FileUtils.cp_r(files, to)
471
-
472
- find_sockets(to).each do |s|
473
- File.delete s
474
- end
475
-
476
- # remove ignored globs more thoroughly
477
- #
478
- # note that the above file list only includes toplevel
479
- # files/directories for cp_r, so this is where sub-files/etc. are
480
- # removed
481
- exclude.each do |e|
482
- Dir.glob("#{to}/#{e}").each do |f|
483
- FileUtils.rm_rf(f)
484
- end
485
- end
486
- end
487
- end
488
-
489
443
  # Minimum size for an application payload to bother checking resources.
490
444
  RESOURCE_CHECK_LIMIT = 64 * 1024
491
445
 
492
446
  def determine_resources(path)
493
- fingerprints = []
494
- total_size = 0
495
-
496
- Dir.glob("#{path}/**/*", File::FNM_DOTMATCH) do |filename|
497
- next if File.directory?(filename)
498
-
499
- size = File.size(filename)
500
-
501
- total_size += size
502
-
503
- fingerprints << {
504
- :size => size,
505
- :sha1 => Digest::SHA1.file(filename).hexdigest,
506
- :fn => filename
507
- }
508
- end
447
+ fingerprints, total_size = make_fingerprints(path)
509
448
 
510
449
  return if total_size <= RESOURCE_CHECK_LIMIT
511
450
 
@@ -519,32 +458,6 @@ module CFoundry::V1
519
458
  resources
520
459
  end
521
460
 
522
- def check_unreachable_links(path)
523
- files = Dir.glob("#{path}/**/*", File::FNM_DOTMATCH)
524
-
525
- # only used for friendlier error message
526
- pwd = Pathname.pwd
527
-
528
- abspath = File.expand_path(path)
529
- unreachable = []
530
- files.each do |f|
531
- file = Pathname.new(f)
532
- if file.symlink? && !file.realpath.to_s.start_with?(abspath)
533
- unreachable << file.relative_path_from(pwd)
534
- end
535
- end
536
-
537
- unless unreachable.empty?
538
- root = Pathname.new(path).relative_path_from(pwd)
539
- raise "Can't deploy application containing links '#{unreachable}' that reach outside its root '#{root}'"
540
- end
541
- end
542
-
543
- def find_sockets(path)
544
- files = Dir.glob("#{path}/**/*", File::FNM_DOTMATCH)
545
- files && files.select { |f| File.socket? f }
546
- end
547
-
548
461
  # Class represnting a running instance of an application.
549
462
  class Instance
550
463
  # The application this instance belongs to.
@@ -1,10 +1,8 @@
1
- require "fileutils"
2
- require "digest/sha1"
3
- require "pathname"
4
1
  require "tmpdir"
5
2
  require "json"
6
3
 
7
4
  require "cfoundry/zip"
5
+ require "cfoundry/upload_helpers"
8
6
  require "cfoundry/chatty_hash"
9
7
 
10
8
  require "cfoundry/v2/model"
@@ -17,6 +15,8 @@ module CFoundry::V2
17
15
  # retrieval, as the attributes are all lazily retrieved. Setting attributes
18
16
  # does not perform any requests; use #update! to commit your changes.
19
17
  class App < Model
18
+ include CFoundry::UploadHelpers
19
+
20
20
  attribute :name
21
21
  attribute :production
22
22
  to_one :space
@@ -154,5 +154,63 @@ module CFoundry::V2
154
154
  b.service_instance == instance
155
155
  }
156
156
  end
157
+
158
+ # Upload application's code to target. Do this after #create! and before
159
+ # #start!
160
+ #
161
+ # [path]
162
+ # A path pointing to either a directory, or a .jar, .war, or .zip
163
+ # file.
164
+ #
165
+ # If a .vmcignore file is detected under the given path, it will be used
166
+ # to exclude paths from the payload, similar to a .gitignore.
167
+ #
168
+ # [check_resources]
169
+ # If set to `false`, the entire payload will be uploaded
170
+ # without checking the resource cache.
171
+ #
172
+ # Only do this if you know what you're doing.
173
+ def upload(path, check_resources = true)
174
+ unless File.exist? path
175
+ raise "invalid application path '#{path}'"
176
+ end
177
+
178
+ zipfile = "#{Dir.tmpdir}/#{@guid}.zip"
179
+ tmpdir = "#{Dir.tmpdir}/.vmc_#{@guid}_files"
180
+
181
+ FileUtils.rm_f(zipfile)
182
+ FileUtils.rm_rf(tmpdir)
183
+
184
+ prepare_package(path, tmpdir)
185
+
186
+ resources = determine_resources(tmpdir) if check_resources
187
+
188
+ packed = CFoundry::Zip.pack(tmpdir, zipfile)
189
+
190
+ @client.base.upload_app(@guid, packed && zipfile, resources || [])
191
+ ensure
192
+ FileUtils.rm_f(zipfile) if zipfile
193
+ FileUtils.rm_rf(tmpdir) if tmpdir
194
+ end
195
+
196
+ private
197
+
198
+ # Minimum size for an application payload to bother checking resources.
199
+ RESOURCE_CHECK_LIMIT = 64 * 1024
200
+
201
+ def determine_resources(path)
202
+ fingerprints, total_size = make_fingerprints(path)
203
+
204
+ return if total_size <= RESOURCE_CHECK_LIMIT
205
+
206
+ resources = @client.base.resource_match(fingerprints)
207
+
208
+ resources.each do |resource|
209
+ FileUtils.rm_f resource[:fn]
210
+ resource[:fn].sub!("#{path}/", "")
211
+ end
212
+
213
+ resources
214
+ end
157
215
  end
158
216
  end
@@ -78,6 +78,27 @@ module CFoundry::V2
78
78
  end
79
79
  end
80
80
 
81
+ def resource_match(fingerprints)
82
+ post(fingerprints, "v2", "resource_match", :json => :json)
83
+ end
84
+
85
+ def upload_app(guid, zipfile, resources = [])
86
+ payload = {
87
+ :resources => resources.to_json,
88
+ :multipart => true,
89
+ :application =>
90
+ if zipfile.is_a? File
91
+ zipfile
92
+ elsif zipfile.is_a? String
93
+ File.new(zipfile, "rb")
94
+ end
95
+ }
96
+
97
+ put(payload, "v2", "apps", guid, "bits")
98
+ rescue RestClient::ServerBrokeConnection
99
+ retry
100
+ end
101
+
81
102
 
82
103
  def params_from(args)
83
104
  depth, query = args
@@ -172,11 +172,11 @@ module CFoundry::V2
172
172
  end
173
173
 
174
174
  def update!(diff = @diff)
175
- @client.base.send(:"update_#{object_name}", @guid, diff)
175
+ @manifest = @client.base.send(:"update_#{object_name}", @guid, diff)
176
176
 
177
177
  @diff.clear if diff == @diff
178
178
 
179
- @manifest = nil
179
+ true
180
180
  end
181
181
 
182
182
  def delete!
@@ -1,4 +1,4 @@
1
1
  module CFoundry # :nodoc:
2
2
  # CFoundry library version number.
3
- VERSION = "0.3.19"
3
+ VERSION = "0.3.20"
4
4
  end
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: 53
4
+ hash: 59
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 19
10
- version: 0.3.19
9
+ - 20
10
+ version: 0.3.20
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-08-06 00:00:00 Z
18
+ date: 2012-08-15 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rest-client
@@ -110,6 +110,7 @@ files:
110
110
  - lib/cfoundry/client.rb
111
111
  - lib/cfoundry/errors.rb
112
112
  - lib/cfoundry/uaaclient.rb
113
+ - lib/cfoundry/upload_helpers.rb
113
114
  - lib/cfoundry/v1/app.rb
114
115
  - lib/cfoundry/v1/base.rb
115
116
  - lib/cfoundry/v1/client.rb
@@ -168,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
169
  requirements: []
169
170
 
170
171
  rubyforge_project: cfoundry
171
- rubygems_version: 1.8.23
172
+ rubygems_version: 1.8.24
172
173
  signing_key:
173
174
  specification_version: 3
174
175
  summary: High-level library for working with the Cloud Foundry API.