Prevent chef recipe from executing previously executed action

chefchef-solo

I have a simple recipe like the following, and currently I am using a local file to indicate if the command has been run or not

execute "test" do
  command "sh test.sh && touch /opt/myapp/done.log"
  only_if {File.exists?("/opt/myapp/done.log")}
end

Are there better method? It is the recommended way?

Best Answer

This is generally the method I use, especially if the command you take results in a file being created as a side effect For example disabling or enabling sites in Debian's apache2 package removes or creates links in /etc/apache2 which you can test for using File.exists?.

A trick is to set an attribute after the execute resource has run:

if !node["did_test"]
  execute "test" do
    command "touch /tmp/foo"
  end
end

ruby_block "did_test" do
  block do
    node.normal["did_test"] = true
  end
end

Note that it's still possible for the execute resource to be run twice in some situations so this technique isn't perfect, but you can now use knife-search to determine which nodes have performed the execute.