diff options
author | John Keiser <john@johnkeiser.com> | 2015-08-07 14:19:39 -0700 |
---|---|---|
committer | John Keiser <john@johnkeiser.com> | 2015-08-07 14:19:39 -0700 |
commit | 3a5e1819c4439836767a001182c1e19de1cfb7e9 (patch) | |
tree | 3459b03bc138449838da95ab937ae533caac39f8 | |
parent | 4a3ede96a443a99748b2092e8c58d40ff8b2e104 (diff) | |
parent | a517fa8a3b0448e673f1645cdbcd83945b8d9b6d (diff) | |
download | chef-3a5e1819c4439836767a001182c1e19de1cfb7e9.tar.gz |
Merge branch 'jk/fs_children'
20 files changed, 89 insertions, 110 deletions
diff --git a/lib/chef/chef_fs/file_system/acl_dir.rb b/lib/chef/chef_fs/file_system/acl_dir.rb index c2354d478d..9f68d7cda7 100644 --- a/lib/chef/chef_fs/file_system/acl_dir.rb +++ b/lib/chef/chef_fs/file_system/acl_dir.rb @@ -28,10 +28,9 @@ class Chef parent.parent.child(name).api_path end - def child(name) + def make_child_entry(name, exists = nil) result = @children.select { |child| child.name == name }.first if @children - result ||= can_have_child?(name, false) ? - AclEntry.new(name, self) : NonexistentFSObject.new(name, self) + result || AclEntry.new(name, self, exists) end def can_have_child?(name, is_dir) @@ -42,7 +41,7 @@ class Chef if @children.nil? # Grab the ACTUAL children (/nodes, /containers, etc.) and get their names names = parent.parent.child(name).children.map { |child| child.dir? ? "#{child.name}.json" : child.name } - @children = names.map { |name| AclEntry.new(name, self, true) } + @children = names.map { |name| make_child_entry(name, true) } end @children end diff --git a/lib/chef/chef_fs/file_system/acls_dir.rb b/lib/chef/chef_fs/file_system/acls_dir.rb index 938bf73fb2..a8c63726b7 100644 --- a/lib/chef/chef_fs/file_system/acls_dir.rb +++ b/lib/chef/chef_fs/file_system/acls_dir.rb @@ -40,8 +40,12 @@ class Chef parent.api_path end + def make_child_entry(name) + children.select { |child| child.name == name }.first + end + def can_have_child?(name, is_dir) - is_dir ? ENTITY_TYPES.include(name) : name == 'organization.json' + is_dir ? ENTITY_TYPES.include?(name) : name == 'organization.json' end def children diff --git a/lib/chef/chef_fs/file_system/base_fs_dir.rb b/lib/chef/chef_fs/file_system/base_fs_dir.rb index 8cc277facc..47e33f961a 100644 --- a/lib/chef/chef_fs/file_system/base_fs_dir.rb +++ b/lib/chef/chef_fs/file_system/base_fs_dir.rb @@ -31,11 +31,6 @@ class Chef true end - # Override child(name) to provide a child object by name without the network read - def child(name) - children.select { |child| child.name == name }.first || NonexistentFSObject.new(name, self) - end - def can_have_child?(name, is_dir) true end diff --git a/lib/chef/chef_fs/file_system/base_fs_object.rb b/lib/chef/chef_fs/file_system/base_fs_object.rb index 43e6a513d7..916ab8297d 100644 --- a/lib/chef/chef_fs/file_system/base_fs_object.rb +++ b/lib/chef/chef_fs/file_system/base_fs_object.rb @@ -95,7 +95,10 @@ class Chef # directly perform a network request to retrieve the y.json data bag. No # network request was necessary to retrieve def child(name) - NonexistentFSObject.new(name, self) + if can_have_child?(name, true) || can_have_child?(name, false) + result = make_child_entry(name) + end + result || NonexistentFSObject.new(name, self) end # Override children to report your *actual* list of children as an array. @@ -171,7 +174,7 @@ class Chef # Important directory attributes: name, parent, path, root # Overridable attributes: dir?, child(name), path_for_printing - # Abstract: read, write, delete, children, can_have_child?, create_child, compare_to + # Abstract: read, write, delete, children, can_have_child?, create_child, compare_to, make_child_entry end # class BaseFsObject end end diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir.rb index a7f1d733b1..4391bdbfcd 100644 --- a/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir.rb @@ -58,14 +58,7 @@ class Chef end def children - begin - Dir.entries(file_path).sort. - select { |child_name| can_have_child?(child_name, File.directory?(File.join(file_path, child_name))) }. - map { |child_name| make_child(child_name) }. - select { |entry| !(entry.dir? && entry.children.size == 0) } - rescue Errno::ENOENT - raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) - end + super.select { |entry| !(entry.dir? && entry.children.size == 0 ) } end def can_have_child?(name, is_dir) @@ -99,7 +92,7 @@ class Chef protected - def make_child(child_name) + def make_child_entry(child_name) segment_info = CookbookDir::COOKBOOK_SEGMENT_INFO[child_name.to_sym] || {} ChefRepositoryFileSystemCookbookEntry.new(child_name, self, nil, segment_info[:ruby_only], segment_info[:recursive]) end diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_entry.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_entry.rb index 66709ccf68..914412f839 100644 --- a/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_entry.rb +++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_entry.rb @@ -34,14 +34,7 @@ class Chef attr_reader :recursive def children - begin - Dir.entries(file_path).sort. - select { |child_name| can_have_child?(child_name, File.directory?(File.join(file_path, child_name))) }. - map { |child_name| make_child(child_name) }. - select { |entry| !(entry.dir? && entry.children.size == 0) } - rescue Errno::ENOENT - raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) - end + super.select { |entry| !(entry.dir? && entry.children.size == 0 ) } end def can_have_child?(name, is_dir) @@ -78,7 +71,7 @@ class Chef protected - def make_child(child_name) + def make_child_entry(child_name) ChefRepositoryFileSystemCookbookEntry.new(child_name, self, nil, ruby_only, recursive) end end diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb index 7c60b51114..5b495666c3 100644 --- a/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb @@ -37,21 +37,14 @@ class Chef attr_reader :chefignore def children - begin - Dir.entries(file_path).sort. - select { |child_name| can_have_child?(child_name, File.directory?(File.join(file_path, child_name))) }. - map { |child_name| make_child(child_name) }. - select do |entry| - # empty cookbooks and cookbook directories are ignored - if !entry.can_upload? - Chef::Log.warn("Cookbook '#{entry.name}' is empty or entirely chefignored at #{entry.path_for_printing}") - false - else - true - end - end - rescue Errno::ENOENT - raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) + super.select do |entry| + # empty cookbooks and cookbook directories are ignored + if !entry.can_upload? + Chef::Log.warn("Cookbook '#{entry.name}' is empty or entirely chefignored at #{entry.path_for_printing}") + false + else + true + end end end @@ -61,7 +54,7 @@ class Chef def write_cookbook(cookbook_path, cookbook_version_json, from_fs) cookbook_name = File.basename(cookbook_path) - child = make_child(cookbook_name) + child = make_child_entry(cookbook_name) # Use the copy/diff algorithm to copy it down so we don't destroy # chefignored data. This is terribly un-thread-safe. @@ -80,7 +73,7 @@ class Chef protected - def make_child(child_name) + def make_child_entry(child_name) ChefRepositoryFileSystemCookbookDir.new(child_name, self) end end diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb index 0b14750744..39172e7ab9 100644 --- a/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb +++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb @@ -70,20 +70,9 @@ class Chef Chef::JSONCompat.to_json_pretty(object) end - def children - # Except cookbooks and data bag dirs, all things must be json files - begin - Dir.entries(file_path).sort. - select { |child_name| can_have_child?(child_name, File.directory?(File.join(file_path, child_name))) }. - map { |child_name| make_child(child_name) } - rescue Errno::ENOENT - raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) - end - end - protected - def make_child(child_name) + def make_child_entry(child_name) ChefRepositoryFileSystemEntry.new(child_name, self) end end diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb index d03baf91fe..267fe30456 100644 --- a/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb @@ -68,13 +68,13 @@ class Chef attr_reader :child_paths attr_reader :versioned_cookbooks - CHILDREN = %w(invitations.json members.json org.json) + CHILDREN = %w(org.json invitations.json members.json) def children @children ||= begin - result = child_paths.keys.sort.map { |name| make_child_entry(name) }.select { |child| !child.nil? } - result += root_dir.children.select { |c| CHILDREN.include?(c.name) } if root_dir - result.sort_by { |c| c.name } + result = child_paths.keys.sort.map { |name| make_child_entry(name) } + result += CHILDREN.map { |name| make_child_entry(name) } + result.select { |c| c && c.exists? }.sort_by { |c| c.name } end end @@ -149,19 +149,23 @@ class Chef # cookbooks from all of them when you list or grab them). # def make_child_entry(name) - paths = child_paths[name].select do |path| - File.exists?(path) + if CHILDREN.include?(name) + return nil if !root_dir + return root_dir.child(name) end + + paths = (child_paths[name] || []).select { |path| File.exists?(path) } if paths.size == 0 - return nil + return NonexistentFSObject.new(name, self) end - if name == 'cookbooks' + case name + when 'cookbooks' dirs = paths.map { |path| ChefRepositoryFileSystemCookbooksDir.new(name, self, path) } - elsif name == 'data_bags' + when 'data_bags' dirs = paths.map { |path| ChefRepositoryFileSystemDataBagsDir.new(name, self, path) } - elsif name == 'policies' + when 'policies' dirs = paths.map { |path| ChefRepositoryFileSystemPoliciesDir.new(name, self, path) } - elsif name == 'acls' + when 'acls' dirs = paths.map { |path| ChefRepositoryFileSystemAclsDir.new(name, self, path) } else data_handler = case name diff --git a/lib/chef/chef_fs/file_system/chef_server_root_dir.rb b/lib/chef/chef_fs/file_system/chef_server_root_dir.rb index 824325f31b..e3ffd644ad 100644 --- a/lib/chef/chef_fs/file_system/chef_server_root_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server_root_dir.rb @@ -110,7 +110,8 @@ class Chef end def can_have_child?(name, is_dir) - is_dir && children.any? { |child| child.name == name } + result = children.select { |child| child.name == name }.first + result && !!result.dir? == !!is_dir end def org @@ -124,6 +125,10 @@ class Chef end end + def make_child_entry(name) + children.select { |child| child.name == name }.first + end + def children @children ||= begin result = [ diff --git a/lib/chef/chef_fs/file_system/cookbook_dir.rb b/lib/chef/chef_fs/file_system/cookbook_dir.rb index 555f9aef0a..c0f0390e98 100644 --- a/lib/chef/chef_fs/file_system/cookbook_dir.rb +++ b/lib/chef/chef_fs/file_system/cookbook_dir.rb @@ -72,16 +72,15 @@ class Chef "#{parent.api_path}/#{cookbook_name}/#{version || "_latest"}" end - def child(name) + def make_child_entry(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 + children.select { |child| child.name == name }.first rescue Chef::ChefFS::FileSystem::NotFoundError + nil end - return NonexistentFSObject.new(name, self) end def can_have_child?(name, is_dir) diff --git a/lib/chef/chef_fs/file_system/cookbooks_acl_dir.rb b/lib/chef/chef_fs/file_system/cookbooks_acl_dir.rb index d6246f1e60..560ceb4886 100644 --- a/lib/chef/chef_fs/file_system/cookbooks_acl_dir.rb +++ b/lib/chef/chef_fs/file_system/cookbooks_acl_dir.rb @@ -31,7 +31,7 @@ class Chef def children if @children.nil? names = parent.parent.child(name).children.map { |child| "#{child.cookbook_name}.json" } - @children = names.uniq.map { |name| AclEntry.new(name, self, true) } + @children = names.uniq.map { |name| make_child_entry(name, true) } end @children end diff --git a/lib/chef/chef_fs/file_system/cookbooks_dir.rb b/lib/chef/chef_fs/file_system/cookbooks_dir.rb index 27bedd3827..6f49c28996 100644 --- a/lib/chef/chef_fs/file_system/cookbooks_dir.rb +++ b/lib/chef/chef_fs/file_system/cookbooks_dir.rb @@ -36,17 +36,9 @@ class Chef super("cookbooks", parent) end - 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 + def make_child_entry(name) + result = @children.select { |child| child.name == name }.first if @children + result || CookbookDir.new(name, self) end def children diff --git a/lib/chef/chef_fs/file_system/data_bags_dir.rb b/lib/chef/chef_fs/file_system/data_bags_dir.rb index 6d0685d3b7..1cb61bbd1a 100644 --- a/lib/chef/chef_fs/file_system/data_bags_dir.rb +++ b/lib/chef/chef_fs/file_system/data_bags_dir.rb @@ -27,16 +27,14 @@ class Chef super("data_bags", parent, "data") end - def child(name) + def make_child_entry(name, exists = false) result = @children.select { |child| child.name == name }.first if @children - result || DataBagDir.new(name, self) + result || DataBagDir.new(name, self, exists) end def children begin - @children ||= root.get_json(api_path).keys.sort.map do |entry| - DataBagDir.new(entry, self, true) - end + @children ||= root.get_json(api_path).keys.sort.map { |entry| make_child_entry(entry, true) } rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e), "Timeout getting children: #{e}" rescue Net::HTTPServerException => e diff --git a/lib/chef/chef_fs/file_system/environments_dir.rb b/lib/chef/chef_fs/file_system/environments_dir.rb index 559dd6af86..3aee3ee5af 100644 --- a/lib/chef/chef_fs/file_system/environments_dir.rb +++ b/lib/chef/chef_fs/file_system/environments_dir.rb @@ -30,7 +30,7 @@ class Chef super("environments", parent, nil, Chef::ChefFS::DataHandler::EnvironmentDataHandler.new) end - def _make_child_entry(name, exists = nil) + def make_child_entry(name, exists = nil) if name == '_default.json' DefaultEnvironmentEntry.new(name, self, exists) else diff --git a/lib/chef/chef_fs/file_system/file_system_entry.rb b/lib/chef/chef_fs/file_system/file_system_entry.rb index 1af7e618de..8611aa2e0f 100644 --- a/lib/chef/chef_fs/file_system/file_system_entry.rb +++ b/lib/chef/chef_fs/file_system/file_system_entry.rb @@ -40,15 +40,18 @@ class Chef end def children + # Except cookbooks and data bag dirs, all things must be json files begin - Dir.entries(file_path).sort.select { |entry| entry != '.' && entry != '..' }.map { |entry| make_child(entry) } + Dir.entries(file_path).sort. + map { |child_name| make_child_entry(child_name) }. + select { |child| child && can_have_child?(child.name, child.dir?) } rescue Errno::ENOENT raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) end end def create_child(child_name, file_contents=nil) - child = make_child(child_name) + child = make_child_entry(child_name) if child.exists? raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, child) end @@ -80,7 +83,7 @@ class Chef end def exists? - File.exists?(file_path) + File.exists?(file_path) && parent.can_have_child?(name, dir?) end def read @@ -99,7 +102,7 @@ class Chef protected - def make_child(child_name) + def make_child_entry(child_name) FileSystemEntry.new(child_name, self) end end diff --git a/lib/chef/chef_fs/file_system/memory_dir.rb b/lib/chef/chef_fs/file_system/memory_dir.rb index a7eda3c654..260a91693c 100644 --- a/lib/chef/chef_fs/file_system/memory_dir.rb +++ b/lib/chef/chef_fs/file_system/memory_dir.rb @@ -1,5 +1,4 @@ require 'chef/chef_fs/file_system/base_fs_dir' -require 'chef/chef_fs/file_system/nonexistent_fs_object' require 'chef/chef_fs/file_system/memory_file' class Chef @@ -13,8 +12,8 @@ class Chef attr_reader :children - def child(name) - @children.select { |child| child.name == name }.first || Chef::ChefFS::FileSystem::NonexistentFSObject.new(name, self) + def make_child_entry(name) + @children.select { |child| child.name == name }.first end def add_child(child) diff --git a/lib/chef/chef_fs/file_system/multiplexed_dir.rb b/lib/chef/chef_fs/file_system/multiplexed_dir.rb index 06d4af705d..70b827f85f 100644 --- a/lib/chef/chef_fs/file_system/multiplexed_dir.rb +++ b/lib/chef/chef_fs/file_system/multiplexed_dir.rb @@ -35,6 +35,21 @@ class Chef end end + def make_child_entry(name) + result = nil + multiplexed_dirs.each do |dir| + child_entry = dir.child(name) + if child_entry.exists? + if result + Chef::Log.warn("Child with name '#{child_entry.name}' found in multiple directories: #{result.parent.path_for_printing} and #{child_entry.parent.path_for_printing}") + else + result = child_entry + end + end + end + result + end + def can_have_child?(name, is_dir) write_dir.can_have_child?(name, is_dir) end diff --git a/lib/chef/chef_fs/file_system/nodes_dir.rb b/lib/chef/chef_fs/file_system/nodes_dir.rb index c3c48377cd..2610b06a82 100644 --- a/lib/chef/chef_fs/file_system/nodes_dir.rb +++ b/lib/chef/chef_fs/file_system/nodes_dir.rb @@ -33,7 +33,7 @@ class Chef def children begin @children ||= root.get_json(env_api_path).keys.sort.map do |key| - _make_child_entry("#{key}.json", true) + make_child_entry("#{key}.json", true) end rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e), "Timeout retrieving children: #{e}" diff --git a/lib/chef/chef_fs/file_system/rest_list_dir.rb b/lib/chef/chef_fs/file_system/rest_list_dir.rb index 672fa444f1..0ac735a2c4 100644 --- a/lib/chef/chef_fs/file_system/rest_list_dir.rb +++ b/lib/chef/chef_fs/file_system/rest_list_dir.rb @@ -33,12 +33,6 @@ class Chef attr_reader :api_path attr_reader :data_handler - def child(name) - result = @children.select { |child| child.name == name }.first if @children - result ||= can_have_child?(name, false) ? - _make_child_entry(name) : NonexistentFSObject.new(name, self) - end - def can_have_child?(name, is_dir) name =~ /\.json$/ && !is_dir end @@ -46,7 +40,7 @@ class Chef def children begin @children ||= root.get_json(api_path).keys.sort.map do |key| - _make_child_entry("#{key}.json", true) + make_child_entry("#{key}.json", true) end rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e), "Timeout retrieving children: #{e}" @@ -66,7 +60,7 @@ class Chef raise Chef::ChefFS::FileSystem::OperationFailedError.new(:create_child, self, e), "Parse error reading JSON creating child '#{name}': #{e}" end - result = _make_child_entry(name, true) + result = make_child_entry(name, true) if data_handler object = data_handler.normalize_for_post(object, result) @@ -106,7 +100,8 @@ class Chef parent.rest end - def _make_child_entry(name, exists = nil) + def make_child_entry(name, exists = nil) + @children.select { |child| child.name == name }.first if @children RestListEntry.new(name, self, exists) end end |