Class: Chef::Provider::File

Inherits:
Chef::Provider show all
Includes:
Mixin::Checksum
Defined in:
lib/chef/provider/file.rb

Direct Known Subclasses

CookbookFile, Directory, RemoteFile, Template

Instance Attribute Summary

Attributes inherited from Chef::Provider

#current_resource, #new_resource, #run_context

Instance Method Summary collapse

Methods included from Mixin::Checksum

#checksum

Methods inherited from Chef::Provider

#action_nothing, build_from_file, #cookbook_name, #initialize, #node, #resource_collection

Methods included from Mixin::ConvertToClassName

#convert_to_class_name, #convert_to_snake_case, #filename_to_qualified_string, #snake_case_basename

Methods included from Mixin::EnforceOwnershipAndPermissions

#enforce_ownership_and_permissions

Methods included from Mixin::RecipeDefinitionDSLCore

#method_missing

Methods included from Mixin::Language

#data_bag, #data_bag_item, #platform?, #platform_family?, #search, #value_for_platform, #value_for_platform_family

Constructor Details

This class inherits a constructor from Chef::Provider

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Chef::Mixin::RecipeDefinitionDSLCore

Instance Method Details

#action_createObject



67
68
69
70
71
72
73
74
75
76
77
# File 'lib/chef/provider/file.rb', line 67

def action_create
  assert_enclosing_directory_exists!
  unless ::File.exists?(@new_resource.path)
    ::File.open(@new_resource.path, "w+") {|f| f.write @new_resource.content }
    @new_resource.updated_by_last_action(true)
    Chef::Log.info("#{@new_resource} created file #{@new_resource.path}")
  else
    set_content unless @new_resource.content.nil?
  end
  enforce_ownership_and_permissions
end

#action_create_if_missingObject



79
80
81
82
83
84
85
# File 'lib/chef/provider/file.rb', line 79

def action_create_if_missing
  if ::File.exists?(@new_resource.path)
    Chef::Log.debug("File #{@new_resource.path} exists, taking no action.")
  else
    action_create
  end
end

#action_deleteObject



87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/chef/provider/file.rb', line 87

def action_delete
  if ::File.exists?(@new_resource.path)
    if ::File.writable?(@new_resource.path)
      backup unless ::File.symlink?(@new_resource.path)
      ::File.delete(@new_resource.path)
      Chef::Log.info("#{@new_resource} deleted file at #{@new_resource.path}")
      @new_resource.updated_by_last_action(true)
    else
      raise "Cannot delete #{@new_resource} at #{@new_resource_path}!"
    end
  end
end

#action_touchObject



100
101
102
103
104
105
106
# File 'lib/chef/provider/file.rb', line 100

def action_touch
  action_create
  time = Time.now
  ::File.utime(time, time, @new_resource.path)
  Chef::Log.info("#{@new_resource} updated atime and mtime to #{time}")
  @new_resource.updated_by_last_action(true)
end

#backup(file = nil) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/chef/provider/file.rb', line 108

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

#compare_contentObject

Compare the content of a file. Returns true if they are the same, false if they are not.



53
54
55
# File 'lib/chef/provider/file.rb', line 53

def compare_content
  checksum(@current_resource.path) == new_resource_content_checksum
end

#load_current_resourceObject



45
46
47
48
49
50
# File 'lib/chef/provider/file.rb', line 45

def load_current_resource
  @current_resource = Chef::Resource::File.new(@new_resource.name)
  @new_resource.path.gsub!(/\\/, "/") # for Windows
  @current_resource.path(@new_resource.path)
  @current_resource
end

#set_contentObject

Set the content of the file, assuming it is not set correctly already.



58
59
60
61
62
63
64
65
# File 'lib/chef/provider/file.rb', line 58

def set_content
  unless compare_content
    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")
    @new_resource.updated_by_last_action(true)
  end
end