diff --git a/internal/configs/import.go b/internal/configs/import.go index 8d83cb4a97..4a434d2088 100644 --- a/internal/configs/import.go +++ b/internal/configs/import.go @@ -150,3 +150,16 @@ func exprToResourceTraversal(expr hcl.Expression) (hcl.Traversal, hcl.Diagnostic return trav, diags } + +// parseImportToStatic attempts to parse the To address of an import block +// statically to get the resource address. This returns false when the address +// cannot be parsed, which is usually a result of dynamic index expressions +// using for_each. +func parseImportToStatic(expr hcl.Expression) (addrs.AbsResourceInstance, bool) { + var toDiags tfdiags.Diagnostics + traversal, hd := hcl.AbsTraversalForExpr(expr) + toDiags = toDiags.Append(hd) + to, td := addrs.ParseAbsResourceInstance(traversal) + toDiags = toDiags.Append(td) + return to, !toDiags.HasErrors() +} diff --git a/internal/configs/module.go b/internal/configs/module.go index 52faf4a7d2..bec7e19e4f 100644 --- a/internal/configs/module.go +++ b/internal/configs/module.go @@ -421,16 +421,18 @@ func (m *Module) appendFile(file *File) hcl.Diagnostics { m.Moved = append(m.Moved, file.Moved...) for _, i := range file.Import { + iTo, iToOK := parseImportToStatic(i.To) for _, mi := range m.Import { - // FIXME: this doesn't allow multiple blocks for individual instances - if i.ToResource.Equal(mi.ToResource) { + // Try to detect duplicate import targets. We need to see if the to + // address can be parsed statically. + miTo, miToOK := parseImportToStatic(mi.To) + if iToOK && miToOK && iTo.Equal(miTo) { diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, - Summary: fmt.Sprintf("Duplicate import configuration for %q", i.To), - Detail: fmt.Sprintf("An import block for the resource %q was already declared at %s. A resource can have only one import block.", i.To, mi.DeclRange), - Subject: &i.DeclRange, + Summary: fmt.Sprintf("Duplicate import configuration for %q", i.ToResource), + Detail: fmt.Sprintf("An import block for the resource %q was already declared at %s. A resource can have only one import block.", i.ToResource, mi.DeclRange), + Subject: i.To.Range().Ptr(), }) - continue } }