我想检查节点属性的值。这个case
声明是我到目前为止所做的,并且有效:
case node[:languages][:ruby][:host_cpu]
when "x86_64"
...
when "i686"
...
end
我想要做的是使用if
语句。这就是我试过的:
if node[:languages][:ruby][:host_cpu]?("X86_64")
...
end
这基于以下内容,其中有效。
if platform?("ubuntu")
...
end
但是,我的尝试没有用。它在if
行上出现语法错误,表示预计会出现意外\n
和$end
。
我发现执行if
有两种方法。第一个是我上面演示的那个(显然)只适用于资源,而if_only
适用于节点。像这样
if_only {node[:languages]}
似乎仅用于检查节点的存在,以及在do上下文中。
如何使用if
语句检查节点的值?一种方法检查值,但仅检查资源,另一种检查节点,但仅检查它们的存在,而不是它们的值。
答案 0 :(得分:8)
你正在混淆许多不同的条件变体,其中大多数都是Chef的一部分,而不是Ruby。让我试着逐一描述不同的选择。
通常,case
与一系列if
和elsif
语句大致相当。您的case
以上
case node[:languages][:ruby][:host_cpu]
when "x86_64"
...
when "i686"
...
end
因此大致相当于
if node[:languages][:ruby][:host_cpu] == "x86_64"
...
elsif node[:languages][:ruby][:host_cpu] == "i686"
...
end
作为旁注,case
实际上使用的===
运算符通常不是可交换的,但更强大。对于简单的比较,它的工作方式与==
相同。这两个变体都是Ruby语言的一部分,您可以在其中编写烹饪书。
您提到的其他选项实际上是Chef在Ruby上定义的API的一部分。这通常称为Chef DSL(代表域特定语言,即语言的扩展或改编,在本例中为特定用法域的Ruby,在本例中为配置管理。)
platform?
方法是由Chef定义的方法,用于检查curent平台是否是传递的值之一。您可以阅读更多相关信息(以及类似的方法,例如,recipes in general和often used ruby idioms的主厨文档中现在推荐的platform_family?
方法。
作为旁注:您可能会对Ruby允许?
和!
字符出现在方法名称的末尾这一事实感到惊讶,这使得Ruby在类似语言中相当独特。对此。这些字符只是方法名称的一部分,对语言没有特殊意义。它们仅按惯例用于程序员以更好地识别方法的目的。如果一个方法最后有?
,那么它将用于检查某些条件,并且预计会返回真值或假值。最后使用!
的方法通常会执行一些潜在的危险操作,例如:改变对象,删除东西,......再次,这只是一种约定,不会被语言解释。
您提到的最后一个选项only_if
和扩展名not_if
用于定义Chef资源上的条件,以确保它们仅在某个条件为真时执行(或者使用{{ 1}},如果是假的话)。由于这些属性仅用于Chef资源,因此它们自然也由Chef定义。
要了解它们有用的原因,有必要了解Chef运行的方式。详情可在Anatomy of a Chef Run的说明中找到。重要的是,您基本上有两个执行阶段:资源编译和融合。在第一步中,执行定义资源的实际代码。在这里,您的not_if
语句中的代码也将运行。在加载完所有配方并定义了所有资源后,Chef进入第二阶段,即Convergence阶段。在那里,运行执行更改的资源的实际实现(在存储包中创建文件和目录,......)。只有在此阶段,才会检查case
和only_if
条件。
事实上,你可以观察到
之间的区别not_if
和
file "/tmp/helloworld"
action :create
content "hello world"
end
if File.exist?("/tmp/helloworld")
file "/tmp/foobar"
action :create
content "foobar"
end
end
在第一个变体中,在资源编译期间检查是否存在file "/tmp/helloworld"
action :create
content "hello world"
end
file "/tmp/foobar"
action :create
content "foobar"
only_if{ File.exist?("/tmp/helloworld") }
end
的条件。目前,尚未运行实际创建/tmp/foobar
文件的代码,因为它仅在转换步骤中执行。因此,在第一次运行期间,将不会创建/tmp/helloworld
文件。
然而,在第二个变体中,检查是使用/tmp/foobar
完成的,在转换期间进行评估。在这里,您会注意到两个文件都是在第一次运行时创建的。
如果你想更多地了解条件的定义如何在Ruby方面起作用(你肯定应该),你可以阅读Ruby Blocks或多或少的代码片段。为了以后的执行而四处传播。