Chef infra 厨师食谱中的编译时与运行时

Chef infra 厨师食谱中的编译时与运行时,chef-infra,Chef Infra,我有下面的(简化的)方法叫做java,当然是安装java 文件recipes/default.rb include_recipe "install_java" 文件recipes/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

我有下面的(简化的)方法叫做java,当然是安装java

文件recipes/default.rb

include_recipe "install_java"
文件recipes/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]”运行菜谱时

=========================================================================== /var/chef/cache/cookbooks/java/recipes/default.rb中的配方编译错误===========================================================================

RuntimeError
------------
Missing JDK installation
似乎没有调用yum\u install()函数。但是,如果我修改install_java.rb配方,只需

# Install RPM from yum repo via yum_install library function
yum_install("jdk1.7.0_51")
它起作用了


这是为什么?

所以我不能完全确定,但很可能
yum\u install
是一种资源(或创建资源的某种助手)。配方有效地分两次运行。首先执行每个文件(通过Ruby的
exec
)。当在DSL中创建资源时,它会“编译”到内存中的资源对象,该对象被添加到全局资源集合(所有资源的一个大数组)中。编译完所有配方文件后,Chef在资源集合上循环,并根据请求运行每个资源的操作(如果需要,在其间发送通知)


因此,总而言之,这意味着
yum\u install
行在运行时除了将对象推入数组之外,实际上可能什么都不做。您可以将另一个代码包装在一个
ruby\u代码块中,以将其延迟到收敛时间。

好的,因此Chef运行需要两次

“编译时” 我想把这称为收集阶段
此时,将运行配方中的实际ruby代码。这意味着任何类似于
jdk|u dir=ls-ld/usr/java/jdk1.*sort | tail-1
都会在那个时候被执行。但是,创建Chef资源的ruby代码只创建资源。这些由您的配方代码创建的资源随后被添加到Chef资源集合中,但资源操作尚未运行

“收敛时间” 我称之为解析阶段。 在这一点上-在所有配方都运行(创建资源,但不运行操作)之后-我们现在准备实际运行资源操作。Chef从资源\u集合中的第一个资源开始,并对该资源运行指定的操作。它通过集合工作,根据需要调用通知,直到所有资源的操作都已运行。那么你的跑步就完成了

你的具体情况 因此,在您的情况下,您尝试在收集阶段访问目录,但直到解析阶段才创建目录。如果要在解析阶段运行ruby代码,可以在
ruby_块
资源中运行。例如:

ruby_block 'verify java is there' do
  block do
    if jdk_dir.empty?
      raise "Missing JDK installation, reinstall"
    end
  end
end

如果此
ruby_块
资源放在
yum_安装
(可能应该是
yum_包
)资源之后,那么它将被放在收集阶段的安装资源之后,然后在解析阶段执行(即运行时)最好的方法是使用统一模式编写自定义资源,而不是使用配方:

参考资料/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
recipes/default.rb:

install_java  "install my java -- you could make this name_property the version"

统一模式消除了编译/聚合两阶段解析,因此这是可行的,但代码必须移动到自定义资源(这会带来额外的可用性优势,而且是一种最佳实践——现在该资源可以增加属性,并且可以重新使用以安装不同版本的java等)。

谢谢。将剩下的代码包装在ruby_块中就成功了。这正是我想要的解释!非常感谢。
install_java  "install my java -- you could make this name_property the version"