cfoundry 0.3.19 → 0.3.20

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.