class Chef::Knife::CookbookUpload

Constants

CHECKSUM
MATCH_CHECKSUM

Public Instance Methods

cookbook_repo() click to toggle source
# File lib/chef/knife/cookbook_upload.rb, line 185
def cookbook_repo
  @cookbook_loader ||= begin
    Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, config[:cookbook_path]) }
    Chef::CookbookLoader.new(config[:cookbook_path])
  end
end
cookbooks_to_upload() click to toggle source
# File lib/chef/knife/cookbook_upload.rb, line 162
def cookbooks_to_upload
  @cookbooks_to_upload ||=
    if config[:all]
      cookbook_repo.load_cookbooks
    else
      upload_set = {}
      @name_args.each do |cookbook_name|
        begin
          if ! upload_set.has_key?(cookbook_name)
            upload_set[cookbook_name] = cookbook_repo[cookbook_name]
            if config[:depends]
              upload_set[cookbook_name].metadata.dependencies.each { |dep, ver| @name_args << dep }
            end
          end
        rescue Exceptions::CookbookNotFoundInRepo => e
          ui.error("Could not find cookbook #{cookbook_name} in your cookbook path, skipping it")
          Log.debug(e)
        end
      end
      upload_set
    end
end
environment() click to toggle source
# File lib/chef/knife/cookbook_upload.rb, line 199
def environment
  @environment ||= config[:environment] ? Environment.load(config[:environment]) : nil
end
run() click to toggle source
# File lib/chef/knife/cookbook_upload.rb, line 77
def run
  # Sanity check before we load anything from the server
  unless config[:all]
    if @name_args.empty?
      show_usage
      ui.fatal("You must specify the --all flag or at least one cookbook name")
      exit 1
    end
  end

  config[:cookbook_path] ||= Chef::Config[:cookbook_path]

  if @name_args.empty? and ! config[:all]
    show_usage
    ui.fatal("You must specify the --all flag or at least one cookbook name")
    exit 1
  end

  assert_environment_valid!
  warn_about_cookbook_shadowing
  version_constraints_to_update = {}
  upload_failures = 0
  upload_ok = 0

  # Get a list of cookbooks and their versions from the server
  # to check for the existence of a cookbook's dependencies.
  @server_side_cookbooks = Chef::CookbookVersion.list_all_versions
  justify_width = @server_side_cookbooks.map {|name| name.size}.max.to_i + 2
  if config[:all]
    cookbook_repo.load_cookbooks
    cbs = []
    cookbook_repo.each do |cookbook_name, cookbook|
      cbs << cookbook
      cookbook.freeze_version if config[:freeze]
      version_constraints_to_update[cookbook_name] = cookbook.version
    end
    begin
      upload(cbs, justify_width)
    rescue Exceptions::CookbookFrozen
      ui.warn("Not updating version constraints for some cookbooks in the environment as the cookbook is frozen.")
    end
    ui.info("Uploaded all cookbooks.")
  else
    if @name_args.empty?
      show_usage
      ui.error("You must specify the --all flag or at least one cookbook name")
      exit 1
    end

    cookbooks_to_upload.each do |cookbook_name, cookbook|
      cookbook.freeze_version if config[:freeze]
      begin
        upload([cookbook], justify_width)
        upload_ok += 1
        version_constraints_to_update[cookbook_name] = cookbook.version
      rescue Exceptions::CookbookNotFoundInRepo => e
        upload_failures += 1
        ui.error("Could not find cookbook #{cookbook_name} in your cookbook path, skipping it")
        Log.debug(e)
        upload_failures += 1
      rescue Exceptions::CookbookFrozen
        ui.warn("Not updating version constraints for #{cookbook_name} in the environment as the cookbook is frozen.")
        upload_failures += 1
      end
    end


    upload_failures += @name_args.length - @cookbooks_to_upload.length

    if upload_failures == 0
      ui.info "Uploaded #{upload_ok} cookbook#{upload_ok > 1 ? "s" : ""}."
    elsif upload_failures > 0 && upload_ok > 0
      ui.warn "Uploaded #{upload_ok} cookbook#{upload_ok > 1 ? "s" : ""} ok but #{upload_failures} " +
        "cookbook#{upload_failures > 1 ? "s" : ""} upload failed."
    elsif upload_failures > 0 && upload_ok == 0
      ui.error "Failed to upload #{upload_failures} cookbook#{upload_failures > 1 ? "s" : ""}."
      exit 1
    end
  end

  unless version_constraints_to_update.empty?
    update_version_constraints(version_constraints_to_update) if config[:environment]
  end
end
update_version_constraints(new_version_constraints) click to toggle source
# File lib/chef/knife/cookbook_upload.rb, line 192
def update_version_constraints(new_version_constraints)
  new_version_constraints.each do |cookbook_name, version|
    environment.cookbook_versions[cookbook_name] = "= #{version}"
  end
  environment.save
end
warn_about_cookbook_shadowing() click to toggle source
# File lib/chef/knife/cookbook_upload.rb, line 203
      def warn_about_cookbook_shadowing
        # because cookbooks are lazy-loaded, we have to force the loader
        # to load the cookbooks the user intends to upload here:
        cookbooks_to_upload
        
        unless cookbook_repo.merged_cookbooks.empty?
          ui.warn "* " * 40
          ui.warn("The cookbooks: #{cookbook_repo.merged_cookbooks.join(', ')} exist in multiple places in your cookbook_path.
A composite version of these cookbooks has been compiled for uploading.

#{ui.color('IMPORTANT:', :red, :bold)} In a future version of Chef, this behavior will be removed and you will no longer
be able to have the same version of a cookbook in multiple places in your cookbook_path.
")
          ui.warn "The affected cookbooks are located:"
          ui.output ui.format_for_display(cookbook_repo.merged_cookbook_paths)
          ui.warn "* " * 40
        end
      end

Private Instance Methods

assert_environment_valid!() click to toggle source
# File lib/chef/knife/cookbook_upload.rb, line 225
def assert_environment_valid!
  environment
rescue Net::HTTPServerException => e
  if e.response.code.to_s == "404"
    ui.error "The environment #{config[:environment]} does not exist on the server, aborting."
    Log.debug(e)
    exit 1
  else
    raise
  end
end
check_for_dependencies!(cookbook) click to toggle source
# File lib/chef/knife/cookbook_upload.rb, line 265
def check_for_dependencies!(cookbook)
  # for all dependencies, check if the version is on the server, or
  # the version is in the cookbooks being uploaded. If not, exit and warn the user.
  missing_dependencies = cookbook.metadata.dependencies.reject do |cookbook_name, version|
    check_server_side_cookbooks(cookbook_name, version) || check_uploading_cookbooks(cookbook_name, version)
  end

  unless missing_dependencies.empty?
    missing_cookbook_names = missing_dependencies.map { |cookbook_name, version|  "'#{cookbook_name}' version '#{version}'"}
    ui.error "Cookbook #{cookbook.name} depends on cookbooks which are not currently"
    ui.error "being uploaded and cannot be found on the server."
    ui.error "The missing cookbook(s) are: #{missing_cookbook_names.join(', ')}"
    exit 1
  end
end
check_server_side_cookbooks(cookbook_name, version) click to toggle source
# File lib/chef/knife/cookbook_upload.rb, line 281
def check_server_side_cookbooks(cookbook_name, version)
  if @server_side_cookbooks[cookbook_name].nil?
    false
  else
    versions = @server_side_cookbooks[cookbook_name]['versions'].collect {|versions| versions["version"]}
    Log.debug "Versions of cookbook '#{cookbook_name}' returned by the server: #{versions.join(", ")}"
    @server_side_cookbooks[cookbook_name]["versions"].each do |versions_hash|
      if Chef::VersionConstraint.new(version).include?(versions_hash["version"])
        Log.debug "Matched cookbook '#{cookbook_name}' with constraint '#{version}' to cookbook version '#{versions_hash['version']}' on the server"
        return true
      end
    end
    false
  end
end
check_uploading_cookbooks(cookbook_name, version) click to toggle source
# File lib/chef/knife/cookbook_upload.rb, line 297
def check_uploading_cookbooks(cookbook_name, version)
  if (! cookbooks_to_upload[cookbook_name].nil?) && Chef::VersionConstraint.new(version).include?(cookbooks_to_upload[cookbook_name].version)
    Log.debug "Matched cookbook '#{cookbook_name}' with constraint '#{version}' to a local cookbook."
    return true
  end
  false
end
upload(cookbooks, justify_width) click to toggle source
# File lib/chef/knife/cookbook_upload.rb, line 237
def upload(cookbooks, justify_width)
  cookbooks.each do |cb|
    ui.info("Uploading #{cb.name.to_s.ljust(justify_width + 10)} [#{cb.version}]")
    check_for_broken_links!(cb)
    check_for_dependencies!(cb)
  end
  Chef::CookbookUploader.new(cookbooks, config[:cookbook_path], :force => config[:force], :concurrency => config[:concurrency]).upload_cookbooks
rescue Chef::Exceptions::CookbookFrozen => e
  ui.error e
  raise
end