This is my code:
if !::File.exist?("#{node['iis']['home']}\\backup\\BkpB4Chef")
windows_batch "Backup IIS Config" do
code <<-EOH
"#{node['iis']['home']}"\\appcmd add backup BkpB4Chef
EOH
end
end
It always says file exists and executes the loop.
As mentioned in the comments, for a deletion action, the if statement is unnecessary, as mentioned, because if chef doesn't find the file to be deleted, it will assume it was already deleted. Otherwise, you generally want to use guard properties in the resource (available for all resources), rather than wrapping a resource in an if-then.
To suggest a change, edit the directory.rb file and submit a pull request to the Chef Infra Client repository. Use the directory resource to manage a directory, which is a hierarchy of folders that comprises all of the information stored on a computer. The root directory is the top-level, under which the rest of the directory is organized.
To test if a file does not exist using the “||” operator, simply check if it exists using the “-f” flag and specify the command to run if it fails. [ [ -f <file> ]] || echo "This file does not exist!"
The basic idea of Chef is that you state the desired state of the system, and then Chef compares that to the actual state, and makes any changes needed to bring the system into the desired state. You do not need to have an if statement to check if the file exists before deleting it; Chef itself should check if the file exists if I'm not mistaken.
You should use Chef guards here. Guards specify conditional execution, but still insert the resource into the resource collection. In your example and jtblin answer, the resource is never added to the collection (which I'll explain a bit further in a moment).
Here's some working code to get you started:
windows_batch "Backup IIS Config" do
code %Q|#{node['iis']['home']}"\\appcmd add backup BkpB4Chef|
not_if { ::File.directory?("#{node['iis']['home']}\\backup\\BkpB4Chef") }
end
creates
Many non-idempotent Chef resources also support a creates
parameter, which explains what the resource does. In other words, what does the windows_batch
"create". This can be a file, directory, or executable. So, the following code is equivalent to the former answer.
windows_batch "Backup IIS Config" do
code %Q|#{node['iis']['home']}"\\appcmd add backup BkpB4Chef|
creates"#{node['iis']['home']}\\backup\\BkpB4Chef"
end
not_if
vs the conditional wrapperChef executes in two phases - the compilation phase and the convergence phase. During the compilation phase, the recipes are evaled and the resources are added to the resource collection. In the convergence phase, the resources in the resource collection are executed and evaluated against the target system. So, consider the following example:
if false
service 'foo' do
action :start
end
end
This is a fairly straight-forward recipe that starts a service based on some conditional. However, at the end of the compilation phase, the service
resource isn't added to the resource collection. Since the recipe DSL is instance_eval
ed, the wrapping if false
conditional prevents that code from ever being read by the Ruby VM. In other words, it's like that service never exists.
It's fairly common to notify resources. Later in the recipe, you might want to restart apache because of a configuration change. The "proper" way to do this is using notifications:
template '/var/www/conf.d/my.conf.file' do
# ...
notifies :restart, 'service[apache2]'
end
This template
cannot adequately notify the service resource, because it doesn't exist in the resource collection. So this recipe will fail. It seems like a trivial example, but if you change the conditional if false
to a node attribute test:
if node['cookbook']['use_apache']
service 'apache2' do
action :start
end
end
you have created a dichotomy in your cookbook where it will work 50% of the time. Unfortunately most cookbooks are much more complex than two resources, so the number of edge cases where a resource can notify a non-existent resource drastically increases with complexity. This is all solvable (and exhibits the correct behavior) using resource guards:
service 'apache2' do
action :start
only_if { node['cookbook']['use_apache'] }
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With