Notification, ruby_block and file patching


#1

Hello,

According to the this discussion and my observations the ruby_block resource is always updated which has an impact when trying to use notifications.
While ruby_block should generally be avoided in favor of more specific resources I am using it for a task that is not handled by default resources - patching configuration files before starting/restarting a service. I know the preferred way is to use the template resource but sometimes it is easier to patch one line of a configuration file than maintain a template file.

My current solution is as follows.

# Helper method to patch file that returns status if the file has been updated
def file_cond_replace_line(path, regex, replace, cond_regex)  
  FileUtils.touch(path) unless ::File.exist?(path)
  File.open(path, 'r') do |f|
    f.each_line do |line|
      return false if line =~ /#{cond_regex}/
    end
  end

  file = Chef::Util::FileEdit.new(path)
  file.search_file_replace_line(/#{regex}/, replace)
  file.write_file
  true
end

config_changed_action = "myservice config changed"
# The content of a file specified by config_path:
# param1 myparam1value
# param2 someothervalue
ruby_block "Setting some parameters in #{config_path} file" do
  block do
    updated = false
    updated = file_cond_replace_line(config_path, '^param1', 'param1 myparam1value', 'param1\s+myparam1value\b') || updated
    #...
    updated = file_cond_replace_line(config_path, '^param2', 'param2 myparam2value', 'param2\s+myparam2value\b') || updated
    node.set[:myservice][:config_changed] = updated
  end
end

ruby_block config_changed_action do
  block { node.set[:myservice][:config_changed] = true }
  action :nothing
end

ruby_block "restart myservice" do
  block {}
  notifies :restart, "service[myservice]"
  only_if { node[:myservice][:config_changed]  }
  action :nothing
end

This is quite tricky. Do you see a more simple way of doing it? I am writing this as I think this is a quite popular pattern at least in my case :slight_smile:

Thanks,
Piotr


#2

I will say that you should really use template unless it’s impossible. If it is actually impossible, then you might have a look at a cookbook like this one: https://supermarket.chef.io/cookbooks/line which will give you well-behaved resources for line editing which will cause notifications to just work.


#3

Thanks, I will give it a try.