Chef pain point: Modifying 2+ lines but not an entire file

I’m suffering some pain modifying server configuration files with Chef.

Chef::Util::FileEdit is great for replacing one line with another, as many times as desired:

ruby_block "provide dovecot with custom MySQL connection info" do
  block do
    file = Chef::Util::FileEdit.new("/etc/dovecot/dovecot-sql.conf.ext")
    file.search_file_replace_line(/#driver = /,"driver = mysql")
    file.search_file_replace_line(/#connect = /,"connect = host=127.0.0.1 dbname=mail user=mailuser password=new_pw")
    file.search_file_replace_line(/default_pass_scheme/,"default_pass_scheme = SHA512-CRYPT")
    file.search_file_replace_line(/password_query/,"password_query = select email as user, password from users where email = '%u';")
    file.write_file
  end
end

And templates are great for replacing entire files:

template "/etc/dovecot/conf.d/10-master.conf" do
  source "10-master.conf.erb"
  mode 0640
  owner "vmail"
  group "dovecot"
end

But I can’t figure out how to replace a multi-line code block in a file. The articles I’ve read suggest Chef tries to force users into replacing whole files. cassianoleal answers a question about how to do so with, “As you said yourself, the recommended Chef pattern is to manage the whole file.” Why must we copy entire files to replace one block of code with another? Chef 11 apparently includes “partials,” which let you insert multi-line code elements. Chef::Util::FileEdit also lets you do that. But the ability to insert multiple lines doesn’t enable deleting multi-line code blocks. I probably could copy the entire file into memory, search-and-replace the multi-line segment with a regex and write the modified file back, but shouldn’t this be a built-in Chef tool?

Posted by James on Monday, March 17, 2014