我在terraform模块中有两个列表......
ingress_ports = [
{
from_port = 80
to_port = 80
protocol = "tcp"
},
{
from_port = 443
to_port = 443
protocol = "tcp"
},
{
from_port = 22
to_port = 22
protocol = "tcp"
}
]
我还有另一个网络ACL设置列表
result = [
{
cidr_block = "1.2.3.4/32"
from_port = 80
to_port = 80
protocol = "tcp"
},
{
cidr_block = "1.2.3.4/32"
from_port = 443
to_port = 443
protocol = "tcp"
},
{
cidr_block = "1.2.3.4/32"
from_port = 22
to_port = 22
protocol = "tcp"
},
{
cidr_block = "5.6.7.8/32"
from_port = 80
to_port = 80
protocol = "tcp"
},
{
cidr_block = "5.6.7.8/32"
from_port = 443
to_port = 443
protocol = "tcp"
},
{
cidr_block = "5.6.7.8/32"
from_port = 22
to_port = 22
protocol = "tcp"
}
]
我希望将这些列表连接在一起,以便我可以使用结果列表创建网络ACL。
for(int index = 0; index < 13; index++)
{
if(inFile.nextInt() < 0)
{
pos[index] = inFile.nextInt();
}
else
{
neg[index] = inFile.nextInt();
}
}
这种东西在Terraform中是否可行?
答案 0 :(得分:1)
这就是我想出的。我记得有一种方法可以使用模和整数除法来执行我想要做的事情。我为入口和出口做了这个,但我只会显示入口。为了帮助在模块中灵活使用它,我在模块外部创建了网络ACL并将其传入。
变量:
variable "acl-id" {}
variable "offset" {}
variable "ingress-rules" {
type = "list"
description = "The List of Ingress Rules. Each item in the list is a map. The Maps will be joined with the 'ingress-cidr'"
}
variable "ingress-cidr" {
type = "list"
description = "List of IPv4 CIDR ranges to apply to all ingress rules"
}
当地人:为了清楚起见,我创造了这些。
locals {
ingress-cidr-size = "${length( var.ingress-cidr )}"
ingress-rules-size = "${length( var.ingress-rules )}"
ingress-join-size = "${local.ingress-cidr-size * local.ingress-rules-size}"
ingress-joined-rules-cidrs = "${data.null_data_source.ingress-join.*.outputs}"
}
数据:
#Perform a cartesian like join of all of the CIDRs to apply to all of the rules
data "null_data_source" "ingress-join" {
count = "${local.ingress-join-size}"
inputs = {
rule-number = "${count.index + var.offset}"
cidr-block = "${ var.ingress-cidr[count.index / local.ingress-rules-size] }"
from-port = "${ lookup ( var.ingress-rules[count.index % local.ingress-rules-size], "from-port" ) }"
to-port = "${ lookup ( var.ingress-rules[count.index % local.ingress-rules-size], "to-port" ) }"
action = "${ lookup ( var.ingress-rules[count.index % local.ingress-rules-size], "action" ) }"
protocol = "${ lookup ( var.ingress-rules[count.index % local.ingress-rules-size], "protocol" ) }"
}
}
网络ACL规则配置:
##########################
# Ingress - Maps of rules
##########################
# Takes a list of 'ingress-rules' where each list item is a Map with the following keys
# action: ether "allow" or "deny"
# from-port: a port number
# to-port: a port number
# protocol: A string like "tpc" or "-1"
# rule-number: A unique value to prevent collisions with other rules
# cidr-block: The CIDR that is applied to this rule
resource "aws_network_acl_rule" "ingress-rules-and-cidr-list" {
count = "${var.create ? local.ingress-join-size : 0}"
network_acl_id = "${var.acl-id}"
egress = false
rule_number = "${lookup( local.ingress-joined-rules-cidrs[count.index], "rule-number", "")}"
rule_action = "${lookup( local.ingress-joined-rules-cidrs[count.index], "action", "")}"
cidr_block = "${lookup(local.ingress-joined-rules-cidrs[count.index], "cidr-block", "")}"
from_port = "${lookup(local.ingress-joined-rules-cidrs[count.index], "from-port", "")}"
to_port = "${lookup(local.ingress-joined-rules-cidrs[count.index], "to-port", "")}"
protocol = "${lookup(local.ingress-joined-rules-cidrs[count.index], "protocol", "")}"
}
答案 1 :(得分:1)
这是我使用的解决方案 下面是您的测试Terraform脚本
provider "aws" {
region = "us-east-1"
}
variable "lista" {
default = ["1", "2", "3"]
}
variable "listb" {
default = ["A", "B", "C", "D"]
}
resource "aws_eip" "eip" {
count = "${length(var.lista) * length(var.listb)}"
tags {
Name = "test-eip ${count.index}. ${element(var.lista, ceil(count.index/length(var.listb)))}:${element(var.listb, count.index)}"
}
}
测试运行 地形图| grep标签。名称
下面是输出
tags.Name: "0. 1:A"
tags.Name: "1. 1:B"
tags.Name: "2. 1:C"
tags.Name: "3. 1:D"
tags.Name: "4. 2:A"
tags.Name: "5. 2:B"
tags.Name: "6. 2:C"
tags.Name: "7. 2:D"
tags.Name: "8. 3:A"
tags.Name: "9. 3:B"
tags.Name: "10. 3:C"
tags.Name: "11. 3:D"
答案 2 :(得分:0)
我在下面的链接中提出了另一种方法-
https://github.com/hashicorp/terraform/issues/6657#issuecomment-453304599
相同的代码段-
我一直在寻找可合并两个列表的解决方案,并发现使用以下格式的解决方案-
locals {
a_identifiers = [
"arn:aws:iam::hhhhjjjjj:role/account_dev",
"arn:aws:iam::hhhhjjjjj:role/account_stage",
]
}
locals {
b_identifiers = [
"arn:aws:iam::hhhhjjjjj:role/account_qa",
"arn:aws:iam::hhhhjjjjj:role/account_prod",
]
}
locals {
combo_identifiers = "${concat(a_identifiers,b_identifiers)}"
}
这是我以后如何使用它的方法-
data "aws_iam_policy_document" "access_policy" {
statement {
effect = "Allow"
principals {
type = "AWS"
identifiers = ["${local.combined_identifiers}"]
}
actions = [
"ec2:*",
]
resources = [
"*",
]
}
}
希望有人会发现它有用
答案 3 :(得分:0)
@grbonk,我明白你在做什么。非常感谢您的指点。刚开始时,很难理解您的代码,因为它具有特定于场景的资源和变量,并且还没有变量值,因此看不到输出。但是,重新阅读有所帮助,下面是我的示例代码,希望有人能对您有所帮助。我将原帖保持原样,以便读者可以看到您指出的简单列表和地图列表的局限性。
我学到了几件事 1. element()仅支持简单列表(平面列表),不支持地图列表 2.当除法用作列表索引时,ceil()是隐式的 3.了解了一些有关null_data_source
的信息这是代码
provider "aws" {
region = "us-east-1"
}
variable "players" {
type = "list"
default = [
{name = "Paul Pierce" position = "Small Forward"},
{name = "Kevin Garnett" position = "Power Forward"},
{name = "Ray Allen" position = "Shooting Guard"}
]
}
variable "teams" {
type = "list"
default = [
{name = "Brooklyn Nets" conference = "eastern"},
{name = "La Lakers" conference = "western"},
{name = "Miami Heat" conference = "eastern"}
]
}
variable "fit" {
type = "list"
default = ["good", "bad", "ugly"]
}
data "template_file" "trade_options" {
count = "${length(var.players) * length(var.teams)}"
template = <<EOF
"$${optionid}. Trade $${player} ($${position}) to $${team} ($${conference}-conference) and its $${fit}"
EOF
vars = {
optionid = "${count.index}"
player = "${lookup(var.players[count.index/length(var.teams)], "name")}"
position = "${lookup(var.players[count.index/length(var.teams)], "position")}"
team = "${lookup(var.teams[count.index % length(var.teams)], "name")}"
conference = "${lookup(var.teams[count.index % length(var.teams)], "conference")}"
fit = "${var.fit[count.index % length(var.fit)]}"
}
}
output "trade-options" {
value = "${data.template_file.trade_options.*.rendered}"
}
以下是运行terraform apply | grep Trade时的输出
"0. Trade Paul Pierce (Small Forward) to Brooklyn Nets (eastern-conference) and its good"
"1. Trade Paul Pierce (Small Forward) to La Lakers (western-conference) and its bad"
"2. Trade Paul Pierce (Small Forward) to Miami Heat (eastern-conference) and its ugly"
"3. Trade Kevin Garnett (Power Forward) to Brooklyn Nets (eastern-conference) and its good"
"4. Trade Kevin Garnett (Power Forward) to La Lakers (western-conference) and its bad"
"5. Trade Kevin Garnett (Power Forward) to Miami Heat (eastern-conference) and its ugly"
"6. Trade Ray Allen (Shooting Guard) to Brooklyn Nets (eastern-conference) and its good"
"7. Trade Ray Allen (Shooting Guard) to La Lakers (western-conference) and its bad"
"8. Trade Ray Allen (Shooting Guard) to Miami Heat (eastern-conference) and its ugly"
答案 4 :(得分:0)
在terraform 0.12中,我们最终可以使用setproduct,这使得这项工作变得更加容易:
cronjobs = [
{
schedule_expression = "cron(5 0 * * ? *)"
command_and_arguments = ["app/aws-console.sh", "task1"]
description = "Hello World"
},
{
schedule_expression = "cron(0 5 1 * ? *)"
command_and_arguments = ["app/aws-console.sh", "task2"]
description = "Send Bills"
}
]
environments = ["dev", "stage"]
locals {
cronjobs_for_all_environments = setproduct(var.cronjobs, var.environments)
}
resource "aws_cloudwatch_event_rule" "cronjob" {
count = length(local.cronjobs_for_all_environments)
name = "cronjob-${local.cronjobs_for_all_environments[count.index][1]}"
description = "${local.cronjobs_for_all_environments[count.index][0].description} (${local.cronjobs_for_all_environments[count.index][1]})"
schedule_expression = local.cronjobs_for_all_environments[count.index][0].schedule_expression
}