diff options
author | sersut <serdar@opscode.com> | 2013-05-15 16:43:23 -0700 |
---|---|---|
committer | sersut <serdar@opscode.com> | 2013-05-15 22:44:53 -0700 |
commit | 684ecb0b689e52aa80931b3378b63c3bfd9ca90a (patch) | |
tree | 2535d553537818b8b00b94200ec7578b5c5dac5f /lib/chef | |
parent | 45a2f6e9c1df78f7a86a6229b57aca333473004c (diff) | |
download | chef-684ecb0b689e52aa80931b3378b63c3bfd9ca90a.tar.gz |
Deprecated functions for file provider.
Diffstat (limited to 'lib/chef')
-rw-r--r-- | lib/chef/deprecation/provider/file.rb | 196 | ||||
-rw-r--r-- | lib/chef/deprecation/warnings.rb | 38 | ||||
-rw-r--r-- | lib/chef/provider/file.rb | 38 |
3 files changed, 243 insertions, 29 deletions
diff --git a/lib/chef/deprecation/provider/file.rb b/lib/chef/deprecation/provider/file.rb new file mode 100644 index 0000000000..cc880641fb --- /dev/null +++ b/lib/chef/deprecation/provider/file.rb @@ -0,0 +1,196 @@ +# +# Author:: Serdar Sutay (<serdar@opscode.com>) +# Copyright:: Copyright (c) 2013 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. +# + +# +# This module contains the deprecated functions of +# Chef::Provider::File. These functions are refactored to different +# components. They are frozen and will be removed in Chef 12. +# + +class Chef + module Deprecation + module Provider + module File + + def diff_current_from_content(new_content) + result = nil + Tempfile.open("chef-diff") do |file| + file.write new_content + file.close + result = diff_current file.path + end + result + end + + def is_binary?(path) + ::File.open(path) do |file| + + buff = file.read(Chef::Config[:diff_filesize_threshold]) + buff = "" if buff.nil? + return buff !~ /^[\r[:print:]]*$/ + end + end + + def diff_current(temp_path) + suppress_resource_reporting = false + + return [ "(diff output suppressed by config)" ] if Chef::Config[:diff_disabled] + return [ "(no temp file with new content, diff output suppressed)" ] unless ::File.exists?(temp_path) # should never happen? + + # solaris does not support diff -N, so create tempfile to diff against if we are creating a new file + target_path = if ::File.exists?(@current_resource.path) + @current_resource.path + else + suppress_resource_reporting = true # suppress big diffs going to resource reporting service + tempfile = Tempfile.new('chef-tempfile') + tempfile.path + end + + diff_filesize_threshold = Chef::Config[:diff_filesize_threshold] + diff_output_threshold = Chef::Config[:diff_output_threshold] + + if ::File.size(target_path) > diff_filesize_threshold || ::File.size(temp_path) > diff_filesize_threshold + return [ "(file sizes exceed #{diff_filesize_threshold} bytes, diff output suppressed)" ] + end + + # MacOSX(BSD?) diff will *sometimes* happily spit out nasty binary diffs + return [ "(current file is binary, diff output suppressed)"] if is_binary?(target_path) + return [ "(new content is binary, diff output suppressed)"] if is_binary?(temp_path) + + begin + # -u: Unified diff format + result = shell_out("diff -u #{target_path} #{temp_path}" ) + rescue Exception => e + # Should *not* receive this, but in some circumstances it seems that + # an exception can be thrown even using shell_out instead of shell_out! + return [ "Could not determine diff. Error: #{e.message}" ] + end + + # diff will set a non-zero return code even when there's + # valid stdout results, if it encounters something unexpected + # So as long as we have output, we'll show it. + if not result.stdout.empty? + if result.stdout.length > diff_output_threshold + [ "(long diff of over #{diff_output_threshold} characters, diff output suppressed)" ] + else + val = result.stdout.split("\n") + val.delete("\\ No newline at end of file") + @new_resource.diff(val.join("\\n")) unless suppress_resource_reporting + val + end + elsif not result.stderr.empty? + [ "Could not determine diff. Error: #{result.stderr}" ] + else + [ "(no diff)" ] + end + end + + def setup_acl + return if Chef::Platform.windows? + acl_scanner = ScanAccessControl.new(@new_resource, @current_resource) + acl_scanner.set_all! + end + + def compare_content + checksum(@current_resource.path) == new_resource_content_checksum + end + + def set_content + unless compare_content + description = [] + description << "update content in file #{@new_resource.path} from #{short_cksum(@current_resource.checksum)} to #{short_cksum(new_resource_content_checksum)}" + description << diff_current_from_content(@new_resource.content) + converge_by(description) do + backup @new_resource.path if ::File.exists?(@new_resource.path) + ::File.open(@new_resource.path, "w") {|f| f.write @new_resource.content } + Chef::Log.info("#{@new_resource} contents updated") + end + end + end + + def update_new_file_state(path=@new_resource.path) + if !::File.directory?(path) + @new_resource.checksum(checksum(path)) + end + + if Chef::Platform.windows? + # TODO: To work around CHEF-3554, add support for Windows + # equivalent, or implicit resource reporting won't work for + # Windows. + return + end + + acl_scanner = ScanAccessControl.new(@new_resource, @new_resource) + acl_scanner.set_all! + end + + def set_all_access_controls + if access_controls.requires_changes? + converge_by(access_controls.describe_changes) do + access_controls.set_all + #Update file state with new access values + update_new_file_state + end + end + end + + def deploy_tempfile + Tempfile.open(::File.basename(@new_resource.name)) do |tempfile| + yield tempfile + + temp_res = Chef::Resource::CookbookFile.new(@new_resource.name) + temp_res.path(tempfile.path) + ac = Chef::FileAccessControl.new(temp_res, @new_resource, self) + ac.set_all! + FileUtils.mv(tempfile.path, @new_resource.path) + end + end + + def backup(file=nil) + file ||= @new_resource.path + if @new_resource.backup != false && @new_resource.backup > 0 && ::File.exist?(file) + time = Time.now + savetime = time.strftime("%Y%m%d%H%M%S") + backup_filename = "#{@new_resource.path}.chef-#{savetime}" + backup_filename = backup_filename.sub(/^([A-Za-z]:)/, "") #strip drive letter on Windows + # if :file_backup_path is nil, we fallback to the old behavior of + # keeping the backup in the same directory. We also need to to_s it + # so we don't get a type error around implicit to_str conversions. + prefix = Chef::Config[:file_backup_path].to_s + backup_path = ::File.join(prefix, backup_filename) + FileUtils.mkdir_p(::File.dirname(backup_path)) if Chef::Config[:file_backup_path] + FileUtils.cp(file, backup_path, :preserve => true) + Chef::Log.info("#{@new_resource} backed up to #{backup_path}") + + # Clean up after the number of backups + slice_number = @new_resource.backup + backup_files = Dir[::File.join(prefix, ".#{@new_resource.path}.chef-*")].sort { |a,b| b <=> a } + if backup_files.length >= @new_resource.backup + remainder = backup_files.slice(slice_number..-1) + remainder.each do |backup_to_delete| + FileUtils.rm(backup_to_delete) + Chef::Log.info("#{@new_resource} removed backup at #{backup_to_delete}") + end + end + end + end + + end + end + end +end diff --git a/lib/chef/deprecation/warnings.rb b/lib/chef/deprecation/warnings.rb new file mode 100644 index 0000000000..2286489d5f --- /dev/null +++ b/lib/chef/deprecation/warnings.rb @@ -0,0 +1,38 @@ +# +# Author:: Serdar Sutay (<serdar@opscode.com>) +# Copyright:: Copyright (c) 2013 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. +# + +class Chef + module Deprecation + module Warnings + + def add_deprecation_warnings_for(method_names) + method_names.each do |name| + m = instance_method(name) + define_method(name) do |*args| + Chef::Log.warn "Method '#{name}' of '#{self.class}' is deprecated. It will be removed in Chef 12." + Chef::Log.warn "Please update your cookbooks accordingly. Accessed from:" + caller[0..3].each {|l| Chef::Log.warn l} + m.send(args) + end + end + end + + end + end +end + diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb index 3c89874dbb..29c4fcc445 100644 --- a/lib/chef/provider/file.rb +++ b/lib/chef/provider/file.rb @@ -28,6 +28,8 @@ require 'chef/mixin/checksum' require 'chef/mixin/shell_out' require 'chef/util/backup' require 'chef/util/diff' +require 'chef/deprecation/provider/file' +require 'chef/deprecation/warnings' # The Tao of File Providers: # - the content provider must always return a tempfile that we can delete/mv @@ -46,6 +48,10 @@ class Chef include Chef::Mixin::Checksum include Chef::Mixin::ShellOut + extend Chef::Deprecation::Warnings + include Chef::Deprecation::Provider::File + add_deprecation_warnings_for(Chef::Deprecation::Provider::File.instance_methods) + attr_reader :deployment_strategy def initialize(new_resource, run_context) @@ -126,7 +132,7 @@ class Chef def action_delete if ::File.exists?(@new_resource.path) converge_by("delete file #{@new_resource.path}") do - backup unless ::File.symlink?(@new_resource.path) + do_backup unless ::File.symlink?(@new_resource.path) ::File.delete(@new_resource.path) Chef::Log.info("#{@new_resource} deleted file at #{@new_resource.path}") end @@ -142,32 +148,6 @@ class Chef end end - # deprecated methods to support - - def set_content - Chef::Log.warn("The method Chef::Provider::File#set_content is deprecated and will be removed in Chef 12") - end - - def compare_content - Chef::Log.warn("The method Chef::Provider::File#compare_content is deprecated and will be removed in Chef 12") - end - - def diff_current - Chef::Log.warn("The method Chef::Provider::File#diff_current is deprecated and will be removed in Chef 12") - end - - def diff_current_from_content - Chef::Log.warn("The method Chef::Provider::File#diff_current_from_content is deprecated and will be removed in Chef 12") - end - - def is_binary?(path) - Chef::Log.warn("The method Chef::Provider::File#is_binary? is deprecated and will be removed in Chef 12") - end - - def update_new_file_state - Chef::Log.warn("The method Chef::Provider::File#update_new_file_state is deprecated and will be removed in Chef 12") - end - private def content @@ -230,7 +210,7 @@ class Chef @file_created == true end - def backup(file = nil) + def do_backup(file = nil) Chef::Util::Backup.new(@new_resource, file).backup! end @@ -239,7 +219,7 @@ class Chef end def update_file_contents - backup unless file_created? + do_backup unless file_created? deployment_strategy.deploy(tempfile.path, @new_resource.path) Chef::Log.info("#{@new_resource} updated file contents #{@new_resource.path}") @new_resource.checksum(checksum(@new_resource.path)) # for reporting |