示例 4:添加流控制 - AWS OpsWorks

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

示例 4:添加流控制

重要

AWS OpsWorks Stacks 不再接受新客户。在 2024 年 5 月 26 日之前,现有客户将能够正常使用 OpsWorks 控制台、API、CLI 和 CloudFormation 资源,届时它们将停产。为准备此过渡,我们建议您 AWS Systems Manager 尽快将堆栈过渡到。有关更多信息,请参阅 AWS OpsWorks Stacks 生命周期终结常见问题解答将 AWS OpsWorks Stacks 应用程序迁移到 AWS Systems Manager 应用程序管理器

有些配方仅仅是一系列 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 变量在资源中表示,在此情况下,该变量表示目录路径。您可以轻松调整此示例,以创建任意数量的子目录。

运行配方
  1. 不退出 createdir 目录;您将对接下来的几个示例使用该说明书。

  2. 如果尚未运行 kitchen destroy,则运行它,以便从干净的实例开始。

  3. 用示例替换 default.rb 中的代码,并运行 kitchen converge

  4. 登录到实例;您会在 /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
运行配方
  1. 如果尚未运行 kitchen destroy,则运行它,以便从干净的实例开始。

  2. 用示例替换 default.rb 中的代码,并运行 kitchen converge

  3. 登录到实例;您会在 /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
运行示例配方
  1. 如果您的实例仍处于运行状态,请运行 kitchen destroy 将其关闭。

  2. 用示例代码替换 default.rb 中的代码。

  3. 编辑 .kitchen.yml,将 CentOS 6.4 系统添加到平台列表中。文件的 platforms 部分此时应类似于如下内容。

    ... platforms: - name: ubuntu-12.04 - name: centos-6.4 ...
  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 针对收集系统数据 (包括平台) 的每次运行而运行名为 Ohai 的工具,并在称为节点对象的结构中将其表示为一组属性。Chef platform? 方法会将括号中的系统与 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 资源则使用该值创建目录。

运行示例配方
  1. 如果您的实例仍处于运行状态,请运行 kitchen destroy 将其关闭。

  2. 用示例代码替换 default.rb 中的代码。

  3. 运行 kitchen converge,然后登录到每个实例,以验证相应的目录是否存在。