1

I have just upgraded from terraform v0.11 to v0.12 But i am facing lot of error

complete code @ https://github.com/sivatest82/Terraform1/tree/master/secretsv12

especially in the block

 secrets = [

    {
      secret_id = "docker_secret.mysql_db_password.id"
      secret_name = "docker_secret.mysql_db_password.name"
      file_name = "/run/secrets/docker_secret.mysql_db_password.name"
    },

    {secret_id = "docker_secret.mysql_root_password.id"
      secret_name = "docker_secret.mysql_root_password.name"
      file_name = "/run/secrets/docker_secret.mysql_root_password.name"
    }
  ]

v0.11 code which had no issue

   resource "docker_service" "mysql-service" {
  name = "mysql_db"

  task_spec {
    container_spec {
      image = "${docker_image.mysql_image.name}"

      secrets = [
        {
          secret_id   = "${docker_secret.mysql_root_password.id}"
          secret_name = "${docker_secret.mysql_root_password.name}"
          file_name   = "/run/secrets/${docker_secret.mysql_root_password.name}"
        },
        {
          secret_id   = "${docker_secret.mysql_db_password.id}"
          secret_name = "${docker_secret.mysql_db_password.name}"
          file_name   = "/run/secrets/${docker_secret.mysql_db_password.name}"
        }
      ]

      env {
        MYSQL_ROOT_PASSWORD_FILE = "/run/secrets/${docker_secret.mysql_root_password.name}"
        MYSQL_DATABASE           = "mydb"
        MYSQL_PASSWORD_FILE      = "/run/secrets/${docker_secret.mysql_db_password.name}"
      }

      mounts = [
        {
          target = "/var/lib/mysql"
          source = "${docker_volume.mysql_data_volume.name}"
          type   = "volume"
        }
      ]
    }
    networks = [
      "${docker_network.private_overlay_network.name}"
    ]
  }
}

v0.12 code

resource "docker_service" "mysql-service" {
  name = "mysql_db"

  task_spec {
    container_spec {
      image = "docker_image.mysql_image.name"

      secrets = [

        {
          secret_id = "docker_secret.mysql_db_password.id"
          secret_name = "docker_secret.mysql_db_password.name"
          file_name = "/run/secrets/docker_secret.mysql_db_password.name"
        },

        {secret_id = "docker_secret.mysql_root_password.id"
          secret_name = "docker_secret.mysql_root_password.name"
          file_name = "/run/secrets/docker_secret.mysql_root_password.name"
        }
      ]


      env = {
        MYSQL_ROOT_PASSWORD_FILE = "/run/secrets/docker_secret.mysql_root_password.name"
        MYSQL_DATABASE           = "mydb"
        MYSQL_PASSWORD_FILE      = "/run/secrets/docker_secret.mysql_db_password.name"
      }

      mounts = {
          target = "/var/lib/mysql"
          source = "docker_volume.mysql_data_volume.name"
          type   = "volume"
        }

    }

    networks = "docker_network.private_overlay_network.name"


  }
}

Error

[cloud_user@siwgftd9213c secrets]$ terraform validate

Error: Unsupported argument

  on main.tf line 8, in resource "docker_service" "mysql-service":
   8:       secrets = {

An argument named "secrets" is not expected here. Did you mean to define a
block of type "secrets"?


Error: Unsupported argument

  on main.tf line 26, in resource "docker_service" "mysql-service":
  26:       mounts = {

An argument named "mounts" is not expected here. Did you mean to define a
block of type "mounts"?


Error: Incorrect attribute value type

  on main.tf line 34, in resource "docker_service" "mysql-service":
  34:     networks = "docker_network.private_overlay_network.name"

Inappropriate value for attribute "networks": set of string required.

I have already have a seperate file for them

Secrets.tf

resource "docker_secret" "mysql_root_password" {
  name = "root_password"
  data = "var.mysql_root_password"
}

resource "docker_secret" "mysql_db_password" {
  name = "db_password"
  data = "var.mysql_db_password"
}

And variables tf file

variable "mysql_root_password" {
  default     = "cDRzU1dvUmQwIQo="
}

variable "mysql_db_password" {
  default     = "cDRzU1dvUmQwIQo="
}

After tfvars.tf creation

  • Able to compile code
  • But unable to apply the plan

Error: Error response from daemon: rpc error: code = InvalidArgument desc = malformed secret reference

on main.tf line 1, in resource "docker_service" "mysql-service":
1: resource "docker_service" "mysql-service" {

main.tf

    resource "docker_service" "mysql-service" {
  name = "mysql_db"

  task_spec {
    container_spec {
      image = docker_image.mysql_image.name

      secrets {
        file_name = "${local.secrets[0].file_name}"
        secret_id = "${local.secrets[0].secret_id}"
      }

      secrets {
        file_name = "${local.secrets[1].file_name}"
        secret_id = "${local.secrets[1].secret_id}"
      }

      env = {
        MYSQL_ROOT_PASSWORD_FILE = "/run/secrets/${docker_secret.mysql_root_password.name}"
        MYSQL_DATABASE           = "mydb"
        MYSQL_PASSWORD_FILE      = "/run/secrets/${docker_secret.mysql_db_password.name}"
      }

      mounts {
          target = "/var/lib/mysql"
          source = "docker_volume.mysql_data_volume.name"
          type   = "volume"
        }
    }

    networks = [docker_network.private_overlay_network.name]
  }
}

tfvars.tf

    locals {
 secrets = [
        {   secret_id   = docker_secret.mysql_root_password.id
            secret_name = docker_secret.mysql_root_password.name
            file_name   = "/run/secrets/${docker_secret.mysql_root_password.name}"
        },
        {
            secret_id   =    docker_secret.mysql_db_password.id
            secret_name =    docker_secret.mysql_db_password.name
            file_name   = "/run/secrets/${docker_secret.mysql_db_password.name}"
       }
    ]
}
4
  • If you follow the steps described in the upgrade guide then the automatic upgrade tool can automatically address these problems. Unfortunately it can only take valid Terraform 0.11 configuration as input, so to use it now would require undoing the manual changes you already made and then running the tool first before making any additional changes. Commented May 4, 2020 at 20:21
  • I am straight away using v0.12.. so i am not upgrading
    – Sivakumarj
    Commented May 5, 2020 at 3:00
  • what i mean is , i installed v0.11 ..written no code, upgraded to v0.12.. written the above code
    – Sivakumarj
    Commented May 5, 2020 at 6:23
  • Ahh, okay! Sorry, I misunderstood your comment that you were upgrading from v0.11 to v0.12. Commented May 5, 2020 at 18:08

3 Answers 3

2

It looks like there are two different problems here, so I'll answer them separately.


First, we'll talk about the errors of this type:

Error: Unsupported argument

  on main.tf line 8, in resource "docker_service" "mysql-service":
   8:       secrets = {

An argument named "secrets" is not expected here. Did you mean to define a
block of type "secrets"?

This error is talking about the distinction described in the Terraform documentation section Arguments and Blocks, and is telling you that secrets is defined in the provider's schema as using nested block syntax rather than argument syntax.

The syntax for nested blocks and the syntax for literal object values are both similar in that they use { } as delimiters, but the meaning of these and what is valid inside the braces in each case is distinct.

To fix this, you can use the block syntax to define these nested objects:

  secrets {
    secret_id   = docker_secret.mysql_root_password.id
    secret_name = docker_secret.mysql_root_password.name
    file_name   = "/run/secrets/${docker_secret.mysql_root_password.name}"
  }
  secrets {
    secret_id   = docker_secret.mysql_db_password.id
    secret_name = docker_secret.mysql_db_password.name
    file_name   = "/run/secrets/${docker_secret.mysql_db_password.name}"
  }

The same is true for the mounts block type:

  mounts {
    target = "/var/lib/mysql"
    source = docker_volume.mysql_data_volume.name
    type   = "volume"
  }

The other error message you saw is an unrelated problem:

Error: Incorrect attribute value type

  on main.tf line 34, in resource "docker_service" "mysql-service":
  34:     networks = "docker_network.private_overlay_network.name"

Inappropriate value for attribute "networks": set of string required.

This error is saying that the networks argument requires a set of strings, but the value you gave here is a single string. This is happening because you've put the reference expression in quotes, and so Terraform assumes you are intending to give a literal string rather than a reference here. The first step to address this is to remove the quotes so to make this a reference expression rather than a literal expression:

  networks = docker_network.private_overlay_network.name

That's not sufficient for this particular situation though, because this name attribute is just a single string rather than a set of strings, and so the above change alone will not fully fix the problem. To address this secondary problem we can use brackets [ ] to construct a single-element sequence:

  networks = [docker_network.private_overlay_network.name]

This argument expects a set of strings rather than a sequence of strings, but that's okay here because Terraform will automatically convert the sequence into a set. (A set is an unordered collection of distinct values, whereas a sequence is an ordered collection of values that may contain duplicates.)

1
1

These were made as errors in 0.12. You need to put these into tfvars file in a locals definition.

locals {
   secret_id = "docker_secret.mysql_db_password.id"
   secret_name = "docker_secret.mysql_db_password.name"
   file_name = "/run/secrets/docker_secret.mysql_db_password.name"

}

Update: Using a list:

locals {
    secrets = [
        {
            secret_id = "docker_secret.mysql_db_password.id"
            secret_name = "docker_secret.mysql_db_password.name"
            file_name = "/run/secrets/docker_secret.mysql_db_password.name"
        },
        {
            secret_id = "docker_secret.mysql_root_password.id"
            secret_name = "docker_secret.mysql_root_password.name"
            file_name = "/run/secrets/docker_secret.mysql_root_password.name"
        }
    ]
}

Then to access an individual value, use indexing with variable evaluation: ${local.secrets[1].file_name}.

8
  • 1) I already have secrets.tf and variables.tf files for them.. #update2 in the question 2) If i mention the secret_id,secret_name,file_name in vars.tf, how can i refer them in main.tf 3) Because the "docker_secret.mysql_db_password.id" and "docker_secret.mysql_db_password.name" are already in secrets.tf file
    – Sivakumarj
    Commented May 3, 2020 at 5:06
  • You access them with variable evaluation, such as ${local.secret_id}.
    – Arcege
    Commented May 3, 2020 at 16:06
  • ok. but what if , if i have two secrets.. as mentioned in my example
    – Sivakumarj
    Commented May 4, 2020 at 0:16
  • I've updated with the example from the OP
    – Arcege
    Commented May 4, 2020 at 0:38
  • yeap able to compile.. but scenario 1)mentioning secrets in main.tf along with tfvars.tf file.. getting error while applying the plan . Error updated in the question scenario 2) not mentioning secrets in main.tf but with tfvars.tf file .. able to apply plan.. but mysql service is not coming up.. it comes up and goes down in seconds..may be it is searching for secrets in the main.tf file?
    – Sivakumarj
    Commented May 5, 2020 at 3:04
0

According to the documentation, you should change your secrets handling to following syntax:

      secrets = [

        {
          secret_id   = docker_secret.mysql_db_password.id
          secret_name = docker_secret.mysql_db_password.name
          file_name   = "/run/secrets/${docker_secret.mysql_db_password.name}"
        },

        {
          secret_id   = docker_secret.mysql_root_password.id
          secret_name = docker_secret.mysql_root_password.name
          file_name   = "/run/secrets/${docker_secret.mysql_root_password.name}"
        }
      ]

So you pass the actual secret ID to the service object and not the Terraform resource reference as a string. The only difference between Terraform 0.11 and 0.12 code is, that in 0.12 you can remove the interpolation syntax (so ${}), if you don't actually use it, as you only pass the attribute of other resource, with no additional formatting.

1
  • i have already tried it.. not working in v0.12
    – Sivakumarj
    Commented May 5, 2020 at 3:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.