Skip to content

Commit

Permalink
deferred actinos: add support for unknown ids in import blocks (#35300)
Browse files Browse the repository at this point in the history
  • Loading branch information
liamcervante committed Jun 12, 2024
1 parent 9ab50f7 commit 96da5e9
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 124 deletions.
26 changes: 18 additions & 8 deletions internal/plans/changes.go
Original file line number Diff line number Diff line change
Expand Up @@ -510,8 +510,23 @@ func (oc *OutputChange) Encode() (*OutputChangeSrc, error) {
// The fields in here are subject to change, so downstream consumers should be
// prepared for backwards compatibility in case the contents changes.
type Importing struct {
// ID is the original ID of the imported resource.
ID string
ID cty.Value
}

// Encode converts the Importing object into a form suitable for serialization
// to a plan file.
func (i *Importing) Encode() *ImportingSrc {
if i == nil {
return nil
}
if i.ID.IsKnown() {
return &ImportingSrc{
ID: i.ID.AsString(),
}
}
return &ImportingSrc{
Unknown: true,
}
}

// Change describes a single change with a given action.
Expand Down Expand Up @@ -593,18 +608,13 @@ func (c *Change) Encode(ty cty.Type) (*ChangeSrc, error) {
return nil, err
}

var importing *ImportingSrc
if c.Importing != nil {
importing = &ImportingSrc{ID: c.Importing.ID}
}

return &ChangeSrc{
Action: c.Action,
Before: beforeDV,
After: afterDV,
BeforeSensitivePaths: sensitiveAttrsBefore,
AfterSensitivePaths: sensitiveAttrsAfter,
Importing: importing,
Importing: c.Importing.Encode(),
GeneratedConfig: c.GeneratedConfig,
}, nil
}
27 changes: 21 additions & 6 deletions internal/plans/changes_src.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,26 @@ func (ocs *OutputChangeSrc) DeepCopy() *OutputChangeSrc {
type ImportingSrc struct {
// ID is the original ID of the imported resource.
ID string

// Unknown is true if the ID was unknown when we tried to import it. This
// should only be true if the overall change is embedded within a deferred
// action.
Unknown bool
}

// Decode unmarshals the raw representation of the importing action.
func (is *ImportingSrc) Decode() *Importing {
if is == nil {
return nil
}
if is.Unknown {
return &Importing{
ID: cty.UnknownVal(cty.String),
}
}
return &Importing{
ID: cty.StringVal(is.ID),
}
}

// ChangeSrc is a not-yet-decoded Change.
Expand Down Expand Up @@ -266,16 +286,11 @@ func (cs *ChangeSrc) Decode(ty cty.Type) (*Change, error) {
}
}

var importing *Importing
if cs.Importing != nil {
importing = &Importing{ID: cs.Importing.ID}
}

return &Change{
Action: cs.Action,
Before: marks.MarkPaths(before, marks.Sensitive, cs.BeforeSensitivePaths),
After: marks.MarkPaths(after, marks.Sensitive, cs.AfterSensitivePaths),
Importing: importing,
Importing: cs.Importing.Decode(),
GeneratedConfig: cs.GeneratedConfig,
}, nil
}
6 changes: 4 additions & 2 deletions internal/plans/planfile/tfplan.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,8 @@ func changeFromTfplan(rawChange *planproto.Change) (*plans.ChangeSrc, error) {

if rawChange.Importing != nil {
ret.Importing = &plans.ImportingSrc{
ID: rawChange.Importing.Id,
ID: rawChange.Importing.Id,
Unknown: rawChange.Importing.Unknown,
}
}
ret.GeneratedConfig = rawChange.GeneratedConfig
Expand Down Expand Up @@ -812,7 +813,8 @@ func changeToTfplan(change *plans.ChangeSrc) (*planproto.Change, error) {

if change.Importing != nil {
ret.Importing = &planproto.Importing{
Id: change.Importing.ID,
Id: change.Importing.ID,
Unknown: change.Importing.Unknown,
}

}
Expand Down
132 changes: 71 additions & 61 deletions internal/plans/planproto/planfile.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions internal/plans/planproto/planfile.proto
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,9 @@ message Path {
message Importing {
// The original ID of the resource.
string id = 1;

// unknown is true if the original ID of the resource is unknown.
bool unknown = 2;
}

// DeferredReason describes the reason why a resource instance change was
Expand Down
40 changes: 40 additions & 0 deletions internal/terraform/context_apply_deferred_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2581,6 +2581,45 @@ resource "test" "a" {
},
},
}

unknownImportId = deferredActionsTest{
configs: map[string]string{
"main.tf": `
variable "id" {
type = string
}
resource "test" "a" {
name = "a"
}
import {
id = var.id
to = test.a
}
`,
},
stages: []deferredActionsTestStage{
{
inputs: map[string]cty.Value{
"id": cty.UnknownVal(cty.String),
},
wantPlanned: map[string]cty.Value{
"a": cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("a"),
"upstream_names": cty.NullVal(cty.Set(cty.String)),
"output": cty.UnknownVal(cty.String),
}),
},
wantActions: make(map[string]plans.Action),
wantDeferred: map[string]ExpectedDeferred{
"test.a": {Reason: providers.DeferredReasonResourceConfigUnknown, Action: plans.Create},
},
wantApplied: make(map[string]cty.Value),
wantOutputs: make(map[string]cty.Value),
},
},
}
)

func TestContextApply_deferredActions(t *testing.T) {
Expand Down Expand Up @@ -2615,6 +2654,7 @@ func TestContextApply_deferredActions(t *testing.T) {
"plan_destroy_resource_change_but_forbidden": planDestroyResourceChangeButForbidden,
"module_deferred_for_each_value": moduleDeferredForEachValue,
"module_inner_resource_instance_deferred": moduleInnerResourceInstanceDeferred,
"unknown_import_id": unknownImportId,
}

for name, test := range tests {
Expand Down
Loading

0 comments on commit 96da5e9

Please sign in to comment.