我有以下(简化)配方java,当然要安装Java。
文件食谱/ default.rb
include_recipe "install_java"
文件食谱/ install_java.rb
# Install RPM from yum repo via yum_install library function
yum_install("jdk1.7.0_51")
# List the directories in /usr/java
jdk_dir = `ls -ld /usr/java/jdk1.* | sort | tail -1`
if jdk_dir.empty?
raise "Missing JDK installation"
end
当我通过“chef-client -o recipe [java]”
运行食谱时Synchronizing Cookbooks:
- java
Compiling Cookbooks...
ls: /usr/java/jdk1.*: No such file or directory
=============================================== ============================ /var/chef/cache/cookbooks/java/recipes/default.rb中的配方编译错误============================== =============================================
RuntimeError
------------
Missing JDK installation
似乎没有调用yum_install()函数。但是,如果我将install_java.rb配方修改为只有
# Install RPM from yum repo via yum_install library function
yum_install("jdk1.7.0_51")
它有效。
为什么会这样?
答案 0 :(得分:33)
好的,所以厨师跑了两次。
我喜欢称之为收集阶段
此时,运行配方中的实际ruby代码。这意味着任何声明
jdk_dir = ls -ld /usr/java/jdk1.* | sort | tail -1
将在那时执行。但是,创建Chef资源yum_install("jdk1.7.0_51")
的ruby代码仅创建资源。然后将由配方代码创建的资源添加到Chef resource_collection 中,但资源操作尚未运行。
我称之为解决阶段。 此时 - 在所有配方运行(创建资源,但没有运行操作)之后 - 我们现在准备好实际运行资源操作。 Chef从 resource_collection 中的第一个资源开始,并在该资源上运行指定的操作。它通过集合工作,根据需要调用通知,直到所有资源的操作都已运行。然后你的跑完了。
因此,在您的情况下,您尝试访问收集阶段中的目录,但在解决阶段之前不会创建目录。如果您想在解决阶段期间运行ruby代码,则可以在ruby_block
资源中执行此操作。例如:
ruby_block 'verify java is there' do
block do
if jdk_dir.empty?
raise "Missing JDK installation, reinstall"
end
end
end
如果此ruby_block
资源放在yum_install
(可能是yum_package
)资源之后,那么它将放在 collection_phase中的安装资源之后,然后在Chef运行的解决阶段(即运行时)期间执行。
答案 1 :(得分:7)
所以我不能完全确定,但yum_install
可能是一种资源(或某种创建资源的帮助者)。食谱有效地运行两次。首先执行每个文件(实际上是通过Ruby的exec
)。当在DSL中创建资源时,它“编译”到内存中的资源对象,该对象被添加到全局资源集合(所有资源的大数组)。编译完所有配方文件后,Chef循环遍历资源集合并按要求运行每个资源的操作(如果需要,在中间发送通知)。
总而言之,这意味着yum_install
行在将对象推入数组时不会实际执行任何操作。您可以将其他代码包装在ruby_code
块中,以将其延迟到收敛时间。
答案 2 :(得分:2)
最好的办法是使用Unified_mode而不是配方来编写自定义资源:
resources / install_java.rb:
unified_mode true
provides :install_java
action :install do
# Install RPM from yum repo via yum_install library function
yum_install("jdk1.7.0_51")
# List the directories in /usr/java
jdk_dir = `ls -ld /usr/java/jdk1.* | sort | tail -1`
if jdk_dir.empty?
raise "Missing JDK installation"
end
end
食谱/default.rb:
install_java "install my java -- you could make this name_property the version"
统一模式消除了编译/收敛两阶段解析,因此可以工作,但是必须将代码移至自定义资源(这会带来额外的可用性好处,并且无论如何都是最佳实践,因为现在资源可以增加属性并可以重复使用以安装不同版本的Java等)。