Chef: create a directory for a template if it doesn’t already exist

chefchef-solo

If I have a template being created, how can I ensure that the directory exists? For instance:

template "#{node[:app][:deploy_to]}/#{node[:app][:name]}/shared/config/database.yml" do
  source 'database.yml.erb'
  owner node[:user][:username]
  group node[:user][:username]
  mode 0644
  variables({
    :environment => node[:app][:environment],
    :adapter => node[:database][:adapter],
    :database => node[:database][:name],
    :username => node[:database][:username],
    :password => node[:database][:password],
    :host => node[:database][:host]
  })
end

This fails since /var/www/example/shared/config does not exist for database.yml to be copied into. I'm thinking of how puppet allows you to "ensure" a directory exists.

Best Answer

Use the directory resource to create the directory before creating the template. The trick is to also specify the recursive attribute otherwise the action will fail unless all parts of the directory but the last exist already.

config_dir = "#{node[:app][:deploy_to]}/#{node[:app][:name]}/shared/config"

directory config_dir do
  owner node[:user][:username]
  group node[:user][:username]
  recursive true
end

template "#{config_dir}/database.yml" do
  source "database.yml.erb"
  ...
end

Note that the owner and group of the directory resource are only applied to the leaf directory when it's being created. The permissions of the rest of the directory are undefined, but will probably be root.root and whatever your umask is.