如何 include_recipe 进入 ruby_block 的厨师食谱

How to include_recipe inside a ruby_block of a chef recipe

我有一个食谱,它在 ruby_block 中设置了一个变量,并且需要将该变量用作食谱的输入属性。 ruby_block 执行后如何使用 include_recipe?

谢谢

ruby_block "evaluate_config" do #~FC014
 block do

  file = File.read('/opt/config/baselogging.json')
  data = JSON.parse(file)

  node.default['kibana']['apache']['basic_auth_username'] = data['KibanaUser']
  node.default['kibana']['apache']['basic_auth_password'] = data['KibanaPassword']

  include_recipe 'kibana'

 end
end

您可以从 ruby 块中读取和设置属性,然后您可以在其后包含如下配方:

ruby_block "evaluate_config" do #~FC014
 block do   
  file = File.read('/opt/config/baselogging.json')
  data = JSON.parse(file)

  node.set['kibana']['apache']['basic_auth_username'] = data['KibanaUser']
  node.set['kibana']['apache']['basic_auth_password'] = data['KibanaPassword']   
 end
end

include_recipe 'kibana'

要包含来自 ruby_block 的食谱,您必须使用 run_context 调用它。

例如:

ruby_block "evaluate_config" do #~FC014
 block do
   ...
   #include_recipe 'kibana'
   run_context.include_recipe "cookbook::recipe"
 end
end

这里的问题似乎是 kibana cookbook 有一个默认配方,它在使用 node['kibana']['apache']['basic_auth_username'] 和密码节点属性时没有 lazy {} 修饰符。

看起来这里有很多工作要做,以懒惰一切并出于我不明白的原因使用 ruby_block。更好的方法是不使用 ruby_block:

file = File.read('/opt/config/baselogging.json')
data = JSON.parse(file)

node.default['kibana']['apache']['basic_auth_username'] = data['KibanaUser']
node.default['kibana']['apache']['basic_auth_password'] = data['KibanaPassword']

include_recipe 'kibana'

如果 chef 本身负责生成 baselogging.json 而你试图生成 baselogging.json 然后从 baselogging.json 中读取我想出的解决方案是重构并删除:

data = ... stuff to populate the data ...

file "/opt/config/baselogging.json" do
  content JSON.generate(data)
end

[...]

node.default['kibana']['apache']['basic_auth_username'] = data['KibanaUser']
node.default['kibana']['apache']['basic_auth_password'] = data['KibanaPassword']

include_recipe 'kibana'

即使当前某处有 remote_file 资源创建 baselogging.json,您最好还是这样做:

# "cheat" and download the file at compile-time
remote_file "/opt/config/baselogging.json" do
   source "http://example.org/baselogging.json"
   action :nothing
end.run_action(:create)

file = File.read('/opt/config/baselogging.json')
data = JSON.parse(file)

node.default['kibana']['apache']['basic_auth_username'] = data['KibanaUser']
node.default['kibana']['apache']['basic_auth_password'] = data['KibanaPassword']

include_recipe 'kibana'

这里更重要的一点是,lazy {} 越来越多地引发懒惰行为的军备竞赛,如果你在你无法控制的范围内消费食谱,那么它会变得越来越丑陋。整个问题有很多 "code smell" 迫使事情发生得越来越晚,最终与所有事物的架构方式作斗争。你最好回去重构你的假设,这样你就可以在厨师中推进更多的工作 运行。

一般情况下,您会在属性文件解析阶段尝试编译节点属性中的所有信息。在食谱代码中设置属性会导致类似这样的问题,并最终导致您发现自己想要向现有的每本社区食谱提交 PR,以懒惰他们使用的所有属性。使用资源驱动库说明书而不是属性和配方驱动程序库说明书可以帮助回避整个过程。除非你应该尽早 assemble 节点数据,这样你就不必延迟对节点数据的所有访问。

如果您必须在配方代码中构建节点数据,那么您必须在编译时构建该数据。尝试在配方收敛时间设置节点数据是您有点迷路的症状。