这是我的代码:
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
它总是说文件存在并执行循环。
这是我的代码:
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
它总是说文件存在并执行循环。
你应该在这里使用厨师警卫。Guards 指定条件执行,但仍将资源插入到资源集合中。在您的示例和 jtblin 答案中,资源永远不会添加到集合中(稍后我将进一步解释)。
这是一些可以帮助您入门的工作代码:
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
许多非幂等 Chef 资源也支持一个creates
参数,该参数解释了资源的作用。换句话说,windows_batch
“创造”了什么。这可以是文件、目录或可执行文件。因此,以下代码等效于前一个答案。
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 条件包装器Chef 分两个阶段执行——编译阶段和收敛阶段。在编译阶段,会评估配方并将资源添加到资源集合中。在收敛阶段,针对目标系统执行和评估资源集合中的资源。因此,请考虑以下示例:
if false
service 'foo' do
action :start
end
end
这是一个相当简单的方法,它根据某些条件启动服务。但是,在编译阶段结束时,service
资源不会添加到资源集合中。由于配方 DSL 是instance_eval
ed,包装if false
条件防止该代码被 Ruby VM 读取。换句话说,就像该服务从未存在一样。
通知资源是相当普遍的。在本节的后面部分,您可能因为配置更改而需要重新启动 apache。执行此操作的“正确”方法是使用通知:
template '/var/www/conf.d/my.conf.file' do
# ...
notifies :restart, 'service[apache2]'
end
这template
不能充分通知服务资源,因为它不存在于资源集合中。所以这个食谱会失败。这似乎是一个微不足道的例子,但如果您将条件更改if false
为节点属性测试:
if node['cookbook']['use_apache']
service 'apache2' do
action :start
end
end
你已经在你的食谱中创建了一个二分法,它将在 50% 的时间里起作用。不幸的是,大多数食谱比两个资源复杂得多,因此资源可以通知不存在的资源的边缘情况的数量随着复杂性的增加而急剧增加。使用资源守卫可以解决所有问题(并表现出正确的行为):
service 'apache2' do
action :start
only_if { node['cookbook']['use_apache'] }
end
使用Dir.exists?
. 您也可以if ! condition
用unless condition
which 读取更好一些。
unless Dir.exist? "#{node['iis']['home']}\\backup\\BkpB4Chef"
windows_batch "Backup IIS Config" do
code <<-EOH
"#{node['iis']['home']}"\\appcmd add backup BkpB4Chef
EOH
end
end