Skip to content

Commit 0252e5a

Browse files
committed
WIP
1 parent 3280649 commit 0252e5a

File tree

12 files changed

+162
-48
lines changed

12 files changed

+162
-48
lines changed

internal/command/views/hook_ui.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -323,11 +323,19 @@ func (h *UiHook) PostImportState(id terraform.HookResourceIdentity, imported []p
323323
return terraform.HookActionContinue, nil
324324
}
325325

326-
func (h *UiHook) PrePlanImport(id terraform.HookResourceIdentity, importID string) (terraform.HookAction, error) {
327-
h.println(fmt.Sprintf(
328-
h.view.colorize.Color("[reset][bold]%s: Preparing import... [id=%s]"),
329-
id.Addr, importID,
330-
))
326+
func (h *UiHook) PrePlanImport(id terraform.HookResourceIdentity, importTarget cty.Value) (terraform.HookAction, error) {
327+
if importTarget.Type().IsObjectType() {
328+
h.println(fmt.Sprintf(
329+
h.view.colorize.Color("[reset][bold]%s: Preparing import... [identity=%s]"),
330+
id.Addr, importTarget.GoString(), // TODO improve
331+
))
332+
} else {
333+
h.println(fmt.Sprintf(
334+
h.view.colorize.Color("[reset][bold]%s: Preparing import... [id=%s]"),
335+
id.Addr, importTarget.AsString(),
336+
))
337+
338+
}
331339

332340
return terraform.HookActionContinue, nil
333341
}

internal/plans/changes.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ func (oc *OutputChange) Encode() (*OutputChangeSrc, error) {
551551
// The fields in here are subject to change, so downstream consumers should be
552552
// prepared for backwards compatibility in case the contents changes.
553553
type Importing struct {
554-
ID cty.Value
554+
Target cty.Value
555555
}
556556

557557
// Encode converts the Importing object into a form suitable for serialization
@@ -560,9 +560,15 @@ func (i *Importing) Encode() *ImportingSrc {
560560
if i == nil {
561561
return nil
562562
}
563-
if i.ID.IsKnown() {
564-
return &ImportingSrc{
565-
ID: i.ID.AsString(),
563+
if i.Target.IsKnown() {
564+
if i.Target.Type().IsObjectType() {
565+
return &ImportingSrc{
566+
Identity: i.Target,
567+
}
568+
} else {
569+
return &ImportingSrc{
570+
ID: i.Target.AsString(),
571+
}
566572
}
567573
}
568574
return &ImportingSrc{

internal/plans/changes_src.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ type ImportingSrc struct {
349349
// ID is the original ID of the imported resource.
350350
ID string
351351

352+
// Identity is the original identity of the imported resource.
353+
Identity cty.Value
354+
352355
// Unknown is true if the ID was unknown when we tried to import it. This
353356
// should only be true if the overall change is embedded within a deferred
354357
// action.
@@ -361,12 +364,25 @@ func (is *ImportingSrc) Decode() *Importing {
361364
return nil
362365
}
363366
if is.Unknown {
367+
if is.Identity.IsNull() {
368+
return &Importing{
369+
Target: cty.UnknownVal(cty.String),
370+
}
371+
}
372+
373+
return &Importing{
374+
Target: cty.UnknownVal(cty.EmptyObject),
375+
}
376+
}
377+
378+
if is.Identity.IsNull() {
364379
return &Importing{
365-
ID: cty.UnknownVal(cty.String),
380+
Target: cty.StringVal(is.ID),
366381
}
367382
}
383+
368384
return &Importing{
369-
ID: cty.StringVal(is.ID),
385+
Target: is.Identity,
370386
}
371387
}
372388

internal/terraform/eval_import.go

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,13 @@ import (
1616
"github.com/hashicorp/terraform/internal/tfdiags"
1717
)
1818

19+
// evaluateImportIdExpression evaluates the given expression to determine the
20+
// import Id for a resource. It should evaluate to a non-empty string.
21+
//
22+
// The given expression must be non-nil or the function will panic.
1923
func evaluateImportIdExpression(expr hcl.Expression, ctx EvalContext, keyData instances.RepetitionData, allowUnknown bool) (cty.Value, tfdiags.Diagnostics) {
2024
var diags tfdiags.Diagnostics
2125

22-
if expr == nil {
23-
return cty.NilVal, diags.Append(&hcl.Diagnostic{
24-
Severity: hcl.DiagError,
25-
Summary: "Invalid import id argument",
26-
Detail: "The import ID cannot be null.",
27-
Subject: expr.Range().Ptr(),
28-
})
29-
}
30-
3126
// import blocks only exist in the root module, and must be evaluated in
3227
// that context.
3328
ctx = evalContextForModuleInstance(ctx, addrs.RootModuleInstance)
@@ -80,6 +75,50 @@ func evaluateImportIdExpression(expr hcl.Expression, ctx EvalContext, keyData in
8075
return importIdVal, diags
8176
}
8277

78+
// evaluateImportIdentityExpression evaluates the given expression to determine the
79+
// import identity for a resource. It uses the resource identity schema to validate
80+
// the structure of the object..
81+
//
82+
// The given expression must be non-nil or the function will panic.
83+
func evaluateImportIdentityExpression(expr hcl.Expression, ctx EvalContext, keyData instances.RepetitionData, allowUnknown bool) (cty.Value, tfdiags.Diagnostics) {
84+
var diags tfdiags.Diagnostics
85+
86+
// import blocks only exist in the root module, and must be evaluated in
87+
// that context.
88+
ctx = evalContextForModuleInstance(ctx, addrs.RootModuleInstance)
89+
scope := ctx.EvaluationScope(nil, nil, keyData)
90+
importIdentityVal, evalDiags := scope.EvalExpr(expr, cty.EmptyObject) // TODO get resource identity schema
91+
diags = diags.Append(evalDiags)
92+
93+
if importIdentityVal.IsNull() {
94+
return cty.NilVal, diags.Append(&hcl.Diagnostic{
95+
Severity: hcl.DiagError,
96+
Summary: "Invalid import identity argument",
97+
Detail: "The import identity cannot be null.",
98+
Subject: expr.Range().Ptr(),
99+
})
100+
}
101+
if !allowUnknown && !importIdentityVal.IsKnown() {
102+
return cty.NilVal, diags.Append(&hcl.Diagnostic{
103+
Severity: hcl.DiagError,
104+
Summary: "Invalid import identity argument",
105+
Detail: `The import block "identity" argument depends on resource attributes that cannot be determined until apply, so Terraform cannot plan to import this resource.`, // FIXME and what should I do about that?
106+
Subject: expr.Range().Ptr(),
107+
// Expression:
108+
// EvalContext:
109+
Extra: diagnosticCausedByUnknown(true),
110+
})
111+
}
112+
113+
// Import data may have marks, which we can discard because the id is only
114+
// sent to the provider.
115+
importIdentityVal, _ = importIdentityVal.Unmark()
116+
117+
// TODO: Validate the object, ensure all required_for-import fields are present
118+
119+
return importIdentityVal, diags
120+
}
121+
83122
func evalImportToExpression(expr hcl.Expression, keyData instances.RepetitionData) (addrs.AbsResourceInstance, tfdiags.Diagnostics) {
84123
var res addrs.AbsResourceInstance
85124
var diags tfdiags.Diagnostics

internal/terraform/hook.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ type Hook interface {
9090

9191
// PrePlanImport and PostPlanImport are called during a plan before and after planning to import
9292
// a new resource using the configuration-driven import workflow.
93-
PrePlanImport(id HookResourceIdentity, importID string) (HookAction, error)
93+
PrePlanImport(id HookResourceIdentity, importTarget cty.Value) (HookAction, error)
9494
PostPlanImport(id HookResourceIdentity, imported []providers.ImportedResource) (HookAction, error)
9595

9696
// PreApplyImport and PostApplyImport are called during an apply for each imported resource when
@@ -185,7 +185,7 @@ func (*NilHook) PostImportState(id HookResourceIdentity, imported []providers.Im
185185
return HookActionContinue, nil
186186
}
187187

188-
func (h *NilHook) PrePlanImport(id HookResourceIdentity, importID string) (HookAction, error) {
188+
func (h *NilHook) PrePlanImport(id HookResourceIdentity, importTarget cty.Value) (HookAction, error) {
189189
return HookActionContinue, nil
190190
}
191191

internal/terraform/hook_mock.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ func (h *MockHook) PostImportState(id HookResourceIdentity, imported []providers
300300
return h.PostImportStateReturn, h.PostImportStateError
301301
}
302302

303-
func (h *MockHook) PrePlanImport(id HookResourceIdentity, importID string) (HookAction, error) {
303+
func (h *MockHook) PrePlanImport(id HookResourceIdentity, importTarget cty.Value) (HookAction, error) {
304304
h.PrePlanImportCalled = true
305305
h.PrePlanImportAddr = id.Addr
306306
return h.PrePlanImportReturn, h.PrePlanImportError

internal/terraform/hook_stop.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func (h *stopHook) PostImportState(id HookResourceIdentity, imported []providers
7474
return h.hook()
7575
}
7676

77-
func (h *stopHook) PrePlanImport(id HookResourceIdentity, importID string) (HookAction, error) {
77+
func (h *stopHook) PrePlanImport(id HookResourceIdentity, importTarget cty.Value) (HookAction, error) {
7878
return h.hook()
7979
}
8080

internal/terraform/hook_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ func (h *testHook) PostImportState(id HookResourceIdentity, imported []providers
127127
return HookActionContinue, nil
128128
}
129129

130-
func (h *testHook) PrePlanImport(id HookResourceIdentity, importID string) (HookAction, error) {
130+
func (h *testHook) PrePlanImport(id HookResourceIdentity, importTarget cty.Value) (HookAction, error) {
131131
h.mu.Lock()
132132
defer h.mu.Unlock()
133133
h.Calls = append(h.Calls, &testHookCall{"PrePlanImport", id.Addr.String()})

internal/terraform/node_resource_abstract.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ func (n *NodeAbstractResource) ImportReferences() []*addrs.Reference {
244244

245245
refs, _ := langrefs.ReferencesInExpr(addrs.ParseRef, importTarget.Config.ID)
246246
result = append(result, refs...)
247+
refs, _ = langrefs.ReferencesInExpr(addrs.ParseRef, importTarget.Config.Identity)
248+
result = append(result, refs...)
247249
refs, _ = langrefs.ReferencesInExpr(addrs.ParseRef, importTarget.Config.ForEach)
248250
result = append(result, refs...)
249251
}

internal/terraform/node_resource_plan.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,17 @@ func (n *nodeExpandPlannableResource) expandResourceImports(ctx EvalContext, all
187187

188188
diags = diags.Append(validateImportTargetExpansion(n.Config, to, imp.Config.To))
189189

190-
importID, evalDiags := evaluateImportIdExpression(imp.Config.ID, ctx, EvalDataForNoInstanceKey, allowUnknown)
190+
var importID cty.Value
191+
var evalDiags tfdiags.Diagnostics
192+
if imp.Config.ID != nil {
193+
importID, evalDiags = evaluateImportIdExpression(imp.Config.ID, ctx, EvalDataForNoInstanceKey, allowUnknown)
194+
} else if imp.Config.Identity != nil {
195+
importID, evalDiags = evaluateImportIdentityExpression(imp.Config.Identity, ctx, EvalDataForNoInstanceKey, allowUnknown)
196+
} else {
197+
// Should never happen
198+
return knownImports, unknownImports, diags
199+
}
200+
191201
diags = diags.Append(evalDiags)
192202
if diags.HasErrors() {
193203
return knownImports, unknownImports, diags

0 commit comments

Comments
 (0)