Terraform: False positive on deprecation warning for interpolation-only expressions when building maps using variables as keys

Created on 8 Oct 2020  ยท  2Comments  ยท  Source: hashicorp/terraform

As a result of the expansion of the detection of interpolation only syntax, code which uses interpolation-only syntax to construct maps is now being picked up by the detection mechanism. However, it does not seem to be possible to build maps in this fashion without using itnerpolation-only syntax.

Terraform Version

$ terraform --version
Terraform v0.13.4

Terraform Configuration Files

For deprecation warning:

locals {
  config = {
    "${var.x}" = {
      foo = "bar"
    },
    "${var.y}" = {
      foo= "baz"
    }
  }
}

variable "x" {
  default = "x"
}

variable "y"  {
  default = "y"
}

For error:

locals {
  config = {
    var.x = {
      foo = "bar"
    },
    var.y = {
      foo= "baz"
    }
  }
}

variable "x" {
  default = "x"
}

variable "y"  {
  default = "y"
}

Expected Behavior

Deprecation warning should not be shown if removing interpolation-only syntax results in errors. Or, one should be able to construct maps using the short form?

Actual Behavior

Removing the interpolation only syntax as suggested by the deprecation warning results in the following error during plan/apply:

$ terraform plan
2020/10/08 10:27:01 [INFO] Terraform version: 0.13.4  
2020/10/08 10:27:01 [INFO] Go runtime version: go1.14.7
2020/10/08 10:27:01 [INFO] CLI args: []string{"/usr/bin/terraform", "plan"}
2020/10/08 10:27:01 [DEBUG] Attempting to open CLI config file: /home/.../.terraformrc
2020/10/08 10:27:01 [DEBUG] File doesn't exist, but doesn't need to. Ignoring.
2020/10/08 10:27:01 [DEBUG] ignoring non-existing provider search directory terraform.d/plugins
2020/10/08 10:27:01 [DEBUG] ignoring non-existing provider search directory /home/.../.terraform.d/plugins
2020/10/08 10:27:01 [DEBUG] ignoring non-existing provider search directory /home/.../.local/share/terraform/plugins
2020/10/08 10:27:01 [DEBUG] ignoring non-existing provider search directory /usr/share/ubuntu/terraform/plugins
2020/10/08 10:27:01 [DEBUG] ignoring non-existing provider search directory /usr/local/share/terraform/plugins
2020/10/08 10:27:01 [DEBUG] ignoring non-existing provider search directory /usr/share/terraform/plugins
2020/10/08 10:27:01 [DEBUG] ignoring non-existing provider search directory /var/lib/snapd/desktop/terraform/plugins
2020/10/08 10:27:01 [INFO] CLI command args: []string{"plan"}
2020/10/08 10:27:01 [TRACE] Meta.Backend: no config given or present on disk, so returning nil config
2020/10/08 10:27:01 [TRACE] Meta.Backend: backend has not previously been initialized in this working directory
2020/10/08 10:27:01 [DEBUG] New state was assigned lineage "348925a7-9a60-c658-aff9-56c49b522c53"
2020/10/08 10:27:01 [TRACE] Meta.Backend: using default local state only (no backend configuration, and no existing initialized backend)
2020/10/08 10:27:01 [TRACE] Meta.Backend: instantiated backend of type <nil>
2020/10/08 10:27:01 [DEBUG] checking for provisioner in "."
2020/10/08 10:27:01 [DEBUG] checking for provisioner in "/usr/bin"
2020/10/08 10:27:01 [INFO] Failed to read plugin lock file .terraform/plugins/linux_amd64/lock.json: open .terraform/plugins/linux_amd64/lock.json: no such file or directory
2020/10/08 10:27:01 [TRACE] Meta.Backend: backend <nil> does not support operations, so wrapping it in a local backend
2020/10/08 10:27:01 [INFO] backend/local: starting Plan operation
2020/10/08 10:27:01 [TRACE] backend/local: requesting state manager for workspace "default"
2020/10/08 10:27:01 [TRACE] backend/local: state manager for workspace "default" will:
 - read initial snapshot from terraform.tfstate
 - write new snapshots to terraform.tfstate
 - create any backup at terraform.tfstate.backup
2020/10/08 10:27:01 [TRACE] backend/local: requesting state lock for workspace "default"
2020/10/08 10:27:01 [TRACE] statemgr.Filesystem: preparing to manage state snapshots at terraform.tfstate
2020/10/08 10:27:01 [TRACE] statemgr.Filesystem: no previously-stored snapshot exists
2020/10/08 10:27:01 [TRACE] statemgr.Filesystem: locking terraform.tfstate using fcntl flock
2020/10/08 10:27:01 [TRACE] statemgr.Filesystem: writing lock metadata to .terraform.tfstate.lock.info
2020/10/08 10:27:01 [TRACE] backend/local: reading remote state for workspace "default"
2020/10/08 10:27:01 [TRACE] statemgr.Filesystem: reading latest snapshot from terraform.tfstate
2020/10/08 10:27:01 [TRACE] statemgr.Filesystem: snapshot file has nil snapshot, but that's okay
2020/10/08 10:27:01 [TRACE] statemgr.Filesystem: read nil snapshot
2020/10/08 10:27:01 [TRACE] backend/local: retrieving local state snapshot for workspace "default"
2020/10/08 10:27:01 [TRACE] backend/local: building context for current working directory
2020/10/08 10:27:01 [TRACE] terraform.NewContext: starting
2020/10/08 10:27:01 [TRACE] terraform.NewContext: loading provider schemas
2020/10/08 10:27:01 [TRACE] terraform.NewContext: complete
2020/10/08 10:27:01 [TRACE] backend/local: finished building terraform.Context
2020/10/08 10:27:01 [TRACE] backend/local: requesting interactive input, if necessary
2020/10/08 10:27:01 [TRACE] Context.Input: Prompting for provider arguments
2020/10/08 10:27:01 [TRACE] backend/local: running validation operation
2020/10/08 10:27:01 [INFO] terraform: building graph: GraphTypeValidate
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.ConfigTransformer
2020/10/08 10:27:01 [TRACE] ConfigTransformer: Starting for path: 
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.ConfigTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.LocalTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.LocalTransformer with new graph:
  local.config (expand) - *terraform.nodeExpandLocal
  ------
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.OutputTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.OutputTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.OrphanResourceInstanceTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.OrphanResourceInstanceTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.StateTransformer
2020/10/08 10:27:01 [TRACE] StateTransformer: state is empty, so nothing to do
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.StateTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.OrphanOutputTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.OrphanOutputTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.AttachResourceConfigTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.AttachResourceConfigTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.AttachStateTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.AttachStateTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.RootVariableTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.RootVariableTransformer with new graph:
  local.config (expand) - *terraform.nodeExpandLocal
  var.x - *terraform.NodeRootVariable
  var.y - *terraform.NodeRootVariable
  ------
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.MissingProvisionerTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.MissingProvisionerTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.ProvisionerTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.ProvisionerTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.ModuleVariableTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.ModuleVariableTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.graphTransformerMulti
2020/10/08 10:27:01 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.ProviderConfigTransformer
2020/10/08 10:27:01 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.ProviderConfigTransformer with new graph:
  local.config (expand) - *terraform.nodeExpandLocal
  var.x - *terraform.NodeRootVariable
  var.y - *terraform.NodeRootVariable
  ------
2020/10/08 10:27:01 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.MissingProviderTransformer
2020/10/08 10:27:01 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.MissingProviderTransformer (no changes)
2020/10/08 10:27:01 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.ProviderTransformer
2020/10/08 10:27:01 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.ProviderTransformer (no changes)
2020/10/08 10:27:01 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.PruneProviderTransformer
2020/10/08 10:27:01 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.PruneProviderTransformer (no changes)
2020/10/08 10:27:01 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.ParentProviderTransformer
2020/10/08 10:27:01 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.ParentProviderTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.graphTransformerMulti (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.RemovedModuleTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.RemovedModuleTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.AttachSchemaTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.AttachSchemaTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.ModuleExpansionTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.ModuleExpansionTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.ReferenceTransformer
2020/10/08 10:27:01 [DEBUG] ReferenceTransformer: "local.config (expand)" references: [var.x var.y]
2020/10/08 10:27:01 [DEBUG] ReferenceTransformer: "var.x" references: []
2020/10/08 10:27:01 [DEBUG] ReferenceTransformer: "var.y" references: []
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.ReferenceTransformer with new graph:
  local.config (expand) - *terraform.nodeExpandLocal
    var.x - *terraform.NodeRootVariable
    var.y - *terraform.NodeRootVariable
  var.x - *terraform.NodeRootVariable
  var.y - *terraform.NodeRootVariable
  ------
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.attachDataResourceDependenciesTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.attachDataResourceDependenciesTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.TargetsTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.TargetsTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.ForcedCBDTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.ForcedCBDTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.CountBoundaryTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.CountBoundaryTransformer with new graph:
  local.config (expand) - *terraform.nodeExpandLocal
    var.x - *terraform.NodeRootVariable
    var.y - *terraform.NodeRootVariable
  meta.count-boundary (EachMode fixup) - *terraform.NodeCountBoundary
    local.config (expand) - *terraform.nodeExpandLocal
    var.x - *terraform.NodeRootVariable
    var.y - *terraform.NodeRootVariable
  var.x - *terraform.NodeRootVariable
  var.y - *terraform.NodeRootVariable
  ------
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.CloseProviderTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.CloseProviderTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.CloseProvisionerTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.CloseProvisionerTransformer (no changes)
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.CloseRootModuleTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.CloseRootModuleTransformer with new graph:
  local.config (expand) - *terraform.nodeExpandLocal
    var.x - *terraform.NodeRootVariable
    var.y - *terraform.NodeRootVariable
  meta.count-boundary (EachMode fixup) - *terraform.NodeCountBoundary
    local.config (expand) - *terraform.nodeExpandLocal
    var.x - *terraform.NodeRootVariable
    var.y - *terraform.NodeRootVariable
  root - *terraform.nodeCloseModule
    meta.count-boundary (EachMode fixup) - *terraform.NodeCountBoundary
  var.x - *terraform.NodeRootVariable
  var.y - *terraform.NodeRootVariable
  ------
2020/10/08 10:27:01 [TRACE] Executing graph transform *terraform.TransitiveReductionTransformer
2020/10/08 10:27:01 [TRACE] Completed graph transform *terraform.TransitiveReductionTransformer with new graph:
  local.config (expand) - *terraform.nodeExpandLocal
    var.x - *terraform.NodeRootVariable
    var.y - *terraform.NodeRootVariable
  meta.count-boundary (EachMode fixup) - *terraform.NodeCountBoundary
    local.config (expand) - *terraform.nodeExpandLocal
  root - *terraform.nodeCloseModule
    meta.count-boundary (EachMode fixup) - *terraform.NodeCountBoundary
  var.x - *terraform.NodeRootVariable
  var.y - *terraform.NodeRootVariable
  ------
2020/10/08 10:27:01 [DEBUG] Starting graph walk: walkValidate
2020/10/08 10:27:01 [TRACE] dag/walk: visiting "var.y"
2020/10/08 10:27:01 [TRACE] vertex "var.y": starting visit (*terraform.NodeRootVariable)
2020/10/08 10:27:01 [TRACE] vertex "var.y": evaluating
2020/10/08 10:27:01 [TRACE] [walkValidate] Entering eval tree: var.y
2020/10/08 10:27:01 [TRACE] eval: *terraform.EvalSequence
2020/10/08 10:27:01 [TRACE] [walkValidate] Exiting eval tree: var.y
2020/10/08 10:27:01 [TRACE] vertex "var.y": visit complete
2020/10/08 10:27:01 [TRACE] dag/walk: visiting "var.x"
2020/10/08 10:27:01 [TRACE] vertex "var.x": starting visit (*terraform.NodeRootVariable)
2020/10/08 10:27:01 [TRACE] vertex "var.x": evaluating
2020/10/08 10:27:01 [TRACE] [walkValidate] Entering eval tree: var.x
2020/10/08 10:27:01 [TRACE] eval: *terraform.EvalSequence
2020/10/08 10:27:01 [TRACE] [walkValidate] Exiting eval tree: var.x
2020/10/08 10:27:01 [TRACE] vertex "var.x": visit complete
2020/10/08 10:27:01 [TRACE] dag/walk: visiting "local.config (expand)"
2020/10/08 10:27:01 [TRACE] vertex "local.config (expand)": starting visit (*terraform.nodeExpandLocal)
2020/10/08 10:27:01 [TRACE] vertex "local.config (expand)": expanding dynamic subgraph
2020/10/08 10:27:01 [TRACE] Expanding local: adding local.config as *terraform.NodeLocal
2020/10/08 10:27:01 [TRACE] vertex "local.config (expand)": entering dynamic subgraph
2020/10/08 10:27:01 [TRACE] dag/walk: visiting "local.config"
2020/10/08 10:27:01 [TRACE] vertex "local.config": starting visit (*terraform.NodeLocal)
2020/10/08 10:27:01 [TRACE] vertex "local.config": evaluating
2020/10/08 10:27:01 [TRACE] [walkValidate] Entering eval tree: local.config
2020/10/08 10:27:01 [TRACE] eval: *terraform.EvalLocal
2020/10/08 10:27:01 [ERROR] eval: *terraform.EvalLocal, err: 2 problems:

- Ambiguous attribute key: If this expression is intended to be a reference, wrap it in parentheses. If it's instead intended as a literal name containing periods, wrap it in quotes to create a string literal.
- Ambiguous attribute key: If this expression is intended to be a reference, wrap it in parentheses. If it's instead intended as a literal name containing periods, wrap it in quotes to create a string literal.
2020/10/08 10:27:01 [TRACE] [walkValidate] Exiting eval tree: local.config
2020/10/08 10:27:01 [TRACE] vertex "local.config": visit complete
2020/10/08 10:27:01 [TRACE] vertex "local.config (expand)": dynamic subgraph encountered errors
2020/10/08 10:27:01 [TRACE] vertex "local.config (expand)": visit complete
2020/10/08 10:27:01 [TRACE] dag/walk: upstream of "meta.count-boundary (EachMode fixup)" errored, so skipping
2020/10/08 10:27:01 [TRACE] dag/walk: upstream of "root" errored, so skipping
2020/10/08 10:27:01 [TRACE] statemgr.Filesystem: removing lock metadata file .terraform.tfstate.lock.info
2020/10/08 10:27:01 [TRACE] statemgr.Filesystem: unlocking terraform.tfstate using fcntl flock

Error: Ambiguous attribute key

  on main.tf line 3, in locals:
   3:     var.x = {

If this expression is intended to be a reference, wrap it in parentheses. If
it's instead intended as a literal name containing periods, wrap it in quotes
to create a string literal.


Error: Ambiguous attribute key

  on main.tf line 6, in locals:
   6:     var.y = {

If this expression is intended to be a reference, wrap it in parentheses. If
it's instead intended as a literal name containing periods, wrap it in quotes
to create a string literal.

Steps to Reproduce

Using first config above to observe deprecation warning when running terraform init
Using second config above observe error when running terraform plan

config documentation enhancement

Most helpful comment

Hi @onematchfox

The syntax for evaluating expressions as map keys is to wrap the expression in parenthesis, e.g.

locals {
  config = {
    (var.x) = {
      foo = "bar"
    },
    (var.y) = {
      foo= "baz"
    }
  }
}

See also #26441.

I'll mark this as a documentation enhancement, as it seems to be a point of confusion, and could do with some more examples.

Thanks!

All 2 comments

Hi @onematchfox

The syntax for evaluating expressions as map keys is to wrap the expression in parenthesis, e.g.

locals {
  config = {
    (var.x) = {
      foo = "bar"
    },
    (var.y) = {
      foo= "baz"
    }
  }
}

See also #26441.

I'll mark this as a documentation enhancement, as it seems to be a point of confusion, and could do with some more examples.

Thanks!

I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

Was this page helpful?
0 / 5 - 0 ratings