生成块上的 Terragrunt 字符串插值

问题描述 投票:0回答:1

很难完成这项工作。

我正在尝试使用生成块添加 for_each 并根据变量 s3 中的条目数量多次运行该模块,但在正确执行时遇到了很多麻烦。

这是 terragrunt.hcl 文件的重要部分

locals {
  s3 = {
    "companies-data-service" = {
      enable_cloudfront        = true
      cloudfront_allowed_paths = ["logos/*"]
      cors_rules = {
        "local" = {
          methods = ["POST", "HEAD", "PUT", "GET"]
          origins = ["http://localhost:*", "https://*.test.io"]
        }
      }
    }
  }
}

generate "cdn" {
  path      = "cdn.tf"
  if_exists = "overwrite"
  contents  = <<EOF
module "cdn" {
  source = "git::[email protected]:my-org/terraform-modules.git//s3?ref=v0.0.21"
  for_each = { for $${k}, $${v} in "${local.s3}" : $${k} => $${v} }

  name                     = "${local.s3}" != {} ? $${each.value} : ""
  environment              = "${local.parent.inputs.core_env_name}"
  cors_rules               = try($${each.value.cors_rules}, {})
  enable_cloudfront        = try($${each.value.enable_cloudfront}, false)
  enable_versioning        = try($${each.value.enable_versioning}, false)
  cloudfront_allowed_paths = try($${each.value.cloudfront_allowed_paths}, [])
  acm_certificate_arn      = "${dependency.acm.outputs.acm_certificate_arn}"
  aliases                  = ["$${each.key}-static.test.com"]

  enable_lifecycle_rules = try($${each.value.enable_lifecycle_rules}, false)
  s3_lifecycle_rules     = try($${each.value.lifecycle_rules}, [])
  bucket_policies        = try($${each.value.bucket_policies}, {})
}
EOF
}

有这些错误

local.s3 as object with 1 attribute "companies-data-service" 
ERRO[0010] .
                                           
ERRO[0010] Cannot include the given value in a string template: string required.
 
ERRO[0010] Error: Invalid template interpolation value

还尝试了这样的 local.s3 变量:

s3 = {
    companies = {
      name = "companies"
      enable_cloudfront        = true
      cloudfront_allowed_paths = ["logos/*"]
      cors_rules = {
        "local" = {
          methods = ["POST", "HEAD", "PUT", "GET"]
          origins = ["http://localhost:*", "https://*.test.io"]
        }
      }
    },
    companies2 = {
      name = "companies-2"
      enable_cloudfront        = true
      cloudfront_allowed_paths = ["logos/*"]
      cors_rules = {
        "local" = {
          methods = ["POST", "HEAD", "PUT", "GET"]
          origins = ["http://localhost:*", "https://*.test.io"]
        }
      }
    }
  }

区块生成如下:

generate "cdn" {
  path      = "cdn.tf"
  if_exists = "overwrite"
  contents  = <<EOF
module "cdn" {
  source = "git::[email protected]:my-org/terraform-modules.git//s3?ref=v0.0.21"
  for_each = "${local.s3}"

  name                     = $${each.value.name}
  environment              = "${local.parent.inputs.core_env_name}"
  cors_rules               = try($${each.value.cors_rules}, {})
  enable_cloudfront        = try($${each.value.enable_cloudfront}, false)
  enable_versioning        = try($${each.value.enable_versioning}, false)
  cloudfront_allowed_paths = try($${each.value.cloudfront_allowed_paths}, [])
  acm_certificate_arn      = "${dependency.acm.outputs.acm_certificate_arn}"
  aliases                  = ["$${each.value.name}-static.test.com"]

  enable_lifecycle_rules = try($${each.value.enable_lifecycle_rules}, false)
  s3_lifecycle_rules     = try($${each.value.lifecycle_rules}, [])
  bucket_policies        = try($${each.value.bucket_policies}, {})
}
EOF
}

为了验证我的更改,我尝试在生成块内传递局部变量,就像纯 terraform 代码一样,这样它就可以工作。

generate "cdn" {
  path      = "cdn.tf"
  if_exists = "overwrite"
  contents  = <<EOF
locals {
  s3 = {
    companies = {
      name = "companies"
      enable_cloudfront        = true
      cloudfront_allowed_paths = ["logos/*"]
      cors_rules = {
        "local" = {
          methods = ["POST", "HEAD", "PUT", "GET"]
          origins = ["http://localhost:*", "https://*.test.io"]
        }
      }
    },
    companies2 = {
      name = "companies-2"
      enable_cloudfront        = true
      cloudfront_allowed_paths = ["logos/*"]
      cors_rules = {
        "local" = {
          methods = ["POST", "HEAD", "PUT", "GET"]
          origins = ["http://localhost:*", "https://*.test.io"]
        }
      }
    }
  }
}
module "cdn" {
  source = "git::[email protected]:my-org/terraform-modules.git//s3?ref=v0.0.21"
  for_each = local.s3

  name                     = each.value.name
  environment              = "${local.parent.inputs.core_env_name}"
  cors_rules               = try(each.value.cors_rules, {})
  enable_cloudfront        = try(each.value.enable_cloudfront, false)
  enable_versioning        = try(each.value.enable_versioning, false)
  cloudfront_allowed_paths = try(each.value.cloudfront_allowed_paths, [])
  acm_certificate_arn      = "${dependency.acm.outputs.acm_certificate_arn}"
  aliases                  = ["$${each.value.name}-static.test.com"]
  enable_lifecycle_rules = try(each.value.enable_lifecycle_rules, false)
  s3_lifecycle_rules     = try(each.value.lifecycle_rules, [])
  bucket_policies        = try(each.value.bucket_policies, {})
}
EOF
}
```

So the issue is clearly with how terragrunt is passing the variable to the generate block, but I don't what is happening because terragrunt don't output anything I can use to debug that variable.

Any help will be much appreciated
amazon-s3 terraform terraform-provider-aws string-interpolation terragrunt
1个回答
0
投票

这是一个 terragrunt 文件,因此

locals
在 terragrunt 内部被消耗,并且您无法将其传递给 terraform。 Terragrunt 仅生成 tf 文件并执行 terraform 命令。你需要将
locals
传递给 terraform 然后你就可以使用

inputs = {
    s3 = local.s3
}

generate "vars" {
    path      = "vars.tf"
    if_exists = "overwrite"
    contents  = <<EOF
variable "s3" {
  type = object({})
}
EOF
}

然后可以将

cdn
块写入

generate "cdn" {
  path      = "cdn.tf"
  if_exists = "overwrite"
  contents  = <<EOF
module "cdn" {
  source = "git::[email protected]:my-org/terraform-modules.git//s3?ref=v0.0.21"
  for_each = { for k, v in s3 : k => v }

  name                     = s3 != {} ? each.value : ""
  environment              = "${local.parent.inputs.core_env_name}"
  cors_rules               = try(each.value.cors_rules, {})
  enable_cloudfront        = try(each.value.enable_cloudfront, false)
  enable_versioning        = try(each.value.enable_versioning, false)
  cloudfront_allowed_paths = try(each.value.cloudfront_allowed_paths, [])
  acm_certificate_arn      = "${dependency.acm.outputs.acm_certificate_arn}"
  aliases                  = ["$${each.key}-static.test.com"]

  enable_lifecycle_rules = try(each.value.enable_lifecycle_rules, false)
  s3_lifecycle_rules     = try(each.value.lifecycle_rules, [])
  bucket_policies        = try(each.value.bucket_policies, {})
}
EOF
}

我已将

"${dependency.acm.outputs.acm_certificate_arn}"
"${local.parent.inputs.core_env_name}"
替换为静态值(我没有这些值)和
source = "vancluever/module/null"
,并且它有效。

© www.soinside.com 2019 - 2024. All rights reserved.