Class: Chef::Provider::File

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

Direct Known Subclasses

Directory, RemoteFile, Template

Instance Attribute Summary

Attributes inherited from Chef::Provider

#current_resource, #new_resource, #node

Instance Method Summary collapse

Methods included from Mixin::GenerateURL

#generate_cookbook_url, #generate_cookbook_url_from_uri

Methods included from Mixin::Checksum

#checksum

Methods inherited from Chef::Provider

#action_nothing, build_from_file, #initialize

Methods included from Mixin::ConvertToClassName

#convert_to_class_name, #convert_to_snake_case, #filename_to_qualified_string, #snake_case_basename

Methods included from Mixin::RecipeDefinitionDSLCore

#method_missing

Methods included from Mixin::Language

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

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



141
142
143
144
145
146
147
148
149
150
151
# File 'lib/chef/provider/file.rb', line 141

def action_create
  unless ::File.exists?(@new_resource.path)
    Chef::Log.info("Creating #{@new_resource} at #{@new_resource.path}")
    ::File.open(@new_resource.path, "w+") { |f| }
    @new_resource.updated = true
  end
  set_content unless @new_resource.content.nil?
  set_owner unless @new_resource.owner.nil?
  set_group unless @new_resource.group.nil?
  set_mode unless @new_resource.mode.nil?
end

#action_create_if_missingObject



153
154
155
# File 'lib/chef/provider/file.rb', line 153

def action_create_if_missing
  action_create
end

#action_deleteObject



157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/chef/provider/file.rb', line 157

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

#action_touchObject



170
171
172
173
174
175
176
# File 'lib/chef/provider/file.rb', line 170

def action_touch
  action_create
  time = Time.now
  Chef::Log.info("Updating #{@new_resource} with new atime/mtime of #{time}")
  ::File.utime(time, time, @new_resource.path)
  @new_resource.updated = true
end

#backup(file = nil) ⇒ Object



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/chef/provider/file.rb', line 178

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}"
    prefix = Chef::Config[:file_backup_path] || ""
    if Chef::Config[:file_backup_path]
      FileUtils.mkdir_p(::File.dirname(Chef::Config[:file_backup_path] + backup_filename))
    end
    Chef::Log.info("Backing up #{@new_resource} to #{prefix + backup_filename}")
    FileUtils.cp(file, prefix + backup_filename, :preserve => true)

    # Clean up after the number of backups
    slice_number = @new_resource.backup
    backup_files = Dir[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|
        Chef::Log.info("Removing backup of #{@new_resource} at #{backup_to_delete}")
        FileUtils.rm(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.



62
63
64
# File 'lib/chef/provider/file.rb', line 62

def compare_content
  @current_resource.checksum == new_resource_content_checksum
end

#compare_groupObject

Compares the group of a file. Returns true if they are the same, false if they are not.



101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/chef/provider/file.rb', line 101

def compare_group
  return false if @new_resource.group.nil?

  @set_group_id = case @new_resource.group
                  when /^\d+$/, Integer
                    @new_resource.group.to_i
                  else
                    Etc.getgrnam(@new_resource.group).gid
                  end

  @set_group_id == @current_resource.group
end

#compare_modeObject



123
124
125
126
127
128
129
130
# File 'lib/chef/provider/file.rb', line 123

def compare_mode
  case @new_resource.mode
  when /^\d+$/, Integer
    octal_mode(@new_resource.mode) == octal_mode(@current_resource.mode)
  else
    false
  end
end

#compare_ownerObject

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



76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/chef/provider/file.rb', line 76

def compare_owner
  return false if @new_resource.owner.nil?

  @set_user_id = case @new_resource.owner
                 when /^\d+$/, Integer
                   @new_resource.owner.to_i
                 else
                   # This raises an ArgumentError if you can't find the user
                   Etc.getpwnam(@new_resource.owner).uid
                 end

  @set_user_id == @current_resource.owner
end

#generate_url(url, type, args = nil) ⇒ Object



204
205
206
207
# File 'lib/chef/provider/file.rb', line 204

def generate_url(url, type, args=nil)
  cookbook_name = (@new_resource.respond_to?(:cookbook) && @new_resource.cookbook) ? @new_resource.cookbook : @new_resource.cookbook_name
  generate_cookbook_url(url, cookbook_name, type, @node, args)
end

#load_current_resourceObject



47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/chef/provider/file.rb', line 47

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)
  if ::File.exist?(@current_resource.path) && ::File.readable?(@current_resource.path)
    cstats = ::File.stat(@current_resource.path)
    @current_resource.owner(cstats.uid)
    @current_resource.group(cstats.gid)
    @current_resource.mode(octal_mode(cstats.mode))
    @current_resource.checksum(checksum(@current_resource.path))
  end
  @current_resource
end

#set_contentObject

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



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

def set_content
  unless compare_content
    Chef::Log.info("Setting content for #{@new_resource}")
    ::File.open(@new_resource.path, "w") {|f| f.write @new_resource.content }
    @new_resource.updated = true
  end
end

#set_groupObject



114
115
116
117
118
119
120
121
# File 'lib/chef/provider/file.rb', line 114

def set_group
  unless compare_group
    Chef::Log.info("Setting group to #{@set_group_id} for #{@new_resource}")
    @set_group_id = negative_complement(@set_group_id)
    ::File.chown(nil, @set_group_id, @new_resource.path)
    @new_resource.updated = true
  end
end

#set_modeObject



132
133
134
135
136
137
138
139
# File 'lib/chef/provider/file.rb', line 132

def set_mode
  unless compare_mode && @new_resource.mode != nil
    Chef::Log.info("Setting mode to #{sprintf("%o" % octal_mode(@new_resource.mode))} for #{@new_resource}")
    # CHEF-174, bad mojo around treating integers as octal.  If a string is passed, we try to do the "right" thing
    ::File.chmod(octal_mode(@new_resource.mode), @new_resource.path)
    @new_resource.updated = true
  end
end

#set_ownerObject

Set the ownership on the file, assuming it is not set correctly already.



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

def set_owner
  unless compare_owner
    Chef::Log.info("Setting owner to #{@set_user_id} for #{@new_resource}")
    @set_user_id = negative_complement(@set_user_id)
    ::File.chown(@set_user_id, nil, @new_resource.path)
    @new_resource.updated = true
  end
end