在 Terraform 变量中使用 JSON 格式的字符串

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

我正在 Terraform 版本 0.14.15 上使用 for_each 方法创建一些资源。该资源有一个属性 input_parameters,它采用 JSON 格式的字符串作为其值。我使用单独的对象在地图变量中定义这个值。我将值指定为 JSON 格式的字符串,但在执行时出现错误,提示我需要声明一个字符串。任何有关修复此错误的见解都会有所帮助。下面是我声明资源和变量的方式。

资源

resource "aws_config_config_rule" "managed_rules" {
  for_each         = var.managed_rules
  name             = each.value.name
  description      = each.value.description
  input_parameters = each.value.input_parameters

  source {
    owner             = each.value.owner
    source_identifier = each.value.source_identifier
  }

  depends_on = [aws_config_configuration_recorder.config_recorder]
}

变量

variable "managed_rules" {
  type = map(object({
    name              = string
    description       = string
    owner             = string
    source_identifier = string
# Is there a variable for strings in JSON format?
    input_parameters  = string
  }))
  default = {
    "1" = {
      name              = "alb-http-to-https-redirection-check"
      description       = "Checks whether HTTP to HTTPS redirection is configured on all HTTP listeners of Application Load Balancers. The rule is NON_COMPLIANT if one or more HTTP listeners of Application Load Balancer do not have HTTP to HTTPS redirection configured."
      owner             = "AWS"
      source_identifier = "ALB_HTTP_TO_HTTPS_REDIRECTION_CHECK"
      input_parameters = {
        "MaximumExecutionFrequency" : "TwentyFour_Hours",
      }
  }

错误

This default value is not compatible with the variable's type constraint:
element "2": attribute "input_parameters": string required.

使用 jsonencode 函数更新代码并将 input_parameters 更改为 any 后,这是错误:

    This default value is not compatible with the variable's type constraint:
collection elements cannot be unified.
json string amazon-web-services terraform config
5个回答
7
投票

这里发生了几件事:

  1. 资源要求
    input_parameters
    是 JSON 编码的字符串
  2. 变量类型为字符串
  3. 您将对象类型传递到仅接受字符串类型的变量中

所以(2)和(3)是矛盾的。在某些时候,您必须将对象转换为 JSON 字符串。您可以在将其作为输入变量传递之前执行此操作,也可以更改输入变量以接受对象并将对象提供给资源时将其转换为 JSON。

我会选择第二个选项,因为将对象而不是字符串传递到模块中更直观。所以,试试这个:

resource "aws_config_config_rule" "managed_rules" {
  for_each         = var.managed_rules
  name             = each.value.name
  description      = each.value.description
  input_parameters = jsonencode(each.value.input_parameters)

  source {
    owner             = each.value.owner
    source_identifier = each.value.source_identifier
  }

  depends_on = [aws_config_configuration_recorder.config_recorder]
}


variable "managed_rules" {
  type = map(object({
    name              = string
    description       = string
    owner             = string
    source_identifier = string
# Is there a variable for strings in JSON format?
    input_parameters  = any
  }))
  default = {
    "1" = {
      name              = "alb-http-to-https-redirection-check"
      description       = "Checks whether HTTP to HTTPS redirection is configured on all HTTP listeners of Application Load Balancers. The rule is NON_COMPLIANT if one or more HTTP listeners of Application Load Balancer do not have HTTP to HTTPS redirection configured."
      owner             = "AWS"
      source_identifier = "ALB_HTTP_TO_HTTPS_REDIRECTION_CHECK"
      input_parameters = {
        "MaximumExecutionFrequency" : "TwentyFour_Hours",
      }
  }

请注意,我在资源的

jsonencode
中使用了
input_parameters
,并且已将该字段的变量类型更改为
any
(因此它将接受任何结构的对象)。


4
投票

添加到乔丹的答案。当我尝试向模块添加 json 策略时,我也有类似的担忧。

我使用

any
对象类型代替
string
对象类型。

这是我修复它的方法

模块main.tf

resource "aws_ecr_repository_policy" "main" {
  repository = var.repository_name
  policy     = var.repository_policy
}

模块变量.tf

variable "repository_name" {
  type        = string
  description = "Name of the repository."
}

variable "repository_policy" {
  type        = any
  description = "The policy document. This is a JSON formatted string."
}

资源创建main.tf

# ECR Repository for container images
module "ecr_repository_1" {
  source = "../../../../modules/aws/ecr-repository"

  ecr_repository_name  = var.ecr_repository_name.1
  image_tag_mutability = var.image_tag_mutability
  image_scan_on_push   = var.image_scan_on_push
  tag_environment      = local.tag_environment
  tag_terraform        = local.tag_terraform.true
}

# ECR Repository policies
module "ecr_repository_policy_1" {
  source = "../../../../modules/aws/ecr-repository-policy"

  repository_name   = var.ecr_repository_name.1
  repository_policy = var.repository_policy.1
}

资源创建变量.tf

variable "ecr_repository_name" {
  type        = map(string)
  description = "Name of the repository."
  default = {
    "1" = "my-backend-api"
  }
}

variable "image_tag_mutability" {
  type        = string
  description = "The tag mutability setting for the repository. Must be one of: MUTABLE or IMMUTABLE. Defaults to MUTABLE."
  default     = "MUTABLE"
}

variable "image_scan_on_push" {
  type        = bool
  description = "Indicates whether images are scanned after being pushed to the repository (true) or not scanned (false)."
  default     = true
}

variable "repository_policy" {
  type        = any
  description = "The policy document. This is a JSON formatted string."
  default = {
    "1" = <<EOF
          {
              "Version": "2008-10-17",
              "Statement": [
                  {
                      "Sid": "new policy",
                      "Effect": "Allow",
                      "Principal": "*",
                      "Action": [
                          "ecr:GetDownloadUrlForLayer",
                          "ecr:BatchGetImage",
                          "ecr:BatchCheckLayerAvailability",
                          "ecr:PutImage",
                          "ecr:InitiateLayerUpload",
                          "ecr:UploadLayerPart",
                          "ecr:CompleteLayerUpload",
                          "ecr:DescribeRepositories",
                          "ecr:GetRepositoryPolicy",
                          "ecr:ListImages",
                          "ecr:DeleteRepository",
                          "ecr:BatchDeleteImage",
                          "ecr:SetRepositoryPolicy",
                          "ecr:DeleteRepositoryPolicy"
                      ]
                  }
              ]
          }
          EOF
  }
}

2
投票

您可以创建您的 json 字符串,如下所示:

variable "managed_rules" {

  type = map(object({
    name              = string
    description       = string
    owner             = string
    source_identifier = string
# Is there a variable for strings in JSON format?
    input_parameters  = string
  }))
  
  default = {
    "1" = {
      name              = "alb-http-to-https-redirection-check"
      description       = "Checks whether HTTP to HTTPS redirection is configured on all HTTP listeners of Application Load Balancers. The rule is NON_COMPLIANT if one or more HTTP listeners of Application Load Balancer do not have HTTP to HTTPS redirection configured."
      owner             = "AWS"
      source_identifier = "ALB_HTTP_TO_HTTPS_REDIRECTION_CHECK"
      input_parameters = <<EOL
      {
        "MaximumExecutionFrequency" : "TwentyFour_Hours",
      }
EOL
  }
 } 
}  

但是如果你想解析这个字符串,你必须使用

jsondecode
。您不能在变量中使用函数,因此必须稍后完成。


0
投票

或者,您可以使用属性类型对象或对象列表代替字符串类型,并直接使用或如果使用列表则通过循环进行迭代。


-1
投票
input_parameters = {
    "MaximumExecutionFrequency" : "TwentyFour_Hours",
  }

这必须是字符串而不是对象,因为您将其定义为字符串

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