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
#action_nothing, build_from_file, #cleanup_after_converge, #converge, #cookbook_name, #events, #initialize, #node, #process_resource_requirements, #requirements, #resource_collection, #run_action, #whyrun_mode?
#convert_to_class_name, #convert_to_snake_case, #filename_to_qualified_string, #snake_case_basename
#access_controls, #enforce_ownership_and_permissions
#method_missing
#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
Instance Method Details
#action_create ⇒ Object
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
|
# File 'lib/chef/provider/file.rb', line 244
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
|
#action_create_if_missing ⇒ Object
275
276
277
278
279
280
281
|
# File 'lib/chef/provider/file.rb', line 275
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
|
#action_delete ⇒ Object
283
284
285
286
287
288
289
290
291
|
# File 'lib/chef/provider/file.rb', line 283
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
|
#action_touch ⇒ Object
293
294
295
296
297
298
299
300
|
# File 'lib/chef/provider/file.rb', line 293
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
|
#backup(file = nil) ⇒ Object
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
|
# File 'lib/chef/provider/file.rb', line 302
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_content ⇒ Object
Compare the content of a file. Returns true if they are the same, false if they are not.
205
206
207
|
# File 'lib/chef/provider/file.rb', line 205
def compare_content
checksum(@current_resource.path) == new_resource_content_checksum
end
|
#define_resource_requirements ⇒ Object
177
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 177
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
|
#deploy_tempfile ⇒ Object
331
332
333
334
335
336
337
338
339
340
341
|
# File 'lib/chef/provider/file.rb', line 331
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
|
#diff_current(temp_path) ⇒ Object
69
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
|
# File 'lib/chef/provider/file.rb', line 69
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
|
#diff_current_from_content(new_content) ⇒ Object
49
50
51
52
53
54
55
56
57
|
# File 'lib/chef/provider/file.rb', line 49
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
|
#is_binary?(path) ⇒ Boolean
59
60
61
62
63
64
65
66
|
# File 'lib/chef/provider/file.rb', line 59
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
|
#load_current_resource ⇒ Object
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
# File 'lib/chef/provider/file.rb', line 127
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
load_current_resource_attrs
setup_acl
@current_resource
end
|
#load_current_resource_attrs ⇒ Object
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
# File 'lib/chef/provider/file.rb', line 146
def load_current_resource_attrs
if Chef::Platform.windows?
return
end
if ::File.exist?(@new_resource.path)
stat = ::File.stat(@new_resource.path)
@current_resource.owner(stat.uid)
@current_resource.mode(stat.mode & 07777)
@current_resource.group(stat.gid)
if @new_resource.group.nil?
@new_resource.group(@current_resource.group)
end
if @new_resource.owner.nil?
@new_resource.owner(@current_resource.owner)
end
if @new_resource.mode.nil?
@new_resource.mode(@current_resource.mode)
end
end
end
|
#set_all_access_controls ⇒ Object
265
266
267
268
269
270
271
272
273
|
# File 'lib/chef/provider/file.rb', line 265
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_content ⇒ Object
Set the content of the file, assuming it is not set correctly already.
210
211
212
213
214
215
216
217
218
219
220
221
|
# File 'lib/chef/provider/file.rb', line 210
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
|
#setup_acl ⇒ Object
172
173
174
175
|
# File 'lib/chef/provider/file.rb', line 172
def setup_acl
@acl_scanner = ScanAccessControl.new(@new_resource, @current_resource)
@acl_scanner.set_all!
end
|
#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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
|
# File 'lib/chef/provider/file.rb', line 226
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
stat = ::File.stat(path)
@new_resource.owner(stat.uid)
@new_resource.mode(stat.mode & 07777)
@new_resource.group(stat.gid)
end
|
#whyrun_supported? ⇒ Boolean
123
124
125
|
# File 'lib/chef/provider/file.rb', line 123
def whyrun_supported?
true
end
|