Chef infra 与厨师一起,如何执行;资源1“;“之前”;资源2“;,以“为条件”;资源2“;执行?
我有一本厨师烹饪书,里面有多种食谱,可以安装一项服务。按照chef客户端的工作方式,它每15分钟(或其他一些常规间隔)重新聚合一次。现在,我的食谱的第一步是停止服务,因此服务将每15分钟停止一次,但我真的想避免这种情况。问题是需要停止服务以执行某些步骤 如果我的食谱资源中只有一两个条件,我可以简单地做:Chef infra 与厨师一起,如何执行;资源1“;“之前”;资源2“;,以“为条件”;资源2“;执行?,chef-infra,chef-recipe,Chef Infra,Chef Recipe,我有一本厨师烹饪书,里面有多种食谱,可以安装一项服务。按照chef客户端的工作方式,它每15分钟(或其他一些常规间隔)重新聚合一次。现在,我的食谱的第一步是停止服务,因此服务将每15分钟停止一次,但我真的想避免这种情况。问题是需要停止服务以执行某些步骤 如果我的食谱资源中只有一两个条件,我可以简单地做: condition1 = ... # some true/false values condition2 = ... # service myservice do only_if { co
condition1 = ... # some true/false values
condition2 = ... #
service myservice do
only_if { condition1 or condition2 }
action :stop
end
resource1 do
only_if { condition1 }
end
resource2 do
only_if { condition2 }
end
但由于我有十几个条件,在多个食谱中,它变得不雅观。有没有一种方法可以实现这个伪代码的功能
service_resource = service myservice do
# somehow don't execute this right now, but wait for
# signal from resource1 or resource2
action :stop
end
resource1 do
make sure service_resource executed first
only_if { condition1 }
end
resource2 do
make sure service_resource executed first
only_if { condition2 }
end
如果Chef中有一些“notifies:before”机制(而不是“notifies:installent”),我可以使用它,但我还没有找到类似的机制。有什么想法吗
编辑:
在进一步考虑这一点之后,另一种方法仍然不完美,但更好,就是利用Chef的编译阶段,定义一个被覆盖的属性。这样至少我们不必把所有的条件都放在一个地方
# in an "attributes" file:
default["stop_service"] = false
# in some recipe:
service myservice do
action :stop
only_if { node["stop_service"] }
end
# ... later, or in some other recipe file
condition1 = ... # true/false
if condition1
# I think this executes before the only_if of the "service" resource
override["stop_service"] = true
end
resource1 do
only_if { condition1 }
end
我要做的是:
在“暂存”位置暂存配置,如果此更改通知停止、复制文件、启动服务
大致上:
service "my_service" do
action :nothing
end
template "/staging/conf1" do
[... usual attributes ...]
notifies :stop,"service[my_service]",:immediately
end
template "/staging/conf2" do
[... usual attributes ...]
notifies :stop,"service[my_service]",:immediately
end
remote_file "/opt/my_service/etc/conf1" do
source "/staging/conf1"
notifies :start,"service[my_service]" # delayed here to allow all conf files to be updated.
end
remote_file "/opt/my_service/etc/conf2" do
source "/staging/conf2"
notifies :start,"service[my_service]" # delayed here to allow all conf files to be updated.
end
我的个人爱好是使用相同的资源循环使用此类选项的文件/模板定义哈希,如:
node['my_namespace']['conf_files']['conf1'] = "template1"
node['my_namespace']['conf_files']['conf2'] = "template2"
然后循环使用
node['my_namespace']['conf_files'].each do |cfgfile,tmplname|
template "/staging/#{cfgfile}" do
source tmplname
notifies :stop,"service[my_service]",:immediately
end
remote_file "/opt/my_service/etc/#{cfgfile}" do
source "/staging/#{cfgfile}"
notifies :start,"service[my_service]"
end
end
对于更复杂的用例,您也可以使用散列而不是单个值
如果涉及2个以上的资源(在替换实际的conf文件之前,执行conf文件的特定命令来验证它,等等),则可以使用一个定义
另一种可能是在LWRP的
load\u current\u resource
中执行所有暂存工作,但对于所描述的用例来说,我可能做得太过分了。UNIXlike操作系统上的大多数服务都可以进行配置(或者甚至是代码,只要本地包管理器通过创建新的inode而不是重写现有inode以具有新内容来替换文件)实时更新,这就是为什么这不是一个常见问题的原因——大多数情况下,服务在重新配置或升级之前不需要停止。@CharlesDuffy最终可能就是我所依赖的,但我写的实际上是一个简化:我们有一组服务,我不确定它们是否都可以配置在运行时更改。我认为至少其中一个会自动重新加载其配置,这样它可以在仅应用部分更改时重新加载。此外,对于某些配方,我们会在现有文件中追加/替换,因此在这些情况下,我们不会使用新的索引节点(如果我正确理解您的意思)。具体取决于追加/替换功能的工作方式——安全实现(当追加的数据超出一个系统调用的范围时,或者当需要进行任何就地编辑时)通过在同一目录中写入临时文件并在目标上重命名来工作。但是,是的,重新启动是有意义的(或SIGSTOP和SIGCONT,如果支持的话)围绕配置更改,如果您希望这些更改是原子性的,则会修改多个文件,并实现自动重新加载行为。实际上,我没有意识到这一点,但您是对的。大多数时候,我们使用的是“sed-I”(“inplace”,我刚刚读过,它与您描述的一样)。在其他一些情况下,我们使用Chef::Util:FileEdit,它并没有完全按照您描述的那样做,但保留了旧文件的备份,因此旧inode仍然未被触及(我认为)。谢谢@Tensibai。我认为它可能适用于某些类型的资源,但它确实会影响食谱的结构。我正试图避免如此大的变化,并尽可能使食谱“自然”,这就是为什么我要寻找“通知:之前”(这需要“厨师资源队列”的一些魔力)之类的东西…但如果它不在框架内,就没什么可做的了。)@fsdj好吧,这个案子已经讨论过了,有一些关于它的审判。关于票中链接的PR的评论告诉我们为什么它实际上不在chef中。哦,哇,这正是我的意思。所以是的,我想现在在chef中真的不可行(“没有大的重构”,正如公关所说)。资源之间的“依赖”会更好(避免像有人提到的那样多次运行前一步)。非常感谢,这样可以避免进一步无用的挖掘。