Class: Chef::CookbookUploader
Instance Attribute Summary collapse
-
#cookbooks ⇒ Object
readonly
Returns the value of attribute cookbooks.
-
#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(cookbooks, path, opts = {}) ⇒ CookbookUploader
constructor
Creates a new CookbookUploader.
- #upload_cookbooks ⇒ Object
- #uploader_function_for(file, checksum, url, checksums_to_upload) ⇒ Object
- #validate_cookbooks ⇒ Object
- #worker_thread(work_queue) ⇒ Object
Constructor Details
#initialize(cookbooks, path, opts = {}) ⇒ CookbookUploader
Creates a new CookbookUploader.
Arguments:
- cookbooks:
-
A Chef::CookbookVersion or array of them describing the cookbook(s) 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.
52 53 54 55 56 |
# File 'lib/chef/cookbook_uploader.rb', line 52 def initialize(cookbooks, path, opts={}) @path, @opts = path, opts @cookbooks = Array(cookbooks) @rest = opts[:rest] || Chef::REST.new(Chef::Config[:chef_server_url]) end |
Instance Attribute Details
#cookbooks ⇒ Object (readonly)
Returns the value of attribute cookbooks.
32 33 34 |
# File 'lib/chef/cookbook_uploader.rb', line 32 def cookbooks @cookbooks 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_cookbooks ⇒ Object
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 110 111 112 113 114 115 116 117 |
# File 'lib/chef/cookbook_uploader.rb', line 58 def upload_cookbooks Thread.abort_on_exception = true # Syntax Check validate_cookbooks # generate checksums of cookbook files and create a sandbox checksum_files = {} cookbooks.each do |cb| Chef::Log.info("Saving #{cb.name}") checksum_files.merge!(cb.checksums) end 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 cookbooks.each do |cb| save_url = opts[:force] ? cb.force_save_url : cb.save_url rest.put_rest(save_url, cb) end Chef::Log.info("Upload complete!") end |
#uploader_function_for(file, checksum, url, checksums_to_upload) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/chef/cookbook_uploader.rb', line 122 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_cookbooks ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/chef/cookbook_uploader.rb', line 151 def validate_cookbooks cookbooks.each do |cb| syntax_checker = Chef::Cookbook::SyntaxCheck.for_cookbook(cb.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 end |
#worker_thread(work_queue) ⇒ Object
119 120 |
# File 'lib/chef/cookbook_uploader.rb', line 119 def worker_thread(work_queue) end |