From f4e7711817ff704286bcde22a9ca95415028e58f Mon Sep 17 00:00:00 2001 From: Thom May Date: Wed, 20 Apr 2016 17:41:46 +0100 Subject: properly deal with loading ruby files --- lib/chef/chef_fs/data_handler/data_handler_base.rb | 21 +++++++++++---------- .../data_handler/environment_data_handler.rb | 2 +- lib/chef/chef_fs/data_handler/role_data_handler.rb | 2 +- lib/chef/chef_fs/file_system/exceptions.rb | 7 +++++++ .../chef_fs/file_system/repository/base_file.rb | 17 ++++++++++++++--- 5 files changed, 34 insertions(+), 15 deletions(-) (limited to 'lib/chef/chef_fs') diff --git a/lib/chef/chef_fs/data_handler/data_handler_base.rb b/lib/chef/chef_fs/data_handler/data_handler_base.rb index b30ae9c708..b34aff4b98 100644 --- a/lib/chef/chef_fs/data_handler/data_handler_base.rb +++ b/lib/chef/chef_fs/data_handler/data_handler_base.rb @@ -24,15 +24,14 @@ class Chef object end - # - # Takes a name like blah.json and removes the .json from it. - # - def remove_dot_json(name) - if name.length < 5 || name[-5, 5] != ".json" - raise "Invalid name #{path}: must end in .json" + def remove_file_extension(name, ext = ".*") + if %w{ .rb .json }.include?(File.extname(name)) + File.basename(name, ext) + else + name end - name[0, name.length - 5] end + alias_method :remove_dot_json, :remove_file_extension # # Return true if minimize() should preserve a key even if it is the same @@ -109,8 +108,10 @@ class Chef # # Bring in an instance of this object from Ruby. (Like roles/x.rb) # - def from_ruby(ruby) - chef_class.from_file(ruby).to_hash + def from_ruby(path) + r = chef_class.new + r.from_file(path) + r.to_hash end # @@ -192,7 +193,7 @@ class Chef # @yield [s] callback to handle errors # @yieldparam [s] error message def verify_integrity(object, entry) - base_name = remove_dot_json(entry.name) + base_name = remove_file_extension(entry.name) if object["name"] != base_name yield("Name must be '#{base_name}' (is '#{object['name']}')") end diff --git a/lib/chef/chef_fs/data_handler/environment_data_handler.rb b/lib/chef/chef_fs/data_handler/environment_data_handler.rb index 8d066764be..68f6daee9a 100644 --- a/lib/chef/chef_fs/data_handler/environment_data_handler.rb +++ b/lib/chef/chef_fs/data_handler/environment_data_handler.rb @@ -7,7 +7,7 @@ class Chef class EnvironmentDataHandler < DataHandlerBase def normalize(environment, entry) normalize_hash(environment, { - "name" => remove_dot_json(entry.name), + "name" => remove_file_extension(entry.name), "description" => "", "cookbook_versions" => {}, "default_attributes" => {}, diff --git a/lib/chef/chef_fs/data_handler/role_data_handler.rb b/lib/chef/chef_fs/data_handler/role_data_handler.rb index 74533cff05..b09c146a5d 100644 --- a/lib/chef/chef_fs/data_handler/role_data_handler.rb +++ b/lib/chef/chef_fs/data_handler/role_data_handler.rb @@ -7,7 +7,7 @@ class Chef class RoleDataHandler < DataHandlerBase def normalize(role, entry) result = normalize_hash(role, { - "name" => remove_dot_json(entry.name), + "name" => remove_file_extension(entry.name), "description" => "", "json_class" => "Chef::Role", "chef_type" => "role", diff --git a/lib/chef/chef_fs/file_system/exceptions.rb b/lib/chef/chef_fs/file_system/exceptions.rb index cf4916e4c8..2a1baba8f5 100644 --- a/lib/chef/chef_fs/file_system/exceptions.rb +++ b/lib/chef/chef_fs/file_system/exceptions.rb @@ -86,6 +86,13 @@ class Chef class CookbookFrozenError < AlreadyExistsError; end + class RubyFileError < OperationNotAllowedError + def reason + result = super + result + " (can't safely update ruby files)" + end + end + class DefaultEnvironmentCannotBeModifiedError < OperationNotAllowedError def reason result = super diff --git a/lib/chef/chef_fs/file_system/repository/base_file.rb b/lib/chef/chef_fs/file_system/repository/base_file.rb index d5ef26887e..514ffc9584 100644 --- a/lib/chef/chef_fs/file_system/repository/base_file.rb +++ b/lib/chef/chef_fs/file_system/repository/base_file.rb @@ -41,11 +41,15 @@ class Chef end def is_json_file? - File.extname(name) == ".json" + File.extname(file_path) == ".json" + end + + def is_ruby_file? + File.extname(file_path) == ".rb" end def name_valid? - !name.start_with?(".") && is_json_file? + !name.start_with?(".") && (is_json_file? || is_ruby_file?) end def fs_entry_valid? @@ -91,12 +95,19 @@ class Chef end def read - File.open(file_path, "rb") { |f| f.read } + if is_ruby_file? + data_handler.from_ruby(file_path).to_json + else + File.open(file_path, "rb") { |f| f.read } + end rescue Errno::ENOENT raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) end def write(content) + if is_ruby_file? + raise Chef::ChefFS::FileSystem::RubyFileError.new(:write, self) + end if content && write_pretty_json && is_json_file? content = minimize(content, self) end -- cgit v1.2.1