Class: Chef::ChefFS::FileSystem::CookbooksDir

Inherits:
RestListDir show all
Defined in:
lib/chef/chef_fs/file_system/cookbooks_dir.rb

Instance Attribute Summary

Attributes inherited from RestListDir

#api_path, #data_handler

Attributes inherited from BaseFSObject

#name, #parent, #path

Instance Method Summary collapse

Methods inherited from RestListDir

#_make_child_entry, #create_child, #environment, #org, #rest

Methods inherited from BaseFSDir

#dir?

Methods inherited from BaseFSObject

#chef_object, #compare_to, #create_child, #delete, #dir?, #exists?, #path_for_printing, #read, #root, #write

Constructor Details

#initialize(parent) ⇒ CookbooksDir

Returns a new instance of CookbooksDir.



32
33
34
# File 'lib/chef/chef_fs/file_system/cookbooks_dir.rb', line 32

def initialize(parent)
  super("cookbooks", parent)
end

Instance Method Details

#can_have_child?(name, is_dir) ⇒ Boolean

Returns:

  • (Boolean)


141
142
143
144
145
# File 'lib/chef/chef_fs/file_system/cookbooks_dir.rb', line 141

def can_have_child?(name, is_dir)
  return false if !is_dir
  return false if Chef::Config[:versioned_cookbooks] && name !~ Chef::ChefFS::FileSystem::CookbookDir::VALID_VERSIONED_COOKBOOK_NAME
  return true
end

#child(name) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/chef/chef_fs/file_system/cookbooks_dir.rb', line 36

def child(name)
  if @children
    result = self.children.select { |child| child.name == name }.first
    if result
      result
    else
      NonexistentFSObject.new(name, self)
    end
  else
    CookbookDir.new(name, self)
  end
end

#childrenObject



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/chef/chef_fs/file_system/cookbooks_dir.rb', line 49

def children
  @children ||= begin
    if Chef::Config[:versioned_cookbooks]
      result = []
      Chef::ChefFS::RawRequest.raw_json(rest, "#{api_path}/?num_versions=all").each_pair do |cookbook_name, cookbooks|
        cookbooks['versions'].each do |cookbook_version|
          result << CookbookDir.new("#{cookbook_name}-#{cookbook_version['version']}", self, :exists => true)
        end
      end
    else
      result = Chef::ChefFS::RawRequest.raw_json(rest, api_path).keys.map { |cookbook_name| CookbookDir.new(cookbook_name, self, :exists => true) }
    end
    result.sort_by(&:name)
  end
end

#create_child_from(other, options = {}) ⇒ Object



65
66
67
# File 'lib/chef/chef_fs/file_system/cookbooks_dir.rb', line 65

def create_child_from(other, options = {})
  upload_cookbook_from(other, options)
end

#upload_cookbook!(uploader, options = {}) ⇒ Object



133
134
135
136
137
138
139
# File 'lib/chef/chef_fs/file_system/cookbooks_dir.rb', line 133

def upload_cookbook!(uploader, options = {})
  if uploader.respond_to?(:upload_cookbook)
    uploader.upload_cookbook
  else
    uploader.upload_cookbooks
  end
end

#upload_cookbook_from(other, options = {}) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/chef/chef_fs/file_system/cookbooks_dir.rb', line 69

def upload_cookbook_from(other, options = {})
  Chef::Config[:versioned_cookbooks] ? upload_versioned_cookbook(other, options) : upload_unversioned_cookbook(other, options)
rescue Timeout::Error => e
  raise Chef::ChefFS::FileSystem::OperationFailedError.new(:write, self, e), "Timeout writing: #{e}"
rescue Net::HTTPServerException => e
  case e.response.code
  when "409"
    raise Chef::ChefFS::FileSystem::CookbookFrozenError.new(:write, self, e), "Cookbook #{other.name} is frozen"
  else
    raise Chef::ChefFS::FileSystem::OperationFailedError.new(:write, self, e), "HTTP error writing: #{e}"
  end
rescue Chef::Exceptions::CookbookFrozen => e
  raise Chef::ChefFS::FileSystem::CookbookFrozenError.new(:write, self, e), "Cookbook #{other.name} is frozen"
end

#upload_unversioned_cookbook(other, options) ⇒ Object



113
114
115
116
117
118
119
120
121
# File 'lib/chef/chef_fs/file_system/cookbooks_dir.rb', line 113

def upload_unversioned_cookbook(other, options)
  cookbook_to_upload = other.chef_object
  cookbook_to_upload.freeze_version if options[:freeze]
  uploader = Chef::CookbookUploader.new(cookbook_to_upload, other.parent.file_path, :force => options[:force], :rest => rest)

  with_actual_cookbooks_dir(other.parent.file_path) do
    upload_cookbook!(uploader)
  end
end

#upload_versioned_cookbook(other, options) ⇒ Object

Knife currently does not understand versioned cookbooks Cookbook Version uploader also requires a lot of refactoring to make this work. So instead, we make a temporary cookbook symlinking back to real cookbook, and upload the proxy.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/chef/chef_fs/file_system/cookbooks_dir.rb', line 88

def upload_versioned_cookbook(other, options)
  cookbook_name = Chef::ChefFS::FileSystem::ChefRepositoryFileSystemCookbookDir.canonical_cookbook_name(other.name)

  Dir.mktmpdir do |temp_cookbooks_path|
    proxy_cookbook_path = "#{temp_cookbooks_path}/#{cookbook_name}"

    # Make a symlink
    File.symlink other.file_path, proxy_cookbook_path

    # Instantiate a proxy loader using the temporary symlink
    proxy_loader = Chef::Cookbook::CookbookVersionLoader.new(proxy_cookbook_path, other.parent.chefignore)
    proxy_loader.load_cookbooks

    cookbook_to_upload = proxy_loader.cookbook_version
    cookbook_to_upload.freeze_version if options[:freeze]

    # Instantiate a new uploader based on the proxy loader
    uploader = Chef::CookbookUploader.new(cookbook_to_upload, proxy_cookbook_path, :force => options[:force], :rest => rest)

    with_actual_cookbooks_dir(temp_cookbooks_path) do
      upload_cookbook!(uploader)
    end
  end
end

#with_actual_cookbooks_dir(actual_cookbook_path) ⇒ Object

Work around the fact that CookbookUploader doesn’t understand chef_repo_path (yet)



124
125
126
127
128
129
130
131
# File 'lib/chef/chef_fs/file_system/cookbooks_dir.rb', line 124

def with_actual_cookbooks_dir(actual_cookbook_path)
  old_cookbook_path = Chef::Config.cookbook_path
  Chef::Config.cookbook_path = actual_cookbook_path if !Chef::Config.cookbook_path

  yield
ensure
  Chef::Config.cookbook_path = old_cookbook_path
end