本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
重要
该 AWS OpsWorks Stacks 服务于 2024 年 5 月 26 日终止,新客户和现有客户均已禁用。我们强烈建议客户尽快将其工作负载迁移到其他解决方案。如果您对迁移有疑问,请通过 re AWS : Post 或通过 Pre
有些配方仅仅是一系列 Chef 资源。在这种情况下,当您运行配方时,它将依次执行每个资源提供程序。但是,拥有一个更复杂的执行路径通常很有用。以下是两种常见情境:
-
您希望配方使用不同的属性设置多次执行同一资源。
-
您希望在不同的操作系统上使用不同的属性设置。
您可以通过将 Ruby 控制结构纳入到配方中来应对诸如此类的情境。本部分将介绍如何从示例 3:创建目录中修改配方,从而应对上述两种情境。
迭代
示例 3:创建目录演示了如何使用 directory
资源创建一个目录或一系列目录。但是,假设您希望创建两个单独的目录,即 /srv/www/config
和 /srv/www/shared
。您可以针对每个目录实施单独的目录资源,但是如果您希望创建非常多的目录,则该方法可能会非常麻烦。以下配方显示了处理该任务的一个更简单的方法。
[ "/srv/www/config", "/srv/www/shared" ].each do |path|
directory path do
mode 0755
owner 'root'
group 'root'
recursive true
action :create
end
end
配方会使用包含子目录路径的字符串集合,而不是针对每个子目录使用单独的目录资源。Ruby each
方法会针对每个集合元素执行一次资源,从第一个元素开始。元素的值通过 path
变量在资源中表示,在此情况下,该变量表示目录路径。您可以轻松调整此示例,以创建任意数量的子目录。
运行配方
-
不退出
createdir
目录;您将对接下来的几个示例使用该说明书。 -
如果尚未运行
kitchen destroy
,则运行它,以便从干净的实例开始。 -
用示例替换
default.rb
中的代码,并运行kitchen converge
。 -
登录到实例;您会在
/srv
下看到新创建的目录。
可以用哈希表来指定每个迭代的两个值。以下配方可创建 /srv/www/config
和 /srv/www/shared
,每个都有不同的模式。
{ "/srv/www/config" => 0644, "/srv/www/shared" => 0755 }.each do |path, mode_value|
directory path do
mode mode_value
owner 'root'
group 'root'
recursive true
action :create
end
end
运行配方
-
如果尚未运行
kitchen destroy
,则运行它,以便从干净的实例开始。 -
用示例替换
default.rb
中的代码,并运行kitchen converge
。 -
登录到实例;您会在
/srv
下看到新创建的具有指定模式的目录。
注意
AWS OpsWorks 堆栈配方通常使用这种方法从堆栈配置和部署 JSON(基本上是一个大型哈希表)中提取值,然后将其插入资源中。有关示例,请参阅Deploy 配方。
条件逻辑
您也可以使用 Ruby 条件逻辑来创建多个执行分支。以下配方使用 if-elsif-else
逻辑来扩展前面的示例,以便它可创建名为 /srv/www/shared
的子目录,但是仅适用于 Debian 和 Ubuntu 系统。对于所有其他系统,它会记录显示在 Test Kitchen 输出中的错误消息。
if platform?("debian", "ubuntu")
directory "/srv/www/shared" do
mode 0755
owner 'root'
group 'root'
recursive true
action :create
end
else
log "Unsupported system"
end
运行示例配方
-
如果您的实例仍处于运行状态,请运行
kitchen destroy
将其关闭。 -
用示例代码替换
default.rb
中的代码。 -
编辑
.kitchen.yml
,将 CentOS 6.4 系统添加到平台列表中。文件的platforms
部分此时应类似于如下内容。... platforms: - name: ubuntu-12.04 - name: centos-6.4 ...
-
运行
kitchen converge
,这将创建一个实例,并按顺序在.kitchen.yml
中针对每个平台运行配方。注意
如果希望仅收敛一个实例,请将实例名称作为参数添加。例如,要仅在 Ubuntu 平台上收敛配方,请运行
kitchen converge default-ubuntu-1204
。如果您忘记了平台名称,则可运行kitchen list
。
您应该会在 Test Kitchen 输出的 CentOS 部分中看到您的日志消息,该消息将类似于以下内容:
... Converging 1 resources Recipe: createdir::default * log[Unsupported system] action write[2014-06-23T19:10:30+00:00] INFO: Processing log[Unsupported system] action write (createdir::default line 12) [2014-06-23T19:10:30+00:00] INFO: Unsupported system [2014-06-23T19:10:30+00:00] INFO: Chef Run complete in 0.004972162 seconds
现在,您可以登录到实例,并验证是否已创建目录。但是,现在您不能简单地运行 kitchen login
,而是必须通过附加平台名称来指定具体的实例,例如 kitchen
login default-ubuntu-1204
。
注意
如果 Test Kitchen 命令采用了某个实例名称,则您无需键入完整的名称。Test Kitchen 会将实例名称视为 Ruby 正则表达式,因此只需足够的字符,即可提供一个唯一匹配项。例如,您可以通过运行 kitchen
converge ub
仅收敛 Ubuntu 实例,或通过运行 kitchen
login 64
登录到 CentOS 实例。
此时,您可能会遇到的问题是,配方如何知道它正在哪个平台上运行。Chef 针对收集系统数据 (包括平台) 的每次运行而运行名为 Ohaiplatform?
方法会将括号中的系统与 Ohai 平台值进行比较,如果其中一个匹配,则返回 true。
您可以使用 node['
直接在代码中引用节点属性的值。例如,平台值由 attribute_name
']node['platform']
表示。例如,您可能已将前面的示例编写为如下内容。
if node[:platform] == 'debian' or node[:platform] == 'ubuntu'
directory "/srv/www/shared" do
mode 0755
owner 'root'
group 'root'
recursive true
action :create
end
else
log "Unsupported system"
end
将条件逻辑包含在配方中的一个常见原因是为了顺应如下事实:不同的 Linux 系列有时会对软件包、目录等使用不同的名称。例如,Apache 软件包名称在 CentOS 系统上为 httpd
,而在 Ubuntu 系统上为 apache2
。
如果您需要对不同的系统使用不同的字符串,则 Chef value_for_platform
if-elsif-else
更简单的解决方案。以下配方会在 CentOS 系统上创建 /srv/www/shared
目录、在 Ubuntu 系统上创建 /srv/www/data
目录,而在所有其他系统上创建 /srv/www/config
。
data_dir = value_for_platform(
"centos" => { "default" => "/srv/www/shared" },
"ubuntu" => { "default" => "/srv/www/data" },
"default" => "/srv/www/config"
)
directory data_dir do
mode 0755
owner 'root'
group 'root'
recursive true
action :create
end
value_for_platform
将相应的路径分配至 data_dir
,而 directory
资源则使用该值创建目录。
运行示例配方
-
如果您的实例仍处于运行状态,请运行
kitchen destroy
将其关闭。 -
用示例代码替换
default.rb
中的代码。 -
运行
kitchen converge
,然后登录到每个实例,以验证相应的目录是否存在。