diff options
author | Seth Chisamore <schisamo@opscode.com> | 2012-10-30 10:39:35 -0400 |
---|---|---|
committer | Seth Chisamore <schisamo@opscode.com> | 2012-10-30 10:39:35 -0400 |
commit | 24dc69a9a97e82a6e4207de68d6dcc664178249b (patch) | |
tree | 19bb289c9f88b4bbab066bc56b95d6d222fd5c35 /lib/chef/chef_fs/file_system/cookbook_dir.rb | |
parent | 9348c1c9c80ee757354d624b7dc1b78ebc7605c4 (diff) | |
download | chef-24dc69a9a97e82a6e4207de68d6dcc664178249b.tar.gz |
[OC-3564] move core Chef to the repo root \o/ \m/
The opscode/chef repository now only contains the core Chef library code
used by chef-client, knife and chef-solo!
Diffstat (limited to 'lib/chef/chef_fs/file_system/cookbook_dir.rb')
-rw-r--r-- | lib/chef/chef_fs/file_system/cookbook_dir.rb | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/lib/chef/chef_fs/file_system/cookbook_dir.rb b/lib/chef/chef_fs/file_system/cookbook_dir.rb new file mode 100644 index 0000000000..e87d5dd49d --- /dev/null +++ b/lib/chef/chef_fs/file_system/cookbook_dir.rb @@ -0,0 +1,188 @@ +# +# Author:: John Keiser (<jkeiser@opscode.com>) +# Copyright:: Copyright (c) 2012 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/chef_fs/file_system/rest_list_dir' +require 'chef/chef_fs/file_system/cookbook_subdir' +require 'chef/chef_fs/file_system/cookbook_file' +require 'chef/chef_fs/file_system/not_found_error' +require 'chef/cookbook_version' +require 'chef/cookbook_uploader' + +class Chef + module ChefFS + module FileSystem + class CookbookDir < BaseFSDir + def initialize(name, parent, versions = nil) + super(name, parent) + @versions = versions + end + + attr_reader :versions + + COOKBOOK_SEGMENT_INFO = { + :attributes => { :ruby_only => true }, + :definitions => { :ruby_only => true }, + :recipes => { :ruby_only => true }, + :libraries => { :ruby_only => true }, + :templates => { :recursive => true }, + :files => { :recursive => true }, + :resources => { :ruby_only => true, :recursive => true }, + :providers => { :ruby_only => true, :recursive => true }, + :root_files => { } + } + + def add_child(child) + @children << child + end + + def api_path + "#{parent.api_path}/#{name}/_latest" + end + + def child(name) + # Since we're ignoring the rules and doing a network request here, + # we need to make sure we don't rethrow the exception. (child(name) + # is not supposed to fail.) + begin + result = children.select { |child| child.name == name }.first + return result if result + rescue Chef::ChefFS::FileSystem::NotFoundError + end + return NonexistentFSObject.new(name, self) + end + + def can_have_child?(name, is_dir) + # A cookbook's root may not have directories unless they are segment directories + if is_dir + return name != 'root_files' && + COOKBOOK_SEGMENT_INFO.keys.any? { |segment| segment.to_s == name } + end + true + end + + def children + if @children.nil? + @children = [] + manifest = chef_object.manifest + COOKBOOK_SEGMENT_INFO.each do |segment, segment_info| + next unless manifest.has_key?(segment) + + # Go through each file in the manifest for the segment, and + # add cookbook subdirs and files for it. + manifest[segment].each do |segment_file| + parts = segment_file[:path].split('/') + # Get or create the path to the file + container = self + parts[0,parts.length-1].each do |part| + old_container = container + container = old_container.children.select { |child| part == child.name }.first + if !container + container = CookbookSubdir.new(part, old_container, segment_info[:ruby_only], segment_info[:recursive]) + old_container.add_child(container) + end + end + # Create the file itself + container.add_child(CookbookFile.new(parts[parts.length-1], container, segment_file)) + end + end + end + @children + end + + def dir? + exists? + end + + def read + # This will only be called if dir? is false, which means exists? is false. + raise Chef::ChefFS::FileSystem::NotFoundError, path_for_printing + end + + def exists? + if !@versions + child = parent.children.select { |child| child.name == name }.first + @versions = child.versions if child + end + !!@versions + end + + def compare_to(other) + if !other.dir? + return [ !exists?, nil, nil ] + end + are_same = true + Chef::ChefFS::CommandLine::diff_entries(self, other, nil, :name_only) do + are_same = false + end + [ are_same, nil, nil ] + end + + def copy_from(other) + parent.upload_cookbook_from(other) + end + + def rest + parent.rest + end + + def chef_object + # We cheat and cache here, because it seems like a good idea to keep + # the cookbook view consistent with the directory structure. + return @chef_object if @chef_object + + # The negative (not found) response is cached + if @could_not_get_chef_object + raise Chef::ChefFS::FileSystem::NotFoundError.new(@could_not_get_chef_object), "#{path_for_printing} not found" + end + + begin + # We want to fail fast, for now, because of the 500 issue :/ + # This will make things worse for parallelism, a little, because + # Chef::Config is global and this could affect other requests while + # this request is going on. (We're not parallel yet, but we will be.) + # Chef bug http://tickets.opscode.com/browse/CHEF-3066 + old_retry_count = Chef::Config[:http_retry_count] + begin + Chef::Config[:http_retry_count] = 0 + @chef_object ||= rest.get_rest(api_path) + ensure + Chef::Config[:http_retry_count] = old_retry_count + end + rescue Net::HTTPServerException + if $!.response.code == "404" + @could_not_get_chef_object = $! + raise Chef::ChefFS::FileSystem::NotFoundError.new(@could_not_get_chef_object), "#{path_for_printing} not found" + else + raise + end + + # Chef bug http://tickets.opscode.com/browse/CHEF-3066 ... instead of 404 we get 500 right now. + # Remove this when that bug is fixed. + rescue Net::HTTPFatalError + if $!.response.code == "500" + @could_not_get_chef_object = $! + raise Chef::ChefFS::FileSystem::NotFoundError.new(@could_not_get_chef_object), "#{path_for_printing} not found" + else + raise + end + end + end + end + end + end +end |