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
Thanks,
Piotr