Warm tip: This article is reproduced from serverfault.com, please click

其他-子模块中的terraform覆盖标签值

(其他 - terraform overwrite tag value in sub modules)

发布于 2020-11-30 12:40:52

我正在使用terraform模块,并将一组default_tags传递给子模块以进行一致的标记。如下所示,它的优点是子模块继承了其父标签,但也可以添加自己的标签。

但是,我还想做的是能够覆盖某些继承的标签值,尤其是“名称”。但是我似乎无法完成这项工作。

在下面的示例(AWS的Terraform 13.5)中,为任何标签指定的第一个值(例如,根模块中的“ scratch-test”)将级联到子模块,并且无法更改。因此,VPC名称标签和子网名称标签都=“ scratch-test”。

如何覆盖子模块中的变量值?

# root variables.tf
variable "default_tags" {
    type = map
    default = {
        environment_type = "Dev Environment"
    }
} 


# root main.tf
provider "aws" {
    region = var.region
}

module "vpc" {
    source = "../../../../scratch/tags-pattern"
    vpc_name                = "scratch-test"
    public_subnets          = ["10.0.0.0/26"]

    default_tags = merge(map(
        "Name", "scratch-test"
    ), var.default_tags)
}

# ../../../../scratch/tags-pattern/main.tf
module "the_vpc" {
    source = "../../terraform/tf-lib/network/vpc"

    vpc_name = var.vpc_name
    vpc_cidr = "10.0.0.0/24"

    default_tags = merge(map(
        "Name", "scratch-test-vpc",
        "vpc_tag", "vpc"
    ), var.default_tags)
}

# Add a subnet
module "public_subnets" {
    source = "../../terraform/tf-lib/network/subnet"
    vpc_id                  = module.the_vpc.output_vpc_id
    subnets                 = var.public_subnets
    default_tags = merge(map(
        "Name", "scratch-test-subnet",
        "subnet_tag", "public"
    ), var.default_tags)
}
# tf-lib/network/vpc/main.tf
resource "aws_vpc" "vpc" {
    cidr_block = var.vpc_cidr
    enable_dns_support = true
    enable_dns_hostnames = true
    tags = merge(map(
        "module", "tf-lib/network/vpc"
    ), var.default_tags)
} 

每个模块的variable.tf文件包含以下语句:

variable "default_tags" {}
Questioner
P Burke
Viewed
11
ydaetskcoR 2020-11-30 21:46:04

merge函数通过覆盖参数序列中定义的后面的映射来设置优先级:

merge 接受任意数量的 map或对象,并返回一个包含来自所有参数的一组合并元素的 map或对象。

如果有多个给定的映射或对象定义了相同的键或属性,则参数序列中后面的那个优先。如果参数类型不匹配,则在应用合并规则之后,结果类型将是与属性的类型结构匹配的对象。

因此,要允许你覆盖默认标签,可以先指定默认标签,如下所示:

# root variables.tf
variable "default_tags" {
    type = map
    default = {
        environment_type = "Dev Environment"
    }
} 


# root main.tf
provider "aws" {
    region = var.region
}

module "vpc" {
    source = "../../../../scratch/tags-pattern"
    vpc_name                = "scratch-test"
    public_subnets          = ["10.0.0.0/26"]

    default_tags = merge(var.default_tags, map(
        "Name", "scratch-test"
    ))
}

使用{}map语法而不是map函数,以上内容也可能看起来更清晰

# root main.tf
provider "aws" {
    region = var.region
}

module "vpc" {
    source = "../../../../scratch/tags-pattern"
    vpc_name                = "scratch-test"
    public_subnets          = ["10.0.0.0/26"]

    default_tags = merge(var.default_tags, {
      Name = "scratch-test",
    })
}

map功能文档中所述,此功能已被弃用,最终将被删除:

不推荐使用此功能。从Terraform v0.12起,Terraform语言具有内置语法,可使用{} 分隔符创建 map请改用内置语法。map功能将在Terraform的将来版本中删除。