In this part of a Chef recipe, there are 4 execute
resources. They should only run when a file does not exists. This is added as a condition to the first resource, which then triggers the entire chain to be run.
# Set up default SSL cert
execute "defaultcert1" do
not_if {File.exist?("/vol/webserver/cert")}
command "mkdir /vol/webserver/cert"
notifies :run, "execute[defaultcert2]", :immediately
end
execute "defaultcert2" do
action :nothing
command "ln -s /etc/ssl/certs/ssl-cert-snakeoil.pem /vol/webserver/cert/server.crt"
notifies :run, "execute[defaultcert3]", :immediately
end
execute "defaultcert3" do
action :nothing
command "ln -s /etc/ssl/private/ssl-cert-snakeoil.key /vol/webserver/cert/server.key"
notifies :run, "execute[defaultcert4]", :immediately
end
execute "defaultcert4" do
action :nothing
command "chown -R ubuntu:ubuntu /vol/webserver/cert"
end
As you can see, it's a rather large bit of code to guard just 4 commands. Is there a better way to do this?
For your particular example, I'd suggest using Chef's
directory
andlink
resources, in preference to shelling out:You don't need to guard these with
not_if
's and notifies - if the directory and links already exist with the correct attributes, Chef won't do anything.On the other hand, say you want to use the snakeoil cert and key if nothing's there to begin with, but do nothing if the files already exist. In that case, I'd use
not_if
on the link resources:Compared to a string of
execute
resources, this communicates intent more clearly - it says that a directory needs to exist (with the correct user and group), and that a couple of symlinks should be created unless something is already present.Finally, if you did have several related shell commands you needed to execute together, consider using the
script
resource.