【发布时间】:2019-06-21 13:34:31
【问题描述】:
我对 Chef 比较陌生,我第一次尝试使用 :before 计时器来发送一些通知。这个想法很简单:我有一个自定义资源,它从存储库中提取工件,将其保存到暂存目录,然后将其部署到部署目录。如果自定义资源发现必须部署工件,则将当前部署备份到备份目录并部署新工件。如果不需要部署工件(由于下面的 not_if { some_condition } 行),则不会运行备份步骤(这是使用通知的全部意义,因为备份步骤仅通过通知触发)。
为了实现此功能,我使用action :nothing 创建了几个资源,并使用通知和:before 计时器从我的自定义资源中运行它们(见下文)。我尝试的每次运行都将some_condition 评估为假。
# SNIPPET 1 - This is my intended code, whose behavior I can't understand.
# All backup actions are set to :nothing and will be triggered
# only if some_condition is false.
directory "delete #{backup_dir}" do
recursive true
path backup_dir
action :nothing
end
directory "create #{backup_dir}" do
owner node['my_cookbook']['owner']
group node['my_cookbook']['group']
path backup_dir
mode '0755'
recursive true
action :nothing
end
execute 'backup current deployment' do
command "mv #{deployments_dir} #{backup_dir}"
action :nothing
only_if { ::Dir.exists?(deployments_dir) }
end
directory "create #{deployments_dir}" do
path deployments_dir
owner node['my_cookbook']['owner']
group node['my_cookbook']['group']
mode "0755"
recursive true
action :nothing
end
node['my_cookbook']['artifacts'].each do |artifact_name|
config = my_environment(artifact_name, node)
# This custom resource downloads the artifact to a staging directory
# and then moves it to deployments_dir.
my_artifact_cache "my_cookbook::deploy_artifacts - Pull cached artifact #{artifact_name}" do
snapshot config['repository'] == 'snapshot'
group_id config['group_id']
artifact_id config['artifact_id']
version config['version']
filetype config['filename_extension']
path deployments_dir
owner node['my_cookbook']['owner']
group node['my_cookbook']['group']
mode "0755"
action :pull
not_if { some_condition }
notifies :delete, "directory[delete #{backup_dir}]", :before
notifies :create, "directory[create #{backup_dir}]", :before
notifies :run, 'execute[backup current deployment]', :before
notifies :create, "directory[create #{deployments_dir}]", :before
end
end
但是,每次我运行上面的代码时,my_artifact_cache 自定义资源中的一些操作都会被跳过,我不知道为什么。这会导致运行失败,因为暂存目录(与我通过通知实际操作的目录无关)不是从自定义资源中创建的。没有通知,日志显示- created directory /staging/dir,而通知我得到- Would create new directory /staging/dir。
当我运行下面的第二个 sn-p 时,一切正常。我希望这两个 sn-ps 在some_condition 为假的情况下是等价的。为什么通知似乎会影响通知资源的行为?我错过了什么吗?
# SNIPPET 2 - Commented out the :nothing actions, replaced them with the actions
# from the notifications - this snippet works as expected. I expected
# snippet 1 to be equivalent during runtime if some_condition is false
directory "delete #{backup_dir}" do
recursive true
path backup_dir
#action :nothing
action :delete
end
directory "create #{backup_dir}" do
owner node['my_cookbook']['owner']
group node['my_cookbook']['group']
path backup_dir
mode '0755'
recursive true
#action :nothing
end
execute 'backup current deployment' do
command "mv #{deployments_dir} #{backup_dir}"
#action :nothing
only_if { ::Dir.exists?(deployments_dir) }
end
directory "create #{deployments_dir}" do
path deployments_dir
owner node['my_cookbook']['owner']
group node['my_cookbook']['group']
mode "0755"
recursive true
#action :nothing
end
node['my_cookbook']['artifacts'].each do |artifact_name|
config = my_environment(artifact_name, node)
# This custom resource downloads the artifact to a staging directory
# and then moves it to deployments_dir.
my_artifact_cache "my_cookbook::deploy_artifacts - Pull cached artifact #{artifact_name}" do
snapshot config['repository'] == 'snapshot'
group_id config['group_id']
artifact_id config['artifact_id']
version config['version']
filetype config['filename_extension']
path deployments_dir
owner node['my_cookbook']['owner']
group node['my_cookbook']['group']
mode "0755"
action :pull
not_if { some_condition }
#notifies :delete, "directory[delete #{backup_dir}]", :before
#notifies :create, "directory[create #{backup_dir}]", :before
#notifies :run, 'execute[backup current deployment]', :before
#notifies :create, "directory[create #{deployments_dir}]", :before
end
end
【问题讨论】:
-
:before 通知可能是解决此问题的错误方法,但可能发生的情况是 my_artifact_cache 里面的所有子资源都没有正确写入为什么运行安全并正确报告如果它们在为什么运行模式下运行时会更新。如果您追踪并修复了所有运行原因的错误,那么 :before 通知应该可以工作。
-
将执行备份的代码放入资源本身可能会更好,并且使用纯 ruby FileUtils/File/Dir 调用以命令式方式编写它可能会更好,而不是使用声明性厨师资源。您使用执行资源来触发 mv 的方式在这里有些代码味道。