2017-06-05 59 views
0

我试图动态创建terraform一些AWS资源利用计数,然后建立一个包含所有创建的资源ID列表输出变量在Terraform中构建动态列表?

resource "aws_subnet" "subnet-1" { 
    // If subnet_id value is supplied then we set count to 1 to create otherwise skip 
    count = "${replace(replace(var.primary_subnet_cidr, "/^.+/", "1"), "/^$/", "0")}" 
    tags = { 
    Name = "subnet-1" 
    } 
    cidr_block = "${var.primary_subnet_cidr}" 
    vpc_id = "${var.vpc_id}" 
    availability_zone = "${var.aws_region}a" 
} 
resource "aws_subnet" "subnet-2" { 
    // If subnet_id value is supplied then we set count to 1 to create otherwise skip 
    count = "${replace(replace(var.secondary_subnet_cidr, "/^.+/", "1"),"/^$/", "0")}" 
    tags = { 
    Name = "subnet-2" 
    } 
    cidr_block = "${var.secondary_subnet_cidr}" 
    vpc_id = "${var.vpc_id}" 
    availability_zone = "${var.aws_region}b" 
} 

output "ids" { 
     value = ["${aws_subnet.subnet-1.id}","${aws_subnet.subnet-2.id}"] 
} 

的想法是创建一个只有你想通过提供子网其变量(primary_subnet_cidr或secondary_subnet_cidr)。

动态创建它们可以正常工作,但是我的问题与动态列表有关。

当试图像一个aws_db_subnet_group.subnet_ids这需要在列表中使用此列表,如果已创建两个子网,它只能否则它抛出我下面的错误

InvalidSubnet: Subnet IDs are required.

我也曾尝试这

output "ids" { 
     value = ["${aws_subnet.*.id}"] 
} 

但terraform似乎不支持资源级别的通配符。

我怀疑这与我生成输出列表的方式有关。是否有更好的方式来生成动态列表,以便只包含创建的资源?

回答

2

您已经关闭,但需要使用正确的Terraform资源语法RESOURCE-TYPE.RESOURCE-NAME.PROPERTY_NAMERESOURCE-TYPE.RESOURCE-NAME.*.PROPERTY_NAME。所以,在你的榜样,您将输出:

output "ids" { 
    value = "${aws_subnet.subnet-1.*.id}" 
} 

当然,你可能想使用concat interpolation function加入两个列表:

output "ids" { 
    value = "${concat(aws_subnet.subnet-1.*.id, aws_subnet.subnet-2.*.id)}" 
} 

但如果你count属性设置上要么0资源,这可能会引发错误。为了弥补这一点,您可以使用其他插值函数的组合(例如coalescelist()),但恐怕我不记得确切的组合。

最后,对于您的count属性,这些var定义有点棘手。这里有一些其他的想法尝试:

// Count = 1 if var.secondary_subnet_cidr is non-empty 
resource "aws_subnet" "subnet-1" { 
    count = "${signum(length(var.secondary_subnet_cidr))}" 
    ... 
} 

// Define a separate var altogether. Ideally, you could infer this, but sometimes it's the best you can do. 
resource "aws_subnet" "subnet-1" { 
    count = "${var.should_create_secondary_subnet)}" 
    ... 
} 

更新2017年6月6日:感谢@MartinAtkins为指出,作为Terraform 0.9.x版本的,你不再需要在[]包列表输出。我已经更新了我的答案。

更新2017年6月8日:要仅从两个列表中选择一个空列表中的非空列表,请使用${element(concat(aws_subnet.subnet-1.*.id, aws_subnet.subnet-2.*.id), 0)}concat()函数将接受一个空列表,并且element(..., 0)将始终返回第一个元素,在这种情况下,它是非空列表。

+0

从Terraform 0.9.6开始,包含“splat变量”的括号不再需要也不建议使用,因为它们将在未来版本中被淘汰。尽管如此,这里仍然有效! :D –

+0

'aws_subnet.subnet-1。*。id' does not exist afaik。正确的语法应该是'aws_subnet.subnet-1.id',因此我试图从所有执行'aws_subnet。*。id'的资源中获取所有id属性的列表,但这不起作用。感谢关于coalescelist和语法的提示。这正是我正在寻找的插值函数组合。我想我得到的错误可能是由于其中一个资源的count = 0时列表中为空的值。也许'compact'可能解决这个问题。我会在稍后尝试。 – ByteFlinger

+0

尝试从不存在的列表读取,因为'count = 0'是常见的情况。如果我记得我们如何入侵,我会更新我的回应! –