

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

# 了解 Terraform 变量、局部值和输出
<a name="variables-locals-outputs"></a>

变量允许在代码块中使用占位符，从而增强了代码的灵活性。每当重复使用代码时，变量可以表示不同的值。Terraform 通过其模块化范围来区分其变量类型。输入变量是可以注入模块的外部值，输出值是可以在外部共享的内部值，局部值始终保持在其原始范围内。

## 变量
<a name="variables"></a>

AWS CloudFormation 使用[参数](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)来表示自定义值，这些值可以从一个堆栈部署到下一个堆栈部署进行设置和重置。*同样，Terraform 使用[输入变量或变量](https://developer.hashicorp.com/terraform/language/values/variables)。*变量可以在 Terraform 配置文件中的任何地方声明，并且通常使用所需的数据类型或默认值进行声明。以下所有三个表达式都是有效的 Terraform 变量声明。

```
variable "thing_i_made_up" {
  type = string
}

variable "random_number" {
  default = 5
}

variable "dogs" {
  type = list(object({
    name  = string
    breed = string
  }))

  default = [
    {
      name  = "Sparky",
      breed = "poodle"
    }
  ]
}
```

要在配置中访问 Sparky 的品种，你可以使用变量`var.dogs[0].breed`。如果变量没有默认值且未被归类为可为空，则必须为每次部署设置该变量的值。否则，可以选择为变量设置一个新值。在根模块中，可以在[命令行、环境变量或 [terrafor](https://developer.hashicorp.com/terraform/language/values/variables#variable-definitions-tfvars-files) m.tfv](https://developer.hashicorp.com/terraform/language/values/variables#variables-on-the-command-line) ars [文件中将当前变量值设置为环境变量](https://developer.hashicorp.com/terraform/language/values/variables#environment-variables)。以下示例说明如何在 **terraform.tfvars** 文件中输入变量值，该文件存储在模块的顶级目录中。

```
# terraform.tfvars
dogs = [
   { 
      name  = "Sparky", 
      breed = "poodle" 
   },
   { 
      name  = "Fluffy", 
      breed = "chihuahua" 
   }
]

random_number = 7

thing_i_made_up = "Kabibble"
```

在此示例`dogs`中，**terraform.tfvars** 文件的值将覆盖变量声明中的默认值。如果您在子模块中声明变量，则可以直接在模块声明块中设置变量值，如以下示例所示。

```
module "my_custom_module" {
  source        = "modulesource/custom"
  version       = "0.0.1"
  random_number = 8
}
```

声明变量时可以使用的其他一些参数包括：
+ `sensitive`— 将其设置为`true`防止变量值暴露在 Terraform 进程输出中。 
+ `nullable`— 将其设置为`true`允许变量没有值。这对于未设置默认值的变量来说很方便。
+ `description`— 将变量的描述添加到堆栈的元数据中。
+ `validation`— 为变量设置验证规则。

Terraform 变量最方便的方面之一是能够在变量声明中添加一个或多个验证对象。您可以使用验证对象添加一个条件，即变量必须通过，否则部署将失败。您也可以设置一条自定义错误消息，使其在违反条件时显示。

例如，你正在设置一个 Terraform 配置文件，你的团队成员将运行该文件。在部署堆栈之前，团队成员需要创建一个 **terraform.tfvars** 文件来设置重要的配置值。为了提醒他们，你可以做类似以下的事情。

```
variable "important_config_setting" {
  type = string

  validation {
    condition     = length(var.important_config_setting) > 0
    error_message = "Don't forget to create the terraform.tfvars file!"
  }

  validation {
    condition     = substr(var.important_config_setting, 0, 7) == "prefix-"
    error_message = "Remember that the value always needs to start with 'prefix-'"
  }
}
```

如本示例所示，您可以在单个变量中设置多个条件。Terraform 仅显示失败条件的错误消息。通过这种方式，您可以对变量值强制执行各种规则。如果变量值导致管道故障，您将确切地知道原因。

## 本地值
<a name="local-values"></a>

如果模块中存在您想要别名的值，请使用`locals`关键字，而不是声明一个永远不会更新的默认变量。顾名思义，一个`locals`区块包含的术语在内部限定于该特定模块。如果要转换字符串值，例如通过在变量值中添加前缀以用于资源名称，则使用本地值可能是一个不错的解决方案。单个`locals`块可以为你的模块声明所有本地值，如以下示例所示。

```
locals {
  moduleName    = "My Module"
  localConfigId = concat("prefix-", var.important_config_setting)
}
```

请记住，当你访问该值时，`locals`关键字会变成单数，例如`local.LocalConfigId`。

## 输出值
<a name="output-values"></a>

[如果 Terraform 输入变量就像 CloudFormation 参数一样，那么你可以说 [Terraform 的输出值就像输出](https://developer.hashicorp.com/terraform/language/values/outputs)一样。CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html)两者都用于公开部署堆栈中的值。但是，由于 Terraform 模块在工具结构中更加根深蒂固，因此 Terraform 输出值也用于将模块中的值公开给父模块或其他子模块，即使这些模块都在同一个部署堆栈中。如果您正在构建两个自定义模块，而第一个模块需要访问第二个模块的 ID 值，则需要将以下`output`块添加到第二个模块。

```
output "module_id" {
  value = local.module_id
}
Then in the first module you could use it like this:
module "first_module" {
  source = "path/to/first/module"
}

resource "example_resource" "example_resource_name" {
  module_id = module.first_module.module_id
}
```

由于 Terraform 输出值可以在同一个堆栈中使用，因此您也可以在`output`块中使用该`sensitive`属性来抑制该值显示在堆栈输出中。此外，方`output`块可以像变量使用`precondition`块一样使用`validation`块：以确保变量遵循一组特定的规则。这有助于确保在继续部署之前，模块中的所有值都按预期存在。

```
output "important_config_setting" {
  value = var.important_config_setting

  precondition {
    condition     = length(var.important_config_setting) > 0
    error_message = "You forgot to create the terraform.tfvars file again."
  }
}
```