diff options
author | Thom May <thom@may.lt> | 2016-04-21 08:38:03 +0100 |
---|---|---|
committer | Thom May <thom@may.lt> | 2016-04-21 08:38:03 +0100 |
commit | b37b683c624ce598643669167dfcbb56086c14ed (patch) | |
tree | 23ee983195844e7757cd84cbf094edf137c8a102 | |
parent | c3cf206089003c758ecf1d4f9f71def57d30a8c5 (diff) | |
parent | ec211cd56072ffb29db5f3c4ea3745b1757514df (diff) | |
download | chef-b37b683c624ce598643669167dfcbb56086c14ed.tar.gz |
Merge pull request #4837 from chef/tm/flow_253
Refactor ChefFS files to be files
33 files changed, 855 insertions, 228 deletions
diff --git a/lib-backcompat/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb b/lib-backcompat/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb new file mode 100644 index 0000000000..eb2c3e8ff6 --- /dev/null +++ b/lib-backcompat/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb @@ -0,0 +1,6 @@ +require "chef/chef_fs/file_system/repository/file_system_entry" + +module Chef::ChefFS::FileSystem::Repository + Chef.log_deprecation "Chef::ChefFS::FileSystem::Repository::ChefRepositoryFileSystemEntry is deprecated. Please use FileSystemEntry directly" + ChefRepositoryFileSystemEntry = FileSystemEntry +end diff --git a/lib/chef/chef_fs/file_system/repository/acl.rb b/lib/chef/chef_fs/file_system/repository/acl.rb new file mode 100644 index 0000000000..e2ba2e8771 --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/acl.rb @@ -0,0 +1,38 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/data_handler/acl_data_handler" +require "chef/chef_fs/file_system/repository/base_file" + +class Chef + module ChefFS + module FileSystem + module Repository + + class Acl < BaseFile + + def initialize(name, parent) + @data_handler = Chef::ChefFS::DataHandler::AclDataHandler.new + super + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/acls_dir.rb b/lib/chef/chef_fs/file_system/repository/acls_dir.rb index 897a182708..619031aa70 100644 --- a/lib/chef/chef_fs/file_system/repository/acls_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/acls_dir.rb @@ -16,8 +16,9 @@ # limitations under the License. # -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/acl" require "chef/chef_fs/file_system/repository/directory" +require "chef/chef_fs/file_system/repository/acls_sub_dir" require "chef/chef_fs/file_system/chef_server/acls_dir" require "chef/chef_fs/data_handler/acl_data_handler" @@ -34,7 +35,11 @@ class Chef protected def make_child_entry(child_name) - ChefRepositoryFileSystemEntry.new(child_name, self, nil, Chef::ChefFS::DataHandler::AclDataHandler.new) + if child_name == "organization.json" + Acl.new(child_name, self) + else + AclsSubDir.new(child_name, self) + end end end end diff --git a/lib/chef/chef_fs/file_system/repository/acls_sub_dir.rb b/lib/chef/chef_fs/file_system/repository/acls_sub_dir.rb new file mode 100644 index 0000000000..8eee8e1d70 --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/acls_sub_dir.rb @@ -0,0 +1,42 @@ +# +# Author:: Jordan Running (<jr@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/repository/acl" +require "chef/chef_fs/data_handler/acl_data_handler" +require "chef/chef_fs/file_system/repository/directory" + +class Chef + module ChefFS + module FileSystem + module Repository + class AclsSubDir < Repository::Directory + + def can_have_child?(name, is_dir) + !is_dir && File.extname(name) == ".json" + end + + protected + + def make_child_entry(child_name) + Acl.new(child_name, self) + end + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/base_file.rb b/lib/chef/chef_fs/file_system/repository/base_file.rb new file mode 100644 index 0000000000..d5ef26887e --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/base_file.rb @@ -0,0 +1,120 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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. +# + +class Chef + module ChefFS + module FileSystem + module Repository + + class BaseFile + + attr_reader :name + attr_reader :parent + attr_reader :path + attr_reader :file_path + attr_reader :data_handler + + def initialize(name, parent) + @parent = parent + @name = name + @path = Chef::ChefFS::PathUtils.join(parent.path, name) + @file_path = "#{parent.file_path}/#{name}" + end + + def dir? + false + end + + def is_json_file? + File.extname(name) == ".json" + end + + def name_valid? + !name.start_with?(".") && is_json_file? + end + + def fs_entry_valid? + name_valid? && exists? + end + + def create(file_contents) + if exists? + raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, self) + else + write(file_contents) + end + end + + def can_have_child?(name, is_dir) + false + end + + attr_writer :write_pretty_json + def write_pretty_json + @write_pretty_json.nil? ? root.write_pretty_json : @write_pretty_json + end + + def path_for_printing + file_path + end + + def delete(_) + File.delete(file_path) + rescue Errno::ENOENT + raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) + end + + def exists? + File.file?(file_path) + end + + def minimize(content, entry) + object = Chef::JSONCompat.parse(content) + object = data_handler.normalize(object, entry) + object = data_handler.minimize(object, entry) + Chef::JSONCompat.to_json_pretty(object) + end + + def read + File.open(file_path, "rb") { |f| f.read } + rescue Errno::ENOENT + raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) + end + + def write(content) + if content && write_pretty_json && is_json_file? + content = minimize(content, self) + end + File.open(file_path, "wb") do |file| + file.write(content) + end + end + + def root + parent.root + end + + def compare_to(other) + nil + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb index f533aa1080..703c0fc635 100644 --- a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb +++ b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb @@ -16,7 +16,7 @@ # limitations under the License. # -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/file_system_entry" require "chef/chef_fs/file_system/repository/cookbooks_dir" require "chef/chef_fs/file_system/exceptions" diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb deleted file mode 100644 index e490daa584..0000000000 --- a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb +++ /dev/null @@ -1,93 +0,0 @@ -# -# Author:: John Keiser (<jkeiser@chef.io>) -# Author:: Ho-Sheng Hsiao (<hosh@chef.io>) -# Copyright:: Copyright 2012-2016, Chef Software 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/repository/file_system_entry" -require "chef/chef_fs/file_system/exceptions" - -class Chef - module ChefFS - module FileSystem - module Repository - # ChefRepositoryFileSystemEntry works just like FileSystemEntry, - # except can inflate Chef objects - class ChefRepositoryFileSystemEntry < FileSystemEntry - def initialize(name, parent, file_path = nil, data_handler = nil) - super(name, parent, file_path) - @data_handler = data_handler - end - - def write_pretty_json=(value) - @write_pretty_json = value - end - - def write_pretty_json - @write_pretty_json.nil? ? root.write_pretty_json : @write_pretty_json - end - - def data_handler - @data_handler || parent.data_handler - end - - def chef_object - begin - return data_handler.chef_object(Chef::JSONCompat.parse(read)) - rescue - Chef::Log.error("Could not read #{path_for_printing} into a Chef object: #{$!}") - end - nil - end - - def can_have_child?(name, is_dir) - !is_dir && name[-5..-1] == ".json" - end - - def name_valid? - !name.start_with?(".") - end - - # basic implementation to support Repository::Directory API - def fs_entry_valid? - name_valid? && File.exist?(file_path) - end - - def write(file_contents) - if file_contents && write_pretty_json && name[-5..-1] == ".json" - file_contents = minimize(file_contents, self) - end - super(file_contents) - end - alias :create :write - - def minimize(file_contents, entry) - object = Chef::JSONCompat.parse(file_contents) - object = data_handler.normalize(object, entry) - object = data_handler.minimize(object, entry) - Chef::JSONCompat.to_json_pretty(object) - end - - protected - - def make_child_entry(child_name) - ChefRepositoryFileSystemEntry.new(child_name, self) - end - end - end - end - end -end diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb index 263d1b2b09..1b26ced372 100644 --- a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb @@ -30,7 +30,7 @@ require "chef/chef_fs/file_system/repository/policy_groups_dir" require "chef/chef_fs/file_system/repository/roles_dir" require "chef/chef_fs/file_system/repository/users_dir" require "chef/chef_fs/file_system/repository/client_keys_dir" -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/file_system_entry" require "chef/chef_fs/file_system/repository/policies_dir" require "chef/chef_fs/file_system/repository/versioned_cookbooks_dir" require "chef/chef_fs/file_system/multiplexed_dir" @@ -150,7 +150,7 @@ class Chef existing_paths = root_paths.select { |path| File.exists?(path) } if existing_paths.size > 0 MultiplexedDir.new(existing_paths.map do |path| - dir = ChefRepositoryFileSystemEntry.new(name, parent, path) + dir = FileSystemEntry.new(name, parent, path) dir.write_pretty_json = !!write_pretty_json dir end) diff --git a/lib/chef/chef_fs/file_system/repository/client.rb b/lib/chef/chef_fs/file_system/repository/client.rb new file mode 100644 index 0000000000..6a99b7f005 --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/client.rb @@ -0,0 +1,38 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/data_handler/client_data_handler" +require "chef/chef_fs/file_system/repository/base_file" + +class Chef + module ChefFS + module FileSystem + module Repository + + class Client < BaseFile + + def initialize(name, parent) + @data_handler = Chef::ChefFS::DataHandler::ClientDataHandler.new + super + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/client_key.rb b/lib/chef/chef_fs/file_system/repository/client_key.rb new file mode 100644 index 0000000000..8ca4f85d2f --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/client_key.rb @@ -0,0 +1,38 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/data_handler/client_key_data_handler" +require "chef/chef_fs/file_system/repository/base_file" + +class Chef + module ChefFS + module FileSystem + module Repository + + class ClientKey < BaseFile + + def initialize(name, parent) + @data_handler = Chef::ChefFS::DataHandler::ClientKeyDataHandler.new + super + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/client_keys_dir.rb b/lib/chef/chef_fs/file_system/repository/client_keys_dir.rb index 0cdc25569e..9e7e7b3d5c 100644 --- a/lib/chef/chef_fs/file_system/repository/client_keys_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/client_keys_dir.rb @@ -16,7 +16,7 @@ # limitations under the License. # -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/client_keys_sub_dir" require "chef/chef_fs/data_handler/client_key_data_handler" require "chef/chef_fs/file_system/repository/directory" @@ -33,7 +33,7 @@ class Chef protected def make_child_entry(child_name) - ChefRepositoryFileSystemEntry.new(child_name, self, nil, Chef::ChefFS::DataHandler::ClientKeyDataHandler.new) + ClientKeysSubDir.new(child_name, self) end end end diff --git a/lib/chef/chef_fs/file_system/repository/client_keys_sub_dir.rb b/lib/chef/chef_fs/file_system/repository/client_keys_sub_dir.rb new file mode 100644 index 0000000000..d231e41e78 --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/client_keys_sub_dir.rb @@ -0,0 +1,42 @@ +# +# Author:: Jordan Running (<jr@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/repository/client_key" +require "chef/chef_fs/data_handler/client_key_data_handler" +require "chef/chef_fs/file_system/repository/directory" + +class Chef + module ChefFS + module FileSystem + module Repository + class ClientKeysSubDir < Repository::Directory + + def can_have_child?(name, is_dir) + !is_dir && File.extname(name) == ".json" + end + + protected + + def make_child_entry(child_name) + ClientKey.new(child_name, self) + end + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/clients_dir.rb b/lib/chef/chef_fs/file_system/repository/clients_dir.rb index 6e23a6b8be..31aa80a28f 100644 --- a/lib/chef/chef_fs/file_system/repository/clients_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/clients_dir.rb @@ -17,7 +17,7 @@ # limitations under the License. # -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/client" require "chef/chef_fs/file_system/repository/directory" require "chef/chef_fs/file_system/exceptions" @@ -31,7 +31,7 @@ class Chef end def make_child_entry(child_name) - ChefRepositoryFileSystemEntry.new(child_name, self, nil, Chef::ChefFS::DataHandler::ClientDataHandler.new) + Client.new(child_name, self) end end end diff --git a/lib/chef/chef_fs/file_system/repository/container.rb b/lib/chef/chef_fs/file_system/repository/container.rb new file mode 100644 index 0000000000..e14a2ded73 --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/container.rb @@ -0,0 +1,38 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/data_handler/container_data_handler" +require "chef/chef_fs/file_system/repository/base_file" + +class Chef + module ChefFS + module FileSystem + module Repository + + class Container < BaseFile + + def initialize(name, parent) + @data_handler = Chef::ChefFS::DataHandler::ContainerDataHandler.new + super + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/containers_dir.rb b/lib/chef/chef_fs/file_system/repository/containers_dir.rb index b5ff84be7b..0fe541417a 100644 --- a/lib/chef/chef_fs/file_system/repository/containers_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/containers_dir.rb @@ -17,7 +17,7 @@ # limitations under the License. # -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/container" require "chef/chef_fs/file_system/repository/directory" require "chef/chef_fs/file_system/exceptions" @@ -32,7 +32,7 @@ class Chef end def make_child_entry(child_name) - ChefRepositoryFileSystemEntry.new(child_name, self, nil, Chef::ChefFS::DataHandler::ContainerDataHandler.new) + Container.new(child_name, self) end end end diff --git a/lib/chef/chef_fs/file_system/repository/cookbooks_dir.rb b/lib/chef/chef_fs/file_system/repository/cookbooks_dir.rb index e1092f112b..0fd249a2c4 100644 --- a/lib/chef/chef_fs/file_system/repository/cookbooks_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/cookbooks_dir.rb @@ -17,7 +17,6 @@ # require "chef/chef_fs/file_system/repository/directory" -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" require "chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_dir" require "chef/cookbook/chefignore" diff --git a/lib/chef/chef_fs/file_system/repository/data_bag_item.rb b/lib/chef/chef_fs/file_system/repository/data_bag_item.rb index a1cff5d1b8..2e3fb39606 100644 --- a/lib/chef/chef_fs/file_system/repository/data_bag_item.rb +++ b/lib/chef/chef_fs/file_system/repository/data_bag_item.rb @@ -17,97 +17,21 @@ # require "chef/chef_fs/data_handler/data_bag_item_data_handler" +require "chef/chef_fs/file_system/repository/base_file" class Chef module ChefFS module FileSystem module Repository - class DataBagItem - - attr_reader :name - attr_reader :parent - attr_reader :path - attr_reader :file_path + class DataBagItem < BaseFile def initialize(name, parent) - @parent = parent - @name = name - @path = Chef::ChefFS::PathUtils.join(parent.path, name) @data_handler = Chef::ChefFS::DataHandler::DataBagItemDataHandler.new - @file_path = "#{parent.file_path}/#{name}" - end - - # Public API callied by chef_fs/file_system - def dir? - false - end - - def name_valid? - !name.start_with?(".") && name.end_with?(".json") - end - - def fs_entry_valid? - name_valid? && File.file?(file_path) - end - - def create(file_contents) - if exists? - raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, self) - else - write(file_contents) - end - end - - def can_have_child?(name, is_dir) - false - end - - def write_pretty_json=(value) - @write_pretty_json = value - end - - def write_pretty_json - @write_pretty_json.nil? ? root.write_pretty_json : @write_pretty_json + super end - def path_for_printing - file_path - end - - def delete(recurse) - File.delete(file_path) - rescue Errno::ENOENT - raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) - end - - def exists? - File.exists?(file_path) - end - - def read - begin - File.open(file_path, "rb") { |f| f.read } - rescue Errno::ENOENT - raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) - end - end - - def write(content) - File.open(file_path, "wb") do |file| - file.write(content) - end - end - - def root - parent.root - end - - def compare_to(other) - nil - end end - end end end diff --git a/lib/chef/chef_fs/file_system/repository/environment.rb b/lib/chef/chef_fs/file_system/repository/environment.rb new file mode 100644 index 0000000000..9ef9741308 --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/environment.rb @@ -0,0 +1,38 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/data_handler/environment_data_handler" +require "chef/chef_fs/file_system/repository/base_file" + +class Chef + module ChefFS + module FileSystem + module Repository + + class Environment < BaseFile + + def initialize(name, parent) + @data_handler = Chef::ChefFS::DataHandler::EnvironmentDataHandler.new + super + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/environments_dir.rb b/lib/chef/chef_fs/file_system/repository/environments_dir.rb index 50b6dbefca..2c9b31b29b 100644 --- a/lib/chef/chef_fs/file_system/repository/environments_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/environments_dir.rb @@ -17,7 +17,7 @@ # limitations under the License. # -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/environment" require "chef/chef_fs/data_handler/environment_data_handler" require "chef/chef_fs/file_system/repository/directory" @@ -32,7 +32,7 @@ class Chef end def make_child_entry(child_name) - ChefRepositoryFileSystemEntry.new(child_name, self, nil, Chef::ChefFS::DataHandler::EnvironmentDataHandler.new) + Environment.new(child_name, self) end end end diff --git a/lib/chef/chef_fs/file_system/repository/file_system_entry.rb b/lib/chef/chef_fs/file_system/repository/file_system_entry.rb index 20e2eb7efc..45ae002521 100644 --- a/lib/chef/chef_fs/file_system/repository/file_system_entry.rb +++ b/lib/chef/chef_fs/file_system/repository/file_system_entry.rb @@ -27,26 +27,64 @@ class Chef module FileSystem module Repository class FileSystemEntry < BaseFSDir - def initialize(name, parent, file_path = nil) + def initialize(name, parent, file_path = nil, data_handler = nil) super(name, parent) @file_path = file_path || "#{parent.file_path}/#{name}" + @data_handler = data_handler end attr_reader :file_path + def write_pretty_json=(value) + @write_pretty_json = value + end + + def write_pretty_json + @write_pretty_json.nil? ? root.write_pretty_json : @write_pretty_json + end + + def data_handler + @data_handler || parent.data_handler + end + def path_for_printing file_path end + def chef_object + data_handler.chef_object(Chef::JSONCompat.parse(read)) + rescue + Chef::Log.error("Could not read #{path_for_printing} into a Chef object: #{$!}") + nil + end + + def can_have_child?(name, is_dir) + !is_dir && File.extname(name) == ".json" + end + + def name_valid? + !name.start_with?(".") + end + + # basic implementation to support Repository::Directory API + def fs_entry_valid? + name_valid? && File.exist?(file_path) + end + + def minimize(file_contents, entry) + object = Chef::JSONCompat.parse(file_contents) + object = data_handler.normalize(object, entry) + object = data_handler.minimize(object, entry) + 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. - 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 + Dir.entries(file_path).sort. + map { |child_name| make_child_entry(child_name) }. + select { |new_child| new_child.fs_entry_valid? && can_have_child?(new_child.name, new_child.dir?) } + rescue Errno::ENOENT + raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) end def create_child(child_name, file_contents = nil) @@ -57,13 +95,11 @@ class Chef if file_contents child.write(file_contents) else - begin - Dir.mkdir(child.file_path) - rescue Errno::EEXIST - raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, child) - end + Dir.mkdir(child.file_path) end child + rescue Errno::EEXIST + raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, child) end def dir? @@ -71,18 +107,16 @@ class Chef end def delete(recurse) - begin - if dir? - if !recurse - raise MustDeleteRecursivelyError.new(self, $!) - end - FileUtils.rm_r(file_path) - else - File.delete(file_path) + if dir? + if !recurse + raise MustDeleteRecursivelyError.new(self, $!) end - rescue Errno::ENOENT - raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) + FileUtils.rm_r(file_path) + else + File.delete(file_path) end + rescue Errno::ENOENT + raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) end def exists? @@ -90,18 +124,20 @@ class Chef end def read - begin - File.open(file_path, "rb") { |f| f.read } - rescue Errno::ENOENT - raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) - end + File.open(file_path, "rb") { |f| f.read } + rescue Errno::ENOENT + raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) end - def write(content) + def write(file_contents) + if file_contents && write_pretty_json && File.extname(name) == ".json" + file_contents = minimize(file_contents, self) + end File.open(file_path, "wb") do |file| - file.write(content) + file.write(file_contents) end end + alias :create :write protected diff --git a/lib/chef/chef_fs/file_system/repository/group.rb b/lib/chef/chef_fs/file_system/repository/group.rb new file mode 100644 index 0000000000..302e72739b --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/group.rb @@ -0,0 +1,38 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/data_handler/group_data_handler" +require "chef/chef_fs/file_system/repository/base_file" + +class Chef + module ChefFS + module FileSystem + module Repository + + class Group < BaseFile + + def initialize(name, parent) + @data_handler = Chef::ChefFS::DataHandler::GroupDataHandler.new + super + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/groups_dir.rb b/lib/chef/chef_fs/file_system/repository/groups_dir.rb index f9ca4956b0..e307000ad8 100644 --- a/lib/chef/chef_fs/file_system/repository/groups_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/groups_dir.rb @@ -17,7 +17,7 @@ # limitations under the License. # -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/group" require "chef/chef_fs/file_system/repository/directory" require "chef/chef_fs/file_system/exceptions" @@ -32,7 +32,7 @@ class Chef end def make_child_entry(child_name) - ChefRepositoryFileSystemEntry.new(child_name, self, nil, Chef::ChefFS::DataHandler::GroupDataHandler.new) + Group.new(child_name, self) end end end diff --git a/lib/chef/chef_fs/file_system/repository/node.rb b/lib/chef/chef_fs/file_system/repository/node.rb new file mode 100644 index 0000000000..d8f0dec7c4 --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/node.rb @@ -0,0 +1,38 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/data_handler/node_data_handler" +require "chef/chef_fs/file_system/repository/base_file" + +class Chef + module ChefFS + module FileSystem + module Repository + + class Node < BaseFile + + def initialize(name, parent) + @data_handler = Chef::ChefFS::DataHandler::NodeDataHandler.new + super + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/nodes_dir.rb b/lib/chef/chef_fs/file_system/repository/nodes_dir.rb index 7263dc3132..d04bea0de2 100644 --- a/lib/chef/chef_fs/file_system/repository/nodes_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/nodes_dir.rb @@ -17,7 +17,7 @@ # limitations under the License. # -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/node" require "chef/chef_fs/file_system/repository/directory" require "chef/chef_fs/file_system/exceptions" @@ -32,7 +32,7 @@ class Chef end def make_child_entry(child_name) - ChefRepositoryFileSystemEntry.new(child_name, self, nil, Chef::ChefFS::DataHandler::NodeDataHandler.new) + Node.new(child_name, self) end end end diff --git a/lib/chef/chef_fs/file_system/repository/policies_dir.rb b/lib/chef/chef_fs/file_system/repository/policies_dir.rb index 47a93f6655..c74ea5469b 100644 --- a/lib/chef/chef_fs/file_system/repository/policies_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/policies_dir.rb @@ -16,7 +16,7 @@ # limitations under the License. # -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/policy" require "chef/chef_fs/file_system/repository/directory" require "chef/chef_fs/data_handler/policy_data_handler" @@ -33,7 +33,7 @@ class Chef protected def make_child_entry(child_name) - ChefRepositoryFileSystemEntry.new(child_name, self, nil, Chef::ChefFS::DataHandler::PolicyDataHandler.new) + Policy.new(child_name, self) end end end diff --git a/lib/chef/chef_fs/file_system/repository/policy.rb b/lib/chef/chef_fs/file_system/repository/policy.rb new file mode 100644 index 0000000000..695bf17e83 --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/policy.rb @@ -0,0 +1,38 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/data_handler/policy_data_handler" +require "chef/chef_fs/file_system/repository/base_file" + +class Chef + module ChefFS + module FileSystem + module Repository + + class Policy < BaseFile + + def initialize(name, parent) + @data_handler = Chef::ChefFS::DataHandler::PolicyDataHandler.new + super + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/policy_group.rb b/lib/chef/chef_fs/file_system/repository/policy_group.rb new file mode 100644 index 0000000000..e4182847b6 --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/policy_group.rb @@ -0,0 +1,38 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/data_handler/policy_group_data_handler" +require "chef/chef_fs/file_system/repository/base_file" + +class Chef + module ChefFS + module FileSystem + module Repository + + class PolicyGroup < BaseFile + + def initialize(name, parent) + @data_handler = Chef::ChefFS::DataHandler::PolicyGroupDataHandler.new + super + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/policy_groups_dir.rb b/lib/chef/chef_fs/file_system/repository/policy_groups_dir.rb index 314c375879..020464a634 100644 --- a/lib/chef/chef_fs/file_system/repository/policy_groups_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/policy_groups_dir.rb @@ -17,7 +17,7 @@ # limitations under the License. # -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/policy_group" require "chef/chef_fs/file_system/repository/directory" require "chef/chef_fs/file_system/exceptions" @@ -32,7 +32,7 @@ class Chef end def make_child_entry(child_name) - ChefRepositoryFileSystemEntry.new(child_name, self, nil, Chef::ChefFS::DataHandler::PolicyGroupDataHandler.new) + PolicyGroup.new(child_name, self) end end end diff --git a/lib/chef/chef_fs/file_system/repository/role.rb b/lib/chef/chef_fs/file_system/repository/role.rb new file mode 100644 index 0000000000..d97ae0e7a1 --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/role.rb @@ -0,0 +1,38 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/data_handler/role_data_handler" +require "chef/chef_fs/file_system/repository/base_file" + +class Chef + module ChefFS + module FileSystem + module Repository + + class Role < BaseFile + + def initialize(name, parent) + @data_handler = Chef::ChefFS::DataHandler::RoleDataHandler.new + super + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/roles_dir.rb b/lib/chef/chef_fs/file_system/repository/roles_dir.rb index e3acd3a730..f59af093bb 100644 --- a/lib/chef/chef_fs/file_system/repository/roles_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/roles_dir.rb @@ -17,7 +17,7 @@ # limitations under the License. # -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/role" require "chef/chef_fs/file_system/repository/directory" require "chef/chef_fs/file_system/exceptions" @@ -32,7 +32,7 @@ class Chef end def make_child_entry(child_name) - ChefRepositoryFileSystemEntry.new(child_name, self, nil, Chef::ChefFS::DataHandler::RoleDataHandler.new) + Role.new(child_name, self) end end end diff --git a/lib/chef/chef_fs/file_system/repository/user.rb b/lib/chef/chef_fs/file_system/repository/user.rb new file mode 100644 index 0000000000..59355cc303 --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/user.rb @@ -0,0 +1,38 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software 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/data_handler/user_data_handler" +require "chef/chef_fs/file_system/repository/base_file" + +class Chef + module ChefFS + module FileSystem + module Repository + + class User < BaseFile + + def initialize(name, parent) + @data_handler = Chef::ChefFS::DataHandler::UserDataHandler.new + super + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/users_dir.rb b/lib/chef/chef_fs/file_system/repository/users_dir.rb index 928bb2d699..32cebf842d 100644 --- a/lib/chef/chef_fs/file_system/repository/users_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/users_dir.rb @@ -17,7 +17,7 @@ # limitations under the License. # -require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/user" require "chef/chef_fs/file_system/repository/directory" require "chef/chef_fs/file_system/exceptions" @@ -32,7 +32,7 @@ class Chef end def make_child_entry(child_name) - ChefRepositoryFileSystemEntry.new(child_name, self, nil, Chef::ChefFS::DataHandler::UserDataHandler.new) + User.new(child_name, self) end end end diff --git a/spec/unit/chef_fs/file_system/repository/base_file_spec.rb b/spec/unit/chef_fs/file_system/repository/base_file_spec.rb new file mode 100644 index 0000000000..bb0c267368 --- /dev/null +++ b/spec/unit/chef_fs/file_system/repository/base_file_spec.rb @@ -0,0 +1,128 @@ +# +# Copyright:: Copyright 2012-2016, Chef Software 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 "spec_helper" +require "chef/chef_fs/file_system/repository/base_file" +require "chef/chef_fs/file_system/repository/directory" +require "chef/chef_fs/file_system/base_fs_object" +require "chef/chef_fs/file_system/exceptions" +require "chef/chef_fs/file_system/nonexistent_fs_object" + +describe Chef::ChefFS::FileSystem::Repository::BaseFile do + let(:root) do + Chef::ChefFS::FileSystem::BaseFSDir.new("", nil) + end + + let(:tmp_dir) { Dir.mktmpdir } + + let(:parent) do + Chef::ChefFS::FileSystem::Repository::Directory.new("test", root, tmp_dir) + end + + let(:file) do + file = described_class.new("test_file.json", parent) + file.write_pretty_json = false + file + end + + let(:content) { '"name": "canteloup"' } + let(:file_path) { File.join(tmp_dir, "test_file.json") } + + after do + FileUtils.rm_f(file_path) + end + + context "#is_json_file?" do + it "returns false when the file is not json" do + file = described_class.new("test_file.dpkg", parent) + expect(file.is_json_file?).to be_falsey + end + + it "returns true when the file is json" do + expect(file.is_json_file?).to be_truthy + end + end + + context "#name_valid?" do + it "rejects dotfiles" do + file = described_class.new(".test_file.json", parent) + expect(file.name_valid?).to be_falsey + end + + it "rejects non json files" do + file = described_class.new("test_file.dpkg", parent) + expect(file.name_valid?).to be_falsey + end + + it "allows correctly named files" do + expect(file.name_valid?).to be_truthy + end + end + + context "#fs_entry_valid?" do + it "rejects invalid names" do + file = described_class.new("test_file.dpkg", parent) + expect(file.fs_entry_valid?).to be_falsey + end + + it "rejects missing files" do + FileUtils.rm_f(file_path) + expect(file.fs_entry_valid?).to be_falsey + end + + it "allows present and properly named files" do + FileUtils.touch(file_path) + expect(file.fs_entry_valid?).to be_truthy + end + end + + context "#create" do + it "doesn't create an existing file" do + FileUtils.touch(file_path) + expect { file.create('"name": "canteloup"') }.to raise_error(Chef::ChefFS::FileSystem::AlreadyExistsError) + end + + it "creates a new file" do + expect(file).to receive(:write).with(content) + expect { file.create(content) }.to_not raise_error + end + + end + + context "#write" do + context "minimises a json object" do + it "not if pretty json is off" do + expect(file).to_not receive(:minimize) + file.write(content) + end + + it "not if it's not a json file" do + file = described_class.new("test_file.dpkg", parent) + file.write_pretty_json = true + expect(file).to_not receive(:minimize) + file.write(content) + end + + it "correctly" do + file = described_class.new("test_file.json", parent) + file.write_pretty_json = true + expect(file).to receive(:minimize).with(content, file).and_return(content) + file.write(content) + end + end + end +end |