简体   繁体   English

Terraform 变量的插值和评估

[英]Terraform variable inteporlation and evaluation

I'm working with modules in Terraform using Yaml approach to manage variables.我正在使用 Yaml 方法在 Terraform 中处理模块来管理变量。 I have a very simple module that should create parameter in AWS Parameter Store based on my RDS and IAM User modules output.So, I wrote this module:我有一个非常简单的模块,它应该根据我的 RDS 和 IAM 用户模块输出在 AWS Parameter Store 中创建参数。所以,我编写了这个模块:

resource "aws_ssm_parameter" "ssm_parameter" {
  name      = var.parameter_name
  type      = var.parameter_type
  value     = var.parameter_value
  overwrite = var.overwrite
  tags      = var.tags
}

The variables I'm using are stored into a Yaml file like this:我使用的变量存储在这样的 Yaml 文件中:

ssms:
  /arquitetura/catalogo/gitlab/token:
    type: SecureString
    value: ManualInclude
  /arquitetura/catalogo/s3/access/key:
    type: String
    value: module.iam_user.access_key
  /arquitetura/catalogo/s3/secret/access/key:
    type: SecureString
    value: module.iam_user.secret_access_key
  /arquitetura/catalogo/rds/user:
    type: String
    value: module.rds_instance.database_username
  /arquitetura/catalogo/rds/password:
    type: SecureString
    value: module.rds_instance.database_password

As we can see, I have in "value" the module output I would like to send to Parameter Store.如我们所见,我在“值”中设置了我想发送到 Parameter Store 的模块输出。 I'm loading this variable file using file and yamldecode functions:我正在使用 file 和 yamldecode 函数加载这个变量文件:

  ssmfile                  = "./env/${terraform.workspace}/ssm.yaml"
  ssmfilecontent           = fileexists(local.ssmfile) ? file(local.ssmfile) : "ssmFileNotFound: true"
  ssmsettings              = yamldecode(local.ssmfilecontent)

So, I have a local.ssmsettings and I can write a module call like this:所以,我有一个 local.ssmsettings,我可以像这样编写一个模块调用:

module "ssm_parameter" {
  source = "../aws-ssm-parameter-tf"

  for_each = local.ssmsettings.ssms

  parameter_name  = each.key
  parameter_type  = each.value.type
  parameter_value = each.value.value
  tags            = local.tags
}

Doing this, my parameter is stored as:这样做,我的参数存储为:

{
    "Parameter": {
        "Name": "/arquitetura/catalogo/rds/user",
        "Type": "String",
        "Value": "module.rds_instance.database_username",
        "Version": 1,
        "LastModifiedDate": "2022-12-15T19:02:01.825000-03:00",
        "ARN": "arn:aws:ssm:sa-east-1:111111111111:parameter/arquitetura/catalogo/rds/user",
        "DataType": "text"
    }
}

Value is receiving the string module.rds_instance.database_username instead of the module output.值正在接收字符串 module.rds_instance.database_username 而不是模块输出。

I know that file function doesn't interpolate variables and I know Terraform doesn't have an eval function.我知道file函数不会插入变量,而且我知道 Terraform 没有eval函数。

Does anybody had the same situation that can tell me how you solved the problem or have any clue that I can follow?有没有人有同样的情况可以告诉我你是如何解决这个问题的,或者有什么线索可以让我遵循?

I already tried to work with Terraform templates, without success.我已经尝试使用 Terraform 模板,但没有成功。

Thanks in advance.提前致谢。

Terraform has no way to understand that the value strings in your YAML files are intended to be references to values elsewhere in your module, and even if it did it wouldn't be possible to resolve them from there because this YAML file is not actually a part of the Terraform module, and is instead just a data file that Terraform has loaded into memory. Terraform 无法理解 YAML 文件中的value字符串旨在引用模块中其他地方的值,即使它理解了也无法从那里解析它们,因为这个 YAML 文件实际上不是一个Terraform 模块的一部分,而只是 Terraform 加载到内存中的数据文件。

However, you can get a similar effect by placing all of the values your YAML file might refer to into a map of strings inside your module:但是,您可以通过将 YAML 文件可能引用的所有值放入模块内的字符串映射中来获得类似的效果:

locals {
  ssm_indirect_values = tomap({
    manual_include        = "ManualInclude"
    aws_access_key_id     = module.iam_user.access_key
    aws_secret_access_key = module.iam_user.secret_access_key
    database_username     = module.rds_instance.database_username
    database_password     = module.rds_instance.database_password
  })
}

Then change your YAML data so that the value strings match with the keys in this map:然后更改您的 YAML 数据,使value字符串与此映射中的键匹配:

ssms:
  /arquitetura/catalogo/gitlab/token:
    type: SecureString
    value: manual_include
  /arquitetura/catalogo/s3/access/key:
    type: String
    value: aws_access_key_id
  /arquitetura/catalogo/s3/secret/access/key:
    type: SecureString
    value: aws_secret_access_key
  /arquitetura/catalogo/rds/user:
    type: String
    value: database_username
  /arquitetura/catalogo/rds/password:
    type: SecureString
    value: database_password

You can then substitute the real values instead of the placeholders before you use the data structure in for_each :然后,您可以在使用for_each中的数据结构之前替换实际值而不是占位符:

locals {
  ssm_file                  = "${path.module}/env/${terraform.workspace}/ssm.yaml"
  ssm_file_content          = file(local.ssm_file)
  ssm_settings              = yamldecode(local.ssm_file_content)

  ssms = tomap({
    for k, obj in local.ssm_settings.ssms :
    k => {
      type  = obj.type
      value = local.ssm_indirect_values[obj.value]
    }
  })
}

module "ssm_parameter" {
  source   = "../aws-ssm-parameter-tf"
  for_each = local.ssms

  parameter_name  = each.key
  parameter_type  = each.value.type
  parameter_value = each.value.value
  tags            = local.tags
}

The for expression in the definition of local.ssms uses the source value string as a lookup key into local.ssm_indirect_values , thereby inserting the real value. local.ssms定义中的for表达式使用源value字符串作为local.ssm_indirect_values中的查找键,从而插入实际值。

The module "ssm_parameter" block now refers to the derived local.ssms instead of the original local.ssm_settings.ssms , so each.value.value will be the final resolved value rather than the lookup key, and so your parameter should be stored as you intended. module "ssm_parameter"块现在引用派生的local.ssms而不是原始的local.ssm_settings.ssms ,因此each.value.value将是最终解析的值而不是查找键,因此您的参数应存储为你打算。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM