用terraform为循环编写DRY代码



我对地形非常陌生,有一项任务要我创建2个AWS KMS密钥。所以我在做这个:

resource "aws_kms_key" "ebs_encryption_key" {
description              = "EBS encryption key"
... omitted for brevity ...
tags = merge(map(
"Name", format("%s-ebs-encryption-key", var.name_prefix),
"component", "kms",
"dataclassification","low",
), var.extra_tags)
}
resource "aws_kms_alias" "ebs_encryption_key" {
name                 = format("alias/%s-ebs-encryption-key", var.name_prefix)
target_key_id        = aws_kms_key.ebs_encryption_key.key_id
}
# Repeated code!
resource "aws_kms_key" "rds_encryption_key" {
description              = "RDS encryption key"
... omitted for brevity ...
tags = merge(map(
"Name", format("%s-rds-encryption-key", var.name_prefix),
"component", "kms",
"dataclassification","low",
), var.extra_tags)
}
resource "aws_kms_alias" "rds_encryption_key" {
name                 = format("alias/%s-rds-encryption-key", var.name_prefix)
target_key_id        = "${aws_kms_key.rds_encryption_key.key_id}"
}

正如你所看到的,这两个代码块之间的唯一区别是";ebs";以及";rds";?如何使用for循环来避免重复代码块?

这似乎是一个小型模块的候选者,该模块封装了声明密钥和相关别名的详细信息,因为密钥和别名通常在系统中一起声明。

模块本身看起来像这样:

variable "name" {
type = string
}
variable "description" {
type = string
}
variable "tags" {
type = map(string)
}
resource "aws_kms_key" "main" {
description = var.description
# ...
tags = var.tags
}
resource "aws_kms_alias" "main" {
name          = "alias/${var.name}"
target_key_id = aws_kms_key.main.key_id
}
output "key_id" {
value = aws_kms_key.main.key_id
}
output "alias_name" {
value = aws_kms_alias.main.name
}

(正如这里所写的,这个模块感觉有点傻,因为这里并没有太多不仅仅从变量中派生出来的东西,但我假设你想避免重复的有趣的东西在你的例子中是"为了简洁而省略",这将取代我的例子中的# ...。(

然后,您的调用模块可以包括一个module块,该块使用for_each创建模块的两个实例,系统地设置参数以填充其输入变量:

module "kms_key" {
for_each = {
kms = "KMS"
ebs = "EBS"
}
name        = "${var.name_prefix}-${each.key}-encryption-key"
description = "${each.value} Encryption Key"
tags = merge(
var.extra_tags,
{
Name               = "${var.name_prefix}-${each.key}-encryption-key"
component          = "kms"
dataclassification = "low"
},
)
}

由于这里的for_each映射具有密钥kmsebs,因此其结果将是声明资源实例,这些实例在计划中应具有以下地址:

  • module.kms_key["kms"].aws_kms_key.main
  • module.kms_key["kms"].aws_kms_alias.main
  • module.kms_key["ebs"].aws_kms_key.main
  • module.kms_key["ebs"].aws_kms_alias.main

由于它们是由映射键标识的,因此您可以在将来向该映射添加新的键,以创建新的键/别名对,而不会干扰现有的键。

如果您需要在调用模块的其他地方使用密钥ID或别名,那么您可以通过调用模块的module.kms_key其他地方的输出访问它们:

  • module.kms_key["kms"].key_id
  • module.kms_key["kms"].alias_name
  • module.kms_key["ebs"].key_id
  • module.kms_key["ebs"].alias_name

最新更新