局部变量
注意:此页面是关于 Packer 的 HCL2 模板的。 HCL2 模板最初作为 Beta 功能被 Packer 1.5 版引入。从 v1.7 开始,HCL2 支持不再处于测试阶段,并且是编写 Packer 配置的首选方式。对于稳定的旧风格配置语言,请参阅模板文档。从 v1.6.2 开始,您可以使用 hcl2_upgrade
命令将遗留的 JSON 模板转换为 HCL2 配置文件。
Packer HCL 模板中有两种变量:输入变量,简称为 variables
,和局部变量,也称为 locals
。输入变量可能有默认值,但可以从命令行或特殊变量文件读取覆盖这些默认值。局部变量可以被认为是常量,并且不能在运行时被覆盖。
这个页面是关于局部变量的。要了解输入变量,请参阅输入变量页面。
局部变量就是为一个表达式分配一个名称,然后可以在一个文件夹中多次使用该名称。
如果输入变量类似于函数参数,那么局部变量就相当于函数内部的局部变量。
变量指南中介绍了输入变量和局部变量的使用。
例子
局部变量在 local
和 locals
块中定义:
# Using the local block allows you to mark locals as sensitive, which will
# filter their values from logs.
local "mylocal" {
expression = "${var.secret_api_key}"
sensitive = true
}
# Using the locals block is more compact and efficient for declaring many locals
# Ids for multiple sets of EC2 instances, merged together
locals {
instance_ids = "${concat(aws_instance.blue.*.id, aws_instance.green.*.id)}"
}
# A computed default name prefix
locals {
default_name_prefix = "${var.project_name}-web"
name_prefix = "${var.name_prefix != "" ? var.name_prefix : local.default_name_prefix}"
}
# Local values can be interpolated elsewhere using the "local." prefix.
source "virtualbox-iso" "example" {
output = "${local.name_prefix}-files"
# ...
}
命名的局部变量可以与其他局部变量合并(merge)来实现默认值的功能:
# Define the common tags for all resources
locals {
common_tags = {
Component = "awesome-app"
Environment = "production"
}
}
# Create a resource that blends the common tags with instance-specific tags.
source "amazon-ebs" "server" {
source_ami = "ami-123456"
instance_type = "t2.micro"
tags = "${merge(
local.common_tags,
{
"Name" = "awesome-app-server",
"Role" = "server"
}
)}"
# ...
}
单个 local
块
local
块仅定义一个文件夹中的一个局部变量。块的标签是局部变量的名称,expression
是创建局部变量时应计算的表达式。您可以在 local
块中可选地声明一个 sensitive
布尔值以将变量标记为敏感并从日志中过滤它。
local "mylocal" {
expression = "${var.secret_api_key}"
sensitive = true
}
local
块对于定义复杂的局部变量也非常有用。 Packer 可能需要一些时间来展开和计算含有依赖于其他局部变量的复杂表达式的 locals
块。locals
块被解释为一个映射。映射未经排序,因此表达式被计算的顺序是不确定的。
为避免这种情况,应改用单一的 local
块。这些块将按照定义的顺序进行计算,计算顺序将始终相同。
locals
块
locals
块定义文件夹内的一个或多个局部变量。
为 locals
块中声明的变量设定的名称在整个文件夹中必须是唯一的。设置的值可以是当前文件夹中任意有效的表达式。
局部变量的表达式可以引用其他局部变量,但不允许循环引用。也就是说,局部变量不能引用自身或引用(直接或间接)返回它的变量。
建议将逻辑上相关的局部变量统一声明到一个块中,尤其是当它们相互依赖时。这将有助于读者理解变量之间的关系。同样的,最好把不相关的局部变量声明在不同的块中,并考虑使用注释来说明每个块,该注释描述所有包含的本地值共有的上下文。
已知的限制
目前不支持在数据源(data source)中使用局部变量,例如下面的示例。
locals {
cloud_owners = ["happycloud"]
cloud_base_filter_name = "cloud-hvm-2.0.*-x86_64-gp2"
}
data "happycloud" "happycloud-linux2-east" {
filters = {
name = local.cloud_base_filter_name
}
most_recent = true
owners = local.cloud_owners
}
局部变量可以引用数据源,但数据源为了避免循环依赖所以不能引用局部变量,因为被引用的局部变量可能引用了数据源自身,或者引用了那些引用了该数据源的局部变量。目前,在数据源中引用用户输入数据的首选方法是使用 variable
块。
variable "cloud_base_filter_name" {
type = string
default = "cloud-hvm-2.0.*-x86_64-gp2"
}
variable "cloud_owners" {
type = string
default = "happycloud"
}
data "happycloud" "happycloud-linux2-east" {
filters = {
name = var.cloud_base_filter_name
}
most_recent = true
owners = var.cloud_owners
}