Lightningmonkey
Lightningmonkey

Reputation: 161

chef delete a directory at the end of a run

So I would like to get chef to clear out a directory AFTER the entire run finishes. I assume the way to do this is through notifies, but I am not having much luck. I have the below code which I thought would delete the cache dir (/var/chef/cache) but it never seems to run.

The logging says that the directory resource was skipped because the action was nothing (which makes sense) during the compile phase, but the action never gets run at the end through the notifies. What am I missing?

directory "delete the dir #{Chef::Config["file_cache_path"]}" do
    recursive true
    path "#{Chef::Config["file_cache_path"]}"
    action :nothing
end

s3_file "download tarball" do
    <details>
    notifies :delete, "directory[#{prefix} delete the dir #{Chef::Config["file_cache_path"]}]", :delayed
end

Upvotes: 0

Views: 3298

Answers (1)

sethvargo
sethvargo

Reputation: 26997

Chef recipes are executed in the order in which they are specified in the run_list. If you want something to be executed last, put that recipe at the end of your run_list. Using notifications is not desirable because:

  1. It's not intuitive
  2. It's not guaranteed

It's not intuitive

Imagine you are another developer on your team reviewing this code. Why does s3_file delete the file cache path? There is no comment, etc. Additionally, in a larger, more complex application, you may have notifications to multiple resources. In my experience, humans are very bad at visualizing that level of indirection, and it often causes unnecessary pain.

It's not guaranteed

There are two kinds of notifications in Chef - delayed and immediate. Immediate notifications are guaranteed to fire if the invoking resource reports it was updated by the last action. Delayed notifications, however, after everything else is finished executing. If the Chef Client Run (CCR) fails to complete successfully, those notifications will not fire. So using a delayed notification to push something to the "end" of the CCR is not guaranteed to execute.

As HolgerJust pointed out in the comments section, Chef 11 will attempt to run delayed notifications, but this is still not a guaranteed action by the Chef Client.

Furthermore (and the real point about promises here), is that Chef only fires notifications if the resource reports it was updated by the last action. Consider:

user 'sethvargo' do
  # ...
  notifies :restart, 'service[tomcat]'
end

# ...

service 'tomcat' do
  action :nothing
end

The first time this run executes, it will create the user named "sethvargo", which will send the :restart action to the tomcat service. However, on subsequent runs, the user "sethvargo" already exists, so the notification will not fire.

In your particular example, if s3_file reports that it was not updated by its last action (aka it did not alter the state of the system), the notification will not fire. That might not seem terrible, until I tell you that updated_by_last_action is a property that the cookbook developer must proxy. Additionally, it was a property that many community cookbooks did not set in the past. It is very possible that the s3_file resource does not properly record its status, and therefore does not fire notifications.

As a final note:

Deleting the Chef::Config[:file_cache_path] is probably a bad idea. If there is a specific file you need to delete, just delete that file. Or tell Chef not to backup files using backup false on your resource.

Upvotes: 1

Related Questions