Class: Chef::CookbookUploader
Instance Attribute Summary collapse
-
#cookbook ⇒ Object
readonly
Returns the value of attribute cookbook.
-
#opts ⇒ Object
readonly
Returns the value of attribute opts.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#rest ⇒ Object
readonly
Returns the value of attribute rest.
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(cookbook, path, opts = {}) ⇒ CookbookUploader
constructor
Creates a new CookbookUploader.
- #upload_cookbook ⇒ Object
- #uploader_function_for(file, checksum, url, checksums_to_upload) ⇒ Object
- #validate_cookbook ⇒ Object
- #worker_thread(work_queue) ⇒ Object
Constructor Details
#initialize(cookbook, path, opts = {}) ⇒ CookbookUploader
Creates a new CookbookUploader.
Arguments:
- cookbook:
-
A Chef::CookbookVersion describing the cookbook to be uploaded
- path:
-
A String or Array of Strings representing the base paths to the cookbook repositories.
- opts:
-
(optional) An options Hash
Options:
-
:force indicates that the uploader should set the force option when
uploading the cookbook. This allows frozen CookbookVersion documents on the server to be overwritten (otherwise a 409 is returned by the server)
-
:rest A Chef::REST object that you have configured the way you like it.
If you don't provide this, one will be created using the values in Chef::Config.
51 52 53 54 |
# File 'lib/chef/cookbook_uploader.rb', line 51 def initialize(cookbook, path, opts={}) @cookbook, @path, @opts = cookbook, path, opts @rest = opts[:rest] || Chef::REST.new(Chef::Config[:chef_server_url]) end |
Instance Attribute Details
#cookbook ⇒ Object (readonly)
Returns the value of attribute cookbook.
32 33 34 |
# File 'lib/chef/cookbook_uploader.rb', line 32 def cookbook @cookbook end |
#opts ⇒ Object (readonly)
Returns the value of attribute opts.
34 35 36 |
# File 'lib/chef/cookbook_uploader.rb', line 34 def opts @opts end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
33 34 35 |
# File 'lib/chef/cookbook_uploader.rb', line 33 def path @path end |
#rest ⇒ Object (readonly)
Returns the value of attribute rest.
35 36 37 |
# File 'lib/chef/cookbook_uploader.rb', line 35 def rest @rest end |
Class Method Details
.setup_worker_threads ⇒ Object
19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/chef/cookbook_uploader.rb', line 19 def self.setup_worker_threads @worker_threads ||= begin work_queue (1...10).map do Thread.new do loop do work_queue.pop.call end end end end end |
.work_queue ⇒ Object
15 16 17 |
# File 'lib/chef/cookbook_uploader.rb', line 15 def self.work_queue @work_queue ||= Queue.new end |
Instance Method Details
#upload_cookbook ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/chef/cookbook_uploader.rb', line 56 def upload_cookbook Thread.abort_on_exception = true Chef::Log.info("Saving #{cookbook.name}") # Syntax Check validate_cookbook # generate checksums of cookbook files and create a sandbox checksum_files = cookbook.checksums checksums = checksum_files.inject({}){|memo,elt| memo[elt.first]=nil ; memo} new_sandbox = rest.post_rest("sandboxes", { :checksums => checksums }) Chef::Log.info("Uploading files") self.class.setup_worker_threads checksums_to_upload = Set.new # upload the new checksums and commit the sandbox new_sandbox['checksums'].each do |checksum, info| if info['needs_upload'] == true checksums_to_upload << checksum Chef::Log.info("Uploading #{checksum_files[checksum]} (checksum hex = #{checksum}) to #{info['url']}") self.class.work_queue << uploader_function_for(checksum_files[checksum], checksum, info['url'], checksums_to_upload) else Chef::Log.debug("#{checksum_files[checksum]} has not changed") end end until checksums_to_upload.empty? sleep 0.1 end sandbox_url = new_sandbox['uri'] Chef::Log.debug("Committing sandbox") # Retry if S3 is claims a checksum doesn't exist (the eventual # in eventual consistency) retries = 0 begin rest.put_rest(sandbox_url, {:is_completed => true}) rescue Net::HTTPServerException => e if e. =~ /^400/ && (retries += 1) <= 5 sleep 2 retry else raise end end # files are uploaded, so save the manifest save_url = opts[:force] ? cookbook.force_save_url : cookbook.save_url rest.put_rest(save_url, cookbook) Chef::Log.info("Upload complete!") end |
#uploader_function_for(file, checksum, url, checksums_to_upload) ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/chef/cookbook_uploader.rb', line 114 def uploader_function_for(file, checksum, url, checksums_to_upload) lambda do # Checksum is the hexadecimal representation of the md5, # but we need the base64 encoding for the content-md5 # header checksum64 = Base64.encode64([checksum].pack("H*")).strip = Time.now.utc.iso8601 file_contents = File.open(file, "rb") {|f| f.read} # TODO - 5/28/2010, cw: make signing and sending the request streaming sign_obj = Mixlib::Authentication::SignedHeaderAuth.signing_object( :http_method => :put, :path => URI.parse(url).path, :body => file_contents, :timestamp => , :user_id => rest.client_name ) headers = { 'content-type' => 'application/x-binary', 'content-md5' => checksum64, :accept => 'application/json' } headers.merge!(sign_obj.sign(OpenSSL::PKey::RSA.new(rest.signing_key))) begin RestClient::Resource.new(url, :headers=>headers, :timeout=>1800, :open_timeout=>1800).put(file_contents) checksums_to_upload.delete(checksum) rescue RestClient::Exception => e Chef::Knife.ui.error("Failed to upload #@cookbook : #{e.}\n#{e.response.body}") raise end end end |
#validate_cookbook ⇒ Object
143 144 145 146 147 148 149 150 151 |
# File 'lib/chef/cookbook_uploader.rb', line 143 def validate_cookbook syntax_checker = Chef::Cookbook::SyntaxCheck.for_cookbook(cookbook.name, @user_cookbook_path) Chef::Log.info("Validating ruby files") exit(1) unless syntax_checker.validate_ruby_files Chef::Log.info("Validating templates") exit(1) unless syntax_checker.validate_templates Chef::Log.info("Syntax OK") true end |
#worker_thread(work_queue) ⇒ Object
111 112 |
# File 'lib/chef/cookbook_uploader.rb', line 111 def worker_thread(work_queue) end |