Skip to content

Commit 765c25d

Browse files
authored
allow interpolation in import block id (#33618)
The import block id field can now reference variables, attributes, and module outputs, as long as the result is a known non-empty string at plan time. A null or unknown value will result in an error. This commit slightly modifies the legacy CLI terraform import code path to construct a synthetic hcl.Expression from the import id passed in from the command line, with no intended change of functionality.
1 parent 8b764f2 commit 765c25d

File tree

17 files changed

+457
-46
lines changed

17 files changed

+457
-46
lines changed

internal/command/import.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/hashicorp/hcl/v2"
1414
"github.com/hashicorp/hcl/v2/hclsyntax"
15+
"github.com/zclconf/go-cty/cty"
1516

1617
"github.com/hashicorp/terraform/internal/addrs"
1718
"github.com/hashicorp/terraform/internal/backend"
@@ -236,7 +237,10 @@ func (c *ImportCommand) Run(args []string) int {
236237
Targets: []*terraform.ImportTarget{
237238
{
238239
Addr: addr,
239-
ID: args[1],
240+
241+
// In the import block, the ID can be an arbitrary hcl.Expression,
242+
// but here it's always interpreted as a literal string.
243+
ID: hcl.StaticExpr(cty.StringVal(args[1]), configs.SynthBody("import", nil).MissingItemRange()),
240244
},
241245
},
242246

internal/configs/import.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ package configs
55

66
import (
77
"github.com/hashicorp/hcl/v2"
8-
"github.com/hashicorp/hcl/v2/gohcl"
98
"github.com/hashicorp/terraform/internal/addrs"
109
)
1110

1211
type Import struct {
13-
ID string
12+
ID hcl.Expression
1413
To addrs.AbsResourceInstance
1514

1615
ProviderConfigRef *ProviderConfigRef
@@ -30,9 +29,7 @@ func decodeImportBlock(block *hcl.Block) (*Import, hcl.Diagnostics) {
3029
diags = append(diags, moreDiags...)
3130

3231
if attr, exists := content.Attributes["id"]; exists {
33-
attrDiags := gohcl.DecodeExpression(attr.Expr, nil, &imp.ID)
34-
diags = append(diags, attrDiags...)
35-
32+
imp.ID = attr.Expr
3633
}
3734

3835
if attr, exists := content.Attributes["to"]; exists {

internal/configs/import_test.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ import (
1414
"github.com/zclconf/go-cty/cty"
1515
)
1616

17+
var (
18+
typeComparer = cmp.Comparer(cty.Type.Equals)
19+
valueComparer = cmp.Comparer(cty.Value.RawEquals)
20+
)
21+
1722
func TestImportBlock_decode(t *testing.T) {
1823
blockRange := hcl.Range{
1924
Filename: "mock.tf",
@@ -52,7 +57,7 @@ func TestImportBlock_decode(t *testing.T) {
5257
},
5358
&Import{
5459
To: mustAbsResourceInstanceAddr("test_instance.bar"),
55-
ID: "foo",
60+
ID: foo_str_expr,
5661
DeclRange: blockRange,
5762
},
5863
``,
@@ -76,7 +81,7 @@ func TestImportBlock_decode(t *testing.T) {
7681
},
7782
&Import{
7883
To: mustAbsResourceInstanceAddr("test_instance.bar[\"one\"]"),
79-
ID: "foo",
84+
ID: foo_str_expr,
8085
DeclRange: blockRange,
8186
},
8287
``,
@@ -100,7 +105,7 @@ func TestImportBlock_decode(t *testing.T) {
100105
},
101106
&Import{
102107
To: mustAbsResourceInstanceAddr("module.bar.test_instance.bar"),
103-
ID: "foo",
108+
ID: foo_str_expr,
104109
DeclRange: blockRange,
105110
},
106111
``,
@@ -138,7 +143,7 @@ func TestImportBlock_decode(t *testing.T) {
138143
DefRange: blockRange,
139144
},
140145
&Import{
141-
ID: "foo",
146+
ID: foo_str_expr,
142147
DeclRange: blockRange,
143148
},
144149
"Missing required argument",
@@ -160,7 +165,7 @@ func TestImportBlock_decode(t *testing.T) {
160165
t.Fatal("expected error")
161166
}
162167

163-
if !cmp.Equal(got, test.want, cmp.AllowUnexported(addrs.MoveEndpoint{})) {
168+
if !cmp.Equal(got, test.want, typeComparer, valueComparer) {
164169
t.Fatalf("wrong result: %s", cmp.Diff(got, test.want))
165170
}
166171
})

internal/terraform/context_import.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package terraform
66
import (
77
"log"
88

9+
"github.com/hashicorp/hcl/v2"
910
"github.com/hashicorp/terraform/internal/addrs"
1011
"github.com/hashicorp/terraform/internal/configs"
1112
"github.com/hashicorp/terraform/internal/states"
@@ -22,7 +23,8 @@ type ImportOpts struct {
2223
SetVariables InputValues
2324
}
2425

25-
// ImportTarget is a single resource to import.
26+
// ImportTarget is a single resource to import,
27+
// in legacy (CLI) import mode.
2628
type ImportTarget struct {
2729
// Config is the original import block for this import. This might be null
2830
// if the import did not originate in config.
@@ -33,7 +35,7 @@ type ImportTarget struct {
3335
Addr addrs.AbsResourceInstance
3436

3537
// ID is the ID of the resource to import. This is resource-specific.
36-
ID string
38+
ID hcl.Expression
3739
}
3840

3941
// Import takes already-created external resources and brings them

0 commit comments

Comments
 (0)