Chef:可变参数的惰性评估
Chef: Lazy evaluation of variable argument
我们遇到了 Mapr 客户端安装的情况。我们希望能够复制位于 /opt/mapr/hive/hive-x.y/conf/ 目录下的自定义 hive-site.xml 文件。问题是在一组包(包括 hive)完全安装之后,我们才知道 hive 版本号。所以,像下面这样的代码是失败的:
package 'mapr-client'
...
...
dir_hive = Dir["/opt/mapr/hive/hive-*"]
template "#{dir_hive[0]}/conf/hive-site.xml" do
source "devg_hive-site.xml.erb"
mode 0644
end
模板名称似乎是在编译时评估的,此时包安装尚未完成,因此名称评估为 /conf/hive-site.xml
而不是 /opt/mapr/hive/hive-1.2/conf/site.xml
。
如果我们等待所有包完全安装并通过单独调用或执行以下代码的手动 运行:
dir_hive = Dir["/opt/mapr/hive/hive-*"]
template "#{dir_hive[0]}/conf/hive-site.xml" do
source "devg_hive-site.xml.erb"
mode 0644
end
我们已成功复制配置文件;但是,如果它是您安装和尝试配置过程的一部分,它就不起作用。以下是我们尝试过的其他一些事情:
- 尝试将代码的配置复制部分移动到单独的配方中并创建了一个 运行 列表并希望如果执行顺序保持不变,一旦包安装完成,配置单元目录将可用,因此我们将拥有正确的文件路径。那没有用。
- 将配置复制代码放在 ruby_block、lazy evluator only_if(检查 /opt/mpar/hive 目录)等下。运气不好。
- 将源 xml 文件复制到 /tmp/ 目录,试图在 /opt/mapr/hive 目录可用时简单地复制文件,再次使用惰性计算器,ruby_block,等等。仍然失败。
- 试图通过 ruby_block 中的循环尝试检查
if !Dir.glob('/opt/mapr/hive/hive-*/conf/hive-site.xml').empty?
并休眠 5 秒。失败。
上面的一些其他变体也没有成功;在所有这些情况下,"#{dir_hive[0]}/conf/hive-site.xml"
似乎在编译时得到评估,因此产生了错误的文件路径。
使用通配符捕获已安装文件路径然后使用该路径进行某些操作(例如用自定义配置文件替换配置文件)的最佳方法是什么。
或者,我们能否在执行某些操作后延迟计算表达式以产生变量名,并且延迟计算的变量名取决于操作后出现的文件名?
感谢您的宝贵时间,感谢您的指点!
它非常 'smelly' 并且它可能会影响您的升级。因为较新的版本会有更高的数字。所以你可以尝试使用 last
而不是 first
.
template "hive-site.xml" do
path lazy { "#{Dir['/opt/mapr/hive/hive-*'].last}/conf/hive-site.xml" }
source "devg_hive-site.xml.erb"
end
我不确定这在您的代码中有多常见,但您可以考虑 resource/code 将从包(元数据或列表文件)中提取路径。
编辑。我有第二个想法。包可能会记录在 node["packages"]
中,版本可以映射到你的路径,你可以使用它并删除 Dir
(你仍然需要惰性块),你可能需要 运行 ohai 插件在安装包后刷新 node["packages"]
(我想你可以为此使用通知)。
它可能看起来类似于:
ohai "reload packages" do
plugin "packages"
action :nothing
end
package "mapr-client" do
notifies :reload, "ohai[reload packages]", :immediately
end
template "hive-site.xml" do
path lazy { "/opr/mapr/hive/hive-#{node["packages"]["mapr-client"]["version"]}/conf/hive-site.xml" }
source "devg_hive-site.xml.erb"
end
不幸的是,版本可能不会映射到目录结构。这个包太糟糕了;-)
我们遇到了 Mapr 客户端安装的情况。我们希望能够复制位于 /opt/mapr/hive/hive-x.y/conf/ 目录下的自定义 hive-site.xml 文件。问题是在一组包(包括 hive)完全安装之后,我们才知道 hive 版本号。所以,像下面这样的代码是失败的:
package 'mapr-client'
...
...
dir_hive = Dir["/opt/mapr/hive/hive-*"]
template "#{dir_hive[0]}/conf/hive-site.xml" do
source "devg_hive-site.xml.erb"
mode 0644
end
模板名称似乎是在编译时评估的,此时包安装尚未完成,因此名称评估为 /conf/hive-site.xml
而不是 /opt/mapr/hive/hive-1.2/conf/site.xml
。
如果我们等待所有包完全安装并通过单独调用或执行以下代码的手动 运行:
dir_hive = Dir["/opt/mapr/hive/hive-*"]
template "#{dir_hive[0]}/conf/hive-site.xml" do
source "devg_hive-site.xml.erb"
mode 0644
end
我们已成功复制配置文件;但是,如果它是您安装和尝试配置过程的一部分,它就不起作用。以下是我们尝试过的其他一些事情:
- 尝试将代码的配置复制部分移动到单独的配方中并创建了一个 运行 列表并希望如果执行顺序保持不变,一旦包安装完成,配置单元目录将可用,因此我们将拥有正确的文件路径。那没有用。
- 将配置复制代码放在 ruby_block、lazy evluator only_if(检查 /opt/mpar/hive 目录)等下。运气不好。
- 将源 xml 文件复制到 /tmp/ 目录,试图在 /opt/mapr/hive 目录可用时简单地复制文件,再次使用惰性计算器,ruby_block,等等。仍然失败。
- 试图通过 ruby_block 中的循环尝试检查
if !Dir.glob('/opt/mapr/hive/hive-*/conf/hive-site.xml').empty?
并休眠 5 秒。失败。
上面的一些其他变体也没有成功;在所有这些情况下,"#{dir_hive[0]}/conf/hive-site.xml"
似乎在编译时得到评估,因此产生了错误的文件路径。
使用通配符捕获已安装文件路径然后使用该路径进行某些操作(例如用自定义配置文件替换配置文件)的最佳方法是什么。
或者,我们能否在执行某些操作后延迟计算表达式以产生变量名,并且延迟计算的变量名取决于操作后出现的文件名?
感谢您的宝贵时间,感谢您的指点!
它非常 'smelly' 并且它可能会影响您的升级。因为较新的版本会有更高的数字。所以你可以尝试使用 last
而不是 first
.
template "hive-site.xml" do
path lazy { "#{Dir['/opt/mapr/hive/hive-*'].last}/conf/hive-site.xml" }
source "devg_hive-site.xml.erb"
end
我不确定这在您的代码中有多常见,但您可以考虑 resource/code 将从包(元数据或列表文件)中提取路径。
编辑。我有第二个想法。包可能会记录在 node["packages"]
中,版本可以映射到你的路径,你可以使用它并删除 Dir
(你仍然需要惰性块),你可能需要 运行 ohai 插件在安装包后刷新 node["packages"]
(我想你可以为此使用通知)。
它可能看起来类似于:
ohai "reload packages" do
plugin "packages"
action :nothing
end
package "mapr-client" do
notifies :reload, "ohai[reload packages]", :immediately
end
template "hive-site.xml" do
path lazy { "/opr/mapr/hive/hive-#{node["packages"]["mapr-client"]["version"]}/conf/hive-site.xml" }
source "devg_hive-site.xml.erb"
end
不幸的是,版本可能不会映射到目录结构。这个包太糟糕了;-)