在Chef食谱中编译时间与运行时间

时间:2014-09-22 18:29:08

标签: chef

我有以下(简化)配方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")

它有效。

为什么会这样?

3 个答案:

答案 0 :(得分:33)

好的,所以厨师跑了两次。

“编译时间”

我喜欢称之为收集阶段 此时,运行配方中的实际ruby代码。这意味着任何声明 jdk_dir = ls -ld /usr/java/jdk1.* | sort | tail -1  将在那时执行。但是,创建Chef资源yum_install("jdk1.7.0_51")的ruby代码仅创建资源。然后将由配方代码创建的资源添加到Chef resource_collection 中,但资源操作尚未运行。

“Converge Time”

我称之为解决阶段。 此时 - 在所有配方运行(创建资源,但没有运行操作)之后 - 我们现在准备好实际运行资源操作。 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等)。