Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

json: cannot unmarshal string into Go struct field MountPoint.MountPoints.ReadOnly of type bool #108

Closed
danieltharp opened this issue Dec 22, 2020 · 6 comments
Labels
bug 🐛 An issue with the system

Comments

@danieltharp
Copy link

Describe the Bug

When you provide a mount point with readOnly = true as a mapped item, it fails to be translated to valid JSON. The same is true of readOnly = "true".

Expected Behavior

A read-only volume to be created.

Steps to Reproduce

Apply an otherwise valid container definition with this code block.

mount_points = [
        {
            sourceVolume = "docker-socket"
            containerPath = "/var/run/docker.sock"
            readOnly        = true
        },
        {
            sourceVolume = "letsencrypt"
            containerPath = "/letsencrypt"
        }
    ]

If relevant, this is one of several definitions running under one service, so the final definition is laid out as:

container_definitions    = "[${module.cache.json_map_encoded},${module.database.json_map_encoded},${module.php-fpm.json_map_encoded},${module.reverse-proxy.json_map_encoded}]"

Screenshots

Error: ECS Task Definition container_definitions is invalid: Error decoding JSON: json: cannot unmarshal string into Go struct field MountPoint.MountPoints.ReadOnly of type bool

  on ecs.tf line 62, in resource "aws_ecs_task_definition" "dev_stack_task":
  62:   container_definitions    = "[${module.cache.json_map_encoded},${module.database.json_map_encoded},${module.php-fpm.json_map_encoded},${module.reverse-proxy.json_map_encoded}]"

Environment (please complete the following information):

Anything that will help us triage the bug will help. Here are some ideas:

  • Terraform Cloud, v0.13.5
@danieltharp danieltharp added the bug 🐛 An issue with the system label Dec 22, 2020
@evanstoddard23
Copy link

I'm running into this even when I don't specify a value for readOnly. Have you found any workarounds?

@evanstoddard23
Copy link

I was able to get around this issue by overriding mountPoints in the container_definitions variable.

@nitrocode
Copy link
Member

nitrocode commented Feb 24, 2021

I don't see this issue.

module "container" {
  source = "cloudposse/ecs-container-definition/aws"

  container_name  = "hello"
  container_image = "world"

  mount_points = [
    {
      sourceVolume  = "docker-socket"
      containerPath = "/var/run/docker.sock"
      readOnly      = true
    },
    {
      sourceVolume  = "letsencrypt"
      containerPath = "/letsencrypt"
    }
  ]
}

output "json" {
  value = module.container.json_map_encoded
}
$ terraform apply
$ terraform output -raw json | jq -M .
{
  "cpu": 0,
  "essential": true,
  "image": "world",
  "mountPoints": [
    {
      "containerPath": "/var/run/docker.sock",
      "readOnly": "true",
      "sourceVolume": "docker-socket"
    },
    {
      "containerPath": "/letsencrypt",
      "readOnly": "false",
      "sourceVolume": "letsencrypt"
    }
  ],
  "name": "hello",
  "portMappings": [],
  "readonlyRootFilesystem": false,
  "volumesFrom": []
}

Could either of you provide a MVRE ?

@nitrocode
Copy link
Member

I cannot reproduce this. Please feel free to reply if you can provide an MVRE.

@jcarlson
Copy link

jcarlson commented Sep 28, 2022

I am able to reproduce this with a minimal example:

variable "foo_volumes" {
  type = list(object({
    name            = string
    container_path  = string
  }))

  default = []
}

variable "bar_volumes" {
  type = list(object({
    name           = string
    container_path = string
    read_only      = bool
  }))

  default = [
    {
      name           = "docker_sock"
      container_path = "/var/run/docker.sock"
      read_only      = false
    }
  ]
}

locals {
  container_definitions = [{
    mountPoints = [for volume in concat(var.foo_volumes, var.bar_volumes) : {
      containerPath = volume.container_path
      sourceVolume  = volume.name
      readOnly      = try(volume.read_only, false)
    }]
  }]
}

resource "local_file" "container_definitions" {
  filename = "container-definitions.json"
  content  = jsonencode(local.container_definitions)
}

output "container_definitions" {
  value = local.container_definitions
}

output "json" {
  value = jsonencode(local.container_definitions)
}

Under Terraform 0.14.11, the plan produced by this configuration is as follows:

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # local_file.container_definitions will be created
  + resource "local_file" "container_definitions" {
      + content              = jsonencode(
            [
              + {
                  + mountPoints = [
                      + {
                          + containerPath = "/var/run/docker.sock"
                          + readOnly      = false
                          + sourceVolume  = "docker_sock"
                        },
                    ]
                },
            ]
        )
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "container-definitions.json"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + container_definitions = [
      + {
          + mountPoints = [
              + {
                  + containerPath = "/var/run/docker.sock"
                  + readOnly      = false
                  + sourceVolume  = "docker_sock"
                },
            ]
        },
    ]
  + json                  = jsonencode(
        [
          + {
              + mountPoints = [
                  + {
                      + containerPath = "/var/run/docker.sock"
                      + readOnly      = false
                      + sourceVolume  = "docker_sock"
                    },
                ]
            },
        ]
    )

Using Terraform 0.15.5, the plan is different:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # local_file.container_definitions will be created
  + resource "local_file" "container_definitions" {
      + content              = jsonencode(
            [
              + {
                  + mountPoints = [
                      + {
                          + containerPath = "/var/run/docker.sock"
                          + readOnly      = "false"
                          + sourceVolume  = "docker_sock"
                        },
                    ]
                },
            ]
        )
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "container-definitions.json"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + container_definitions = [
      + {
          + mountPoints = [
              + {
                  + containerPath = "/var/run/docker.sock"
                  + readOnly      = "false"
                  + sourceVolume  = "docker_sock"
                },
            ]
        },
    ]
  + json                  = jsonencode(
        [
          + {
              + mountPoints = [
                  + {
                      + containerPath = "/var/run/docker.sock"
                      + readOnly      = "false"
                      + sourceVolume  = "docker_sock"
                    },
                ]
            },
        ]
    )

Note that the readOnly attribute in 0.14.11 is encoded as a boolean, while in 0.15.5 it is encoded as a string. Replacing concat(var.foo_volumes, var.bar_volumes) with var.bar_volumes in this example resolves this issue, so there appears to be some sort of regression in the way objects are iterated after concatenation.

Terraform v1.2.9 produces a similar plan to v0.15.5.

@jcarlson
Copy link

I filed a proper bug report with Terraform, as this issue does not appear to be related to this module or any providers. See: hashicorp/terraform#31894

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 An issue with the system
Projects
None yet
Development

No branches or pull requests

4 participants