abv1998
abv1998

Reputation: 25

Terraform error: Expected an attribute value, introduced by an equals sign ("=")

I'm really new to terraform and I'm having an issue doing something very basic. I will only put in the relevant codes to help save time

In my variables.tf file, I have the following:

variable "keys_location" {
  type        = string
  description = "keys are here"
}

I have kept the keys that are referenced in my wrkspace.vars, I have the following:

keys_location = {
    "./keys/testing/certificate1.cer", 
    "./keys/testing/certificate2.cer",
}

And in my main.tf, I have this

resource "azurerm_virtual_network_gateway" "gw" {
  name                = "testing-${terraform.workspace}"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  type     = "Vpn"
  vpn_type = "RouteBased"
  active_active = false
  enable_bgp    = false
  sku           = "VpnGw1"
  ip_configuration {
    name                          = "config"
    public_ip_address_id          = azurerm_public_ip.ip.id
    private_ip_address_allocation = "Dynamic"
    subnet_id                     = azurerm_subnet.subnet.id
  }

  test_config {
        test_protocols = ["IkeV2","SSTP"]
        address_space = [var.vpn_test_address_space]
        dynamic "keys_location" {
          for_each = var.keys_location
            root_certificate {
            name = "Root-Cert"
            public_cert_data = file(var.keys_location)
          }
        }
  }

When I do a terraform plan, the error I get is:

Error: Missing attribute value

  on vars/wrkspace.vars line 5:
   4: keys_location = {
   5:     "./keys/testing/certificate1.cer",

Expected an attribute value, introduced by an equals sign ("=").

How can this issue be fixed?

Upvotes: 0

Views: 12551

Answers (2)

Martin Atkins
Martin Atkins

Reputation: 74694

I can see two problems with what you shared, and one of them is the cause of this error.


The error itself is reporting that you've used braces { }, which are delimiters used for writing object/map values, but the content of the braces looks like you intended to define a list instead.

If you did intend to define a list then you should use square brackets [ ] to indicate that:

keys_location = [
  "./keys/testing/certificate1.cer", 
  "./keys/testing/certificate2.cer",
]

If you actually did intend to declare a map then you'll need to choose a unique key for each element, which is what this error message is trying to tell you (because it's assuming you wanted to declare a map). I can't predict what would be good map keys so I've just used some placeholder ones for example here:

keys_location = {
  cert1 = "./keys/testing/certificate1.cer", 
  cert2 = "./keys/testing/certificate2.cer",
}

If you make a change like I suggested above then I expect you will encounter the second error, which is that you've declared your variable as type = string but you've assigned it a list or map value. To make that work you'll need to specify a more appropriate type constraint for the variable.

If you intended to provide a list (using square brackets [ ]) then you could declare the variable as follows:

variable "keys_location" {
  type = list(string)
}

If you intended to provide a map (using braces { }) then you could declare the variable as follows:

variable "keys_location" {
  type = map(string)
}

Upvotes: 1

logyball
logyball

Reputation: 178

The Terraform for_each meta-argument operates on maps and sets, and iteration is done over either keys and values (in the case of maps) or values (in the case of sets). In order to iterate over the values in a set, one should use each.key.

In your case, because you're actually iterating over the values in the path_to_keys variable, the keys_location variable is unnecessary. You should instead reference each of the values inside the path_to_keys variable.

One possible solution would be changing your main.tf to the following:

resource "azurerm_virtual_network_gateway" "gw" {
  name                = "testing-${terraform.workspace}"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  type     = "Vpn"
  vpn_type = "RouteBased"
  active_active = false
  enable_bgp    = false
  sku           = "VpnGw1"
  ip_configuration {
    name                          = "config"
    public_ip_address_id          = azurerm_public_ip.ip.id
    private_ip_address_allocation = "Dynamic"
    subnet_id                     = azurerm_subnet.subnet.id
  }

  test_config {
        test_protocols = ["IkeV2","SSTP"]
        address_space = [var.vpn_test_address_space]
        dynamic "keys_location" {
          for_each = var.path_to_keys
            root_certificate {
            name = "Root-Cert"
            public_cert_data = file(each.key)
          }
        }
  }

your variables.tf to:

variable "path_to_keys" {
  type        = set
  description = "keys are here"
}

and your wrkspace.tfvars to:

path_to_keys = [
    "./keys/testing/certificate1.cer", 
    "./keys/testing/certificate2.cer",
]

Upvotes: 1

Related Questions