Class: Chef::Provider::File
Constant Summary
Mixin::ShellOut::DEPRECATED_OPTIONS
Instance Attribute Summary
#action, #current_resource, #new_resource, #run_context
Instance Method Summary
collapse
#run_command_compatible_options, #shell_out, #shell_out!
#checksum
#access_controls, #enforce_ownership_and_permissions
#action_nothing, #cleanup_after_converge, #cookbook_name, #events, #initialize, #node, #process_resource_requirements, #requirements, #resource_collection, #run_action, #set_updated_status, #whyrun_mode?
#method_missing
#convert_to_class_name, #convert_to_snake_case, #filename_to_qualified_string, #snake_case_basename
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::DSL::Recipe
Instance Method Details
[View source]
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
# File 'lib/chef/provider/file.rb', line 217
def action_create
if !::File.exists?(@new_resource.path)
description = []
desc = "create new file #{@new_resource.path}"
desc << " with content checksum #{short_cksum(new_resource_content_checksum)}" if new_resource.content
description << desc
description << diff_current_from_content(@new_resource.content)
converge_by(description) do
Chef::Log.info("entered create")
::File.open(@new_resource.path, "w+") {|f| f.write @new_resource.content }
access_controls.set_all
Chef::Log.info("#{@new_resource} created file #{@new_resource.path}")
update_new_file_state
end
else
set_content unless @new_resource.content.nil?
set_all_access_controls
end
end
|
[View source]
248
249
250
251
252
253
254
|
# File 'lib/chef/provider/file.rb', line 248
def action_create_if_missing
if ::File.exists?(@new_resource.path)
Chef::Log.debug("#{@new_resource} exists at #{@new_resource.path} taking no action.")
else
action_create
end
end
|
[View source]
256
257
258
259
260
261
262
263
264
|
# File 'lib/chef/provider/file.rb', line 256
def action_delete
if ::File.exists?(@new_resource.path)
converge_by("delete file #{@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
end
end
|
[View source]
266
267
268
269
270
271
272
273
|
# File 'lib/chef/provider/file.rb', line 266
def action_touch
action_create
converge_by("update utime on file #{@new_resource.path}") do
time = Time.now
::File.utime(time, time, @new_resource.path)
Chef::Log.info("#{@new_resource} updated atime and mtime to #{time}")
end
end
|
[View source]
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
|
# File 'lib/chef/provider/file.rb', line 275
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]:)/, "") 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}")
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 the content of a file. Returns true if they are the same, false if they are not.
[View source]
180
181
182
|
# File 'lib/chef/provider/file.rb', line 180
def compare_content
checksum(@current_resource.path) == new_resource_content_checksum
end
|
permalink
#define_resource_requirements ⇒ Object
[View source]
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
# File 'lib/chef/provider/file.rb', line 152
def define_resource_requirements
access_controls.requires_changes?
requirements.assert(:create, :create_if_missing, :touch) do |a|
parent_directory = ::File.dirname(@new_resource.path)
a.assertion { ::File.directory?(parent_directory) }
a.failure_message(Chef::Exceptions::EnclosingDirectoryDoesNotExist, "Parent directory #{parent_directory} does not exist.")
a.whyrun("Assuming directory #{parent_directory} would have been created")
end
requirements.assert(:delete) do |a|
a.assertion do
if ::File.exists?(@new_resource.path)
::File.writable?(@new_resource.path)
else
true
end
end
a.failure_message(Chef::Exceptions::InsufficientPermissions,"File #{@new_resource.path} exists but is not writable so it cannot be deleted")
end
end
|
[View source]
304
305
306
307
308
309
310
311
312
313
314
|
# File 'lib/chef/provider/file.rb', line 304
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
|
[View source]
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
# File 'lib/chef/provider/file.rb', line 70
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)
target_path = if ::File.exists?(@current_resource.path)
@current_resource.path
else
suppress_resource_reporting = true 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
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
result = shell_out("diff -u #{target_path} #{temp_path}" )
rescue Exception => e
return [ "Could not determine diff. Error: #{e.message}" ]
end
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
|
permalink
#diff_current_from_content(new_content) ⇒ Object
[View source]
50
51
52
53
54
55
56
57
58
|
# File 'lib/chef/provider/file.rb', line 50
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
|
permalink
#is_binary?(path) ⇒ Boolean
[View source]
60
61
62
63
64
65
66
67
|
# File 'lib/chef/provider/file.rb', line 60
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
|
[View source]
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
# File 'lib/chef/provider/file.rb', line 128
def load_current_resource
@current_resource ||= Chef::Resource::File.new(@new_resource.name)
@new_resource.path.gsub!(/\\/, "/") @current_resource.path(@new_resource.path)
if !::File.directory?(@new_resource.path)
if ::File.exist?(@new_resource.path)
if @action != :create_if_missing
@current_resource.checksum(checksum(@new_resource.path))
end
end
end
setup_acl
@current_resource
end
|
[View source]
238
239
240
241
242
243
244
245
246
|
# File 'lib/chef/provider/file.rb', line 238
def set_all_access_controls
if access_controls.requires_changes?
converge_by(access_controls.describe_changes) do
access_controls.set_all
update_new_file_state
end
end
end
|
Set the content of the file, assuming it is not set correctly already.
[View source]
185
186
187
188
189
190
191
192
193
194
195
196
|
# File 'lib/chef/provider/file.rb', line 185
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
|
permalink
#update_new_file_state(path = @new_resource.path) ⇒ Object
if you are using a tempfile before creating, you must override the default with the tempfile, since the file at @new_resource.path will not be updated on converge
[View source]
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
|
# File 'lib/chef/provider/file.rb', line 201
def update_new_file_state(path=@new_resource.path)
if !::File.directory?(path)
@new_resource.checksum(checksum(path))
end
if Chef::Platform.windows?
return
end
acl_scanner = ScanAccessControl.new(@new_resource, @new_resource)
acl_scanner.set_all!
end
|
permalink
#whyrun_supported? ⇒ Boolean
[View source]
124
125
126
|
# File 'lib/chef/provider/file.rb', line 124
def whyrun_supported?
true
end
|