summaryrefslogtreecommitdiff
path: root/lib/chef
diff options
context:
space:
mode:
authorsersut <serdar@opscode.com>2013-05-15 16:43:23 -0700
committersersut <serdar@opscode.com>2013-05-15 22:44:53 -0700
commit684ecb0b689e52aa80931b3378b63c3bfd9ca90a (patch)
tree2535d553537818b8b00b94200ec7578b5c5dac5f /lib/chef
parent45a2f6e9c1df78f7a86a6229b57aca333473004c (diff)
downloadchef-684ecb0b689e52aa80931b3378b63c3bfd9ca90a.tar.gz
Deprecated functions for file provider.
Diffstat (limited to 'lib/chef')
-rw-r--r--lib/chef/deprecation/provider/file.rb196
-rw-r--r--lib/chef/deprecation/warnings.rb38
-rw-r--r--lib/chef/provider/file.rb38
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