How can I change a file with Chef?
Chef actually allows and uses this. You can find an example in the opscode's
cookbooks/chef-server/recipes/default.rb
:
ruby_block "ensure node can resolve API FQDN" do
block do
fe = Chef::Util::FileEdit.new("/etc/hosts")
fe.insert_line_if_no_match(/#{node['chef-server']['api_fqdn']}/,
"127.0.0.1 #{node['chef-server']['api_fqdn']}")
fe.write_file
end
not_if { Resolv.getaddress(node['chef-server']['api_fqdn']) rescue false }
end
Here's the use-case. After the installation from source I had to uncomment lines in some created configuration file that hadn't been the same in all versions of software, therefore use of templates hadn't been appropriate. The methods I used were:
- (Object) search_file_replace(regex, replace)
- (Object) search_file_replace_line(regex, newline)
You may find the full documentation here:
- http://rubydoc.info/gems/chef/Chef/Util/FileEdit
TO STRESS: This method is to be used only when using templates and partials is inappropriate. As @StephenKing already said, templates are common way of doing this.
Here is an example of how you can use Chef to uncomment a line in a configuration file. The ruby_block
is protected with a ::File::grep
. The test for Debian is just for fun.
pam_config = "/etc/pam.d/su"
commented_limits = /^#\s+(session\s+\w+\s+pam_limits\.so)\b/m
ruby_block "add pam_limits to su" do
block do
sed = Chef::Util::FileEdit.new(pam_config)
sed.search_file_replace(commented_limits, '\1')
sed.write_file
end
only_if { ::File.readlines(pam_config).grep(commented_limits).any? }
end if platform_family?('debian')