How can I change a file with Chef?

40,402

Solution 1

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:

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.

Solution 2

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')

Solution 3

As of 2020, the solutions provided are discouraged - see here and here.

The modern way of performing file manual editing is to use the official, community-maintained, cookbook line.

Example:

replace_or_add "why hello" do
  path "/some/file"
  pattern "Why hello there.*"
  line "Why hello there, you beautiful person, you."
end

It's crucial, before using such strategy, to be 100% sure that manual editing is really required, but this is strictly dependent on the use case.

Share:
40,402
Marcelino Juarez Valderrama
Author by

Marcelino Juarez Valderrama

Updated on September 17, 2020

Comments

  • Marcelino Juarez Valderrama
    Marcelino Juarez Valderrama over 3 years

    I have 7 files and 1 war. I need to change values when I deploy them. I have this:

    ##usuario
    #alfresco.user=*****
    alfresco.user=********
    ##pass 
    #alfresco.password= sfsfs
    alfresco.password=sfgsf
    
    alfresco.rutaAnexos=/gthtfdh/dfgdf/cm:
    
    #atributo.type.anexo=ANEXO_INFO_OBJETO
    atributo.type.anexo=AN
    atributo.type.observaciones=OBSERVACIONES
    

    I need to comment some lines and uncomment some other lines. Then I need to make seven templates and put variables depending on the environments and create a file in the recipe.

    How can I do this?