

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

# 配方结构
<a name="cookbooks-101-basics-structure"></a>

**重要**  
该 AWS OpsWorks Stacks 服务于 2024 年 5 月 26 日终止，新客户和现有客户均已禁用。我们强烈建议客户尽快将其工作负载迁移到其他解决方案。如果您对迁移有疑问，请通过 re [AWS : Post 或通过 Pre](https://repost.aws/) mium Su [AWS pp](https://aws.amazon.com/support) ort 与 AWS 支持 团队联系。

说明书本质上是一组*配方*，可用来在实例上执行各种任务。要阐明如何实施配方，查看一个简单的示例会非常有用。以下是内置 [HAProxy 层](layers-haproxy.md)的设置配方。现在只需关注总体结构，不必过于关注细节；细节将在后续示例中加以介绍。

```
package 'haproxy' do
  action :install
end

if platform?('debian','ubuntu')
  template '/etc/default/haproxy' do
    source 'haproxy-default.erb'
    owner 'root'
    group 'root'
    mode 0644
  end
end

include_recipe 'haproxy::service'

service 'haproxy' do
  action [:enable, :start]
end

template '/etc/haproxy/haproxy.cfg' do
  source 'haproxy.cfg.erb'
  owner 'root'
  group 'root'
  mode 0644
  notifies :restart, "service[haproxy]"
end
```

**注意**  
有关此示例以及工作配方和相关文件的其他示例，请参阅 [OpsWorks Stacks 内置配方](https://github.com/aws/opsworks-cookbooks)。

该示例重点介绍了关键配方元素，以下各节中分别介绍了这些元素。

**Topics**
+ [资源](#cookbooks-101-basics-structure-resources)
+ [流控制](#cookbooks-101-basics-structure-ruby)
+ [包含的配方](#cookbooks-101-basics-structure-include)

## 资源
<a name="cookbooks-101-basics-structure-resources"></a>

配方主要包含一组 Chef *资源*。其中每种资源指定实例最终状态的一个特定方面，例如要安装的软件包或要启动的服务。该示例有四种资源：
+ 一种`package`资源，代表已安装的软件包，在本示例中是[HAProxy 服务器](http://haproxy.1wt.eu/)。
+ 一种`service`资源，它代表一项服务，即本示例中的 HAProxy服务。
+ 两个`template`资源，代表要根据指定模板创建的文件，本示例的两个 HAProxy 配置文件。

资源提供了一种用于指定实例状态的声明方式。在幕后，每种资源都有一个关联的*提供程序*执行所需的任务，如安装软件包、创建和配置目录、启动服务等等。如果任务的详细信息取决于特定的操作系统，则资源有多个提供程序，并对系统使用适当的提供程序。例如，在 Red Hat Linux 系统上，`package` 提供程序使用 `yum` 来安装软件包。在 Ubuntu Linux 系统上，`package` 提供程序使用 `apt-get`。

您将资源实施为具有以下通用格式的 Ruby 代码块。

```
resource_type "resource_name" do
  attribute1 'value1'
  attribute2 'value2'
  ...
  action :action_name
  notifies : action 'resource'
end
```

元素有：

**资源类型**  
(必选) 该示例包含三种资源类型，即 `package`、`service` 和 `template`。

**资源名称**  
(必选) 该名称标识特定资源，有时用作其中一个属性的默认值。在示例中，`package` 代表名为 `haproxy` 的程序包资源，而第一个 `template` 资源代表名为 `/etc/default/haproxy` 的配置文件。

**属性**  
(可选) 属性指定资源配置，并因资源类型以及您希望的资源配置方式而异。  
+ 该示例的 `template` 资源显式定义一组属性，以指定所创建文件的源、所有者、组和模式。
+ 该示例的 `package` 和 `service` 资源没有显式定义任何属性。

  资源名称通常为必需属性的默认值，有时只需资源名称即可。例如，资源名称是 `package` 资源的 `package_name` 属性的默认值，该属性为唯一必需的属性。
还有一些称为 guard 属性的专有属性，这些属性指定资源提供程序何时执行操作。例如，`only_if` 属性指示资源提供程序只有在满足指定条件时才执行操作。该 HAProxy 配方不使用守卫属性，但以下几个示例使用了这些属性。

**操作和通知**  
(可选) 操作和通知指定提供程序要执行哪些任务。  
+ `action` 指示提供程序采取指定的操作，如安装或创建。

  每种资源都有一组取决于特定资源的操作，其中一个是默认操作。在示例中，`package` 资源的操作为 `install`，该操作会指示提供程序安装软件包。第一种 `template` 资源没有 `action` 元素，因此提供程序会执行默认的 `create` 操作。
+ `notifies` 指示另一种资源的提供程序执行操作，但前提是资源的状态已更改。

  `notifies` 通常与 `template` 和 `file` 等资源一起使用，以执行诸如在修改配置文件后重新启动服务等操作。资源没有默认通知。如果需要通知，资源必须具有显式 `notifies` 元素。在 HAProxy 配方中，如果关联的配置文件已更改，第二个`template``service`资源会通知 haproxy 资源重新启动 HAProxy 服务。

有时资源依赖于操作系统。
+ 有些资源只能在 Linux 或 Windows 系统上使用。

  例如，[package](https://docs.chef.io/chef/resources.html#package) 会将软件包安装在 Linux 系统上，而 [windows\$1package](https://docs.chef.io/chef/resources.html#windows-package) 会将软件包安装在 Windows 系统上。
+ 有些资源可以用在任何操作系统上，但却拥有特定于操作系统的属性。

  例如，[file](https://docs.chef.io/chef/resources.html#file) 资源可用于 Linux 或 Windows 系统上，但却拥有用于配置权限的独立属性集。

有关标准资源的说明，包括每种资源的可用属性、操作和通知，请参阅[关于资源和提供程序](https://docs.chef.io/resource.html)。

## 流控制
<a name="cookbooks-101-basics-structure-ruby"></a>

由于配方为 Ruby 应用程序，因此您可以使用 Ruby 控制结构将流控制纳入到配方中。例如，您可以使用 Ruby 条件逻辑使配方在不同的系统上有不同的行为。该 HAProxy 配方包括一个使用`template`资源创建配置文件的`if`块，但前提是该配方在 Debian 或 Ubuntu 系统上运行。

另一个常见情况是，使用循环利用不同的属性设置多次执行资源。例如，您可以使用循环创建一组目录，从而利用不同目录名称多次执行 `directory` 资源。

**注意**  
如果您不熟悉 Ruby，请参阅[适用于 Chef 的 Ruby 基础知识](https://docs.chef.io/just_enough_ruby_for_chef.html)，该部分介绍了您需要了解的有关大部分配方的内容。

## 包含的配方
<a name="cookbooks-101-basics-structure-include"></a>

`include_recipe` 会在您的代码中包括其他配方，这样有助于将您的配方模块化，并在多个配方中重复使用相同的代码。当您运行主机配方时，Chef 会在执行主机配方之前，使用指定配方的代码替换每个 `include_recipe` 元素。您通过使用标准 Chef `cookbook_name::recipe_name` 语法来标识包含的配方，其中 `recipe_name` 省略了 `.rb` 扩展名。该示例包括一个代表 HAProxy 服务的配方。`haproxy::service`

**注意**  
如果您在运行于 11.10 及更高版本的 Chef 上的配方中使用 `include_recipe`，以包含来自其他说明书的配方，则必须使用 `depends` 语句声明说明书的 `metadata.rb` 文件中的依赖关系。有关更多信息，请参阅 [实施配方：Chef 11.10](workingcookbook-chef11-10.md)。