finish context refresh tests

This commit is contained in:
James Bardin 2018-09-07 17:45:51 -04:00 committed by Martin Atkins
parent a8d62478c6
commit 426a976c93
8 changed files with 295 additions and 246 deletions

View File

@ -712,6 +712,10 @@ func TestContext2Refresh_output(t *testing.T) {
ResourceTypes: map[string]*configschema.Block{ ResourceTypes: map[string]*configschema.Block{
"aws_instance": { "aws_instance": {
Attributes: map[string]*configschema.Attribute{ Attributes: map[string]*configschema.Attribute{
"id": {
Type: cty.String,
Computed: true,
},
"foo": { "foo": {
Type: cty.String, Type: cty.String,
Computed: true, Computed: true,
@ -739,6 +743,7 @@ func TestContext2Refresh_output(t *testing.T) {
Primary: &InstanceState{ Primary: &InstanceState{
ID: "foo", ID: "foo",
Attributes: map[string]string{ Attributes: map[string]string{
"id": "foo",
"foo": "bar", "foo": "bar",
}, },
}, },
@ -757,12 +762,6 @@ func TestContext2Refresh_output(t *testing.T) {
}), }),
}) })
p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
return providers.ReadResourceResponse{
NewState: req.PriorState,
}
}
s, diags := ctx.Refresh() s, diags := ctx.Refresh()
if diags.HasErrors() { if diags.HasErrors() {
t.Fatalf("refresh errors: %s", diags.Err()) t.Fatalf("refresh errors: %s", diags.Err())
@ -771,7 +770,7 @@ func TestContext2Refresh_output(t *testing.T) {
actual := strings.TrimSpace(s.String()) actual := strings.TrimSpace(s.String())
expected := strings.TrimSpace(testContextRefreshOutputStr) expected := strings.TrimSpace(testContextRefreshOutputStr)
if actual != expected { if actual != expected {
t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected) t.Fatalf("wrong result\n\ngot:\n%q\n\nwant:\n%q", actual, expected)
} }
} }
@ -804,7 +803,9 @@ func TestContext2Refresh_outputPartial(t *testing.T) {
}) })
p.ReadResourceFn = nil p.ReadResourceFn = nil
p.ReadResourceResponse = providers.ReadResourceResponse{} p.ReadResourceResponse = providers.ReadResourceResponse{
NewState: cty.NullVal(p.GetSchemaReturn.ResourceTypes["aws_instance"].ImpliedType()),
}
// Refresh creates a partial plan for any instances that don't have // Refresh creates a partial plan for any instances that don't have
// remote objects yet, to get stub values for interpolation. Therefore // remote objects yet, to get stub values for interpolation. Therefore
@ -838,59 +839,66 @@ func TestContext2Refresh_outputPartial(t *testing.T) {
} }
func TestContext2Refresh_stateBasic(t *testing.T) { func TestContext2Refresh_stateBasic(t *testing.T) {
t.Fatalf("not yet updated for new provider interface") p := testProvider("aws")
/* m := testModule(t, "refresh-basic")
p := testProvider("aws") state := mustShimLegacyState(&State{
m := testModule(t, "refresh-basic") Modules: []*ModuleState{
state := mustShimLegacyState(&State{ &ModuleState{
Modules: []*ModuleState{ Path: rootModulePath,
&ModuleState{ Resources: map[string]*ResourceState{
Path: rootModulePath, "aws_instance.web": &ResourceState{
Resources: map[string]*ResourceState{ Type: "aws_instance",
"aws_instance.web": &ResourceState{ Primary: &InstanceState{
Type: "aws_instance", ID: "bar",
Primary: &InstanceState{
ID: "bar",
},
}, },
}, },
}, },
}, },
}) },
ctx := testContext2(t, &ContextOpts{ })
Config: m, ctx := testContext2(t, &ContextOpts{
ProviderResolver: providers.ResolverFixed( Config: m,
map[string]providers.Factory{ ProviderResolver: providers.ResolverFixed(
"aws": testProviderFuncFixed(p), map[string]providers.Factory{
}, "aws": testProviderFuncFixed(p),
), },
State: state, ),
}) State: state,
})
p.RefreshFn = nil schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
p.RefreshReturn = &InstanceState{ ty := schema.ImpliedType()
ID: "foo",
}
s, diags := ctx.Refresh() readStateVal, err := schema.CoerceValue(cty.ObjectVal(map[string]cty.Value{
if diags.HasErrors() { "id": cty.StringVal("foo"),
t.Fatalf("refresh errors: %s", diags.Err()) }))
} if err != nil {
originalMod := state.RootModule() t.Fatal(err)
mod := s.RootModule() }
if !p.RefreshCalled {
t.Fatal("refresh should be called") p.ReadResourceFn = nil
} p.ReadResourceResponse = providers.ReadResourceResponse{
if !reflect.DeepEqual(p.RefreshState, originalMod.Resources["aws_instance.web"].Primary) { NewState: readStateVal,
t.Fatalf( }
"bad:\n\n%#v\n\n%#v",
p.RefreshState, s, diags := ctx.Refresh()
originalMod.Resources["aws_instance.web"].Primary) if diags.HasErrors() {
} t.Fatalf("refresh errors: %s", diags.Err())
if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) { }
t.Fatalf("bad: %#v", mod.Resources)
} if !p.ReadResourceCalled {
*/ t.Fatal("read resource should be called")
}
mod := s.RootModule()
newState, err := mod.Resources["aws_instance.web"].Instances[addrs.NoKey].Current.Decode(ty)
if err != nil {
t.Fatal(err)
}
if !cmp.Equal(readStateVal, newState.Value, valueComparer, equateEmpty) {
t.Fatal(cmp.Diff(readStateVal, newState.Value, valueComparer, equateEmpty))
}
} }
func TestContext2Refresh_dataOrphan(t *testing.T) { func TestContext2Refresh_dataOrphan(t *testing.T) {
@ -929,94 +937,106 @@ func TestContext2Refresh_dataOrphan(t *testing.T) {
} }
func TestContext2Refresh_dataState(t *testing.T) { func TestContext2Refresh_dataState(t *testing.T) {
t.Fatalf("not yet updated for new provider interface") m := testModule(t, "refresh-data-resource-basic")
/*
m := testModule(t, "refresh-data-resource-basic")
state := mustShimLegacyState(&State{ state := mustShimLegacyState(&State{
Modules: []*ModuleState{ Modules: []*ModuleState{
&ModuleState{ &ModuleState{
Path: rootModulePath, Path: rootModulePath,
// Intentionally no resources since data resources are // Intentionally no resources since data resources are
// supposed to refresh themselves even if they didn't // supposed to refresh themselves even if they didn't
// already exist. // already exist.
Resources: map[string]*ResourceState{}, Resources: map[string]*ResourceState{},
},
}, },
}) },
})
p := testProvider("null") schema := &configschema.Block{
p.GetSchemaReturn = &ProviderSchema{ Attributes: map[string]*configschema.Attribute{
Provider: &configschema.Block{}, "inputs": {
DataSources: map[string]*configschema.Block{ Type: cty.Map(cty.String),
"null_data_source": { Optional: true,
Attributes: map[string]*configschema.Attribute{
"inputs": {
Type: cty.Map(cty.String),
Optional: true,
},
},
},
}, },
} },
}
ctx := testContext2(t, &ContextOpts{ p := testProvider("null")
Config: m, p.GetSchemaReturn = &ProviderSchema{
ProviderResolver: providers.ResolverFixed( Provider: &configschema.Block{},
map[string]providers.Factory{ DataSources: map[string]*configschema.Block{
"null": testProviderFuncFixed(p), "null_data_source": schema,
}, },
), }
State: state,
})
p.ReadDataDiffFn = nil ctx := testContext2(t, &ContextOpts{
p.ReadDataDiffReturn = &InstanceDiff{ Config: m,
Attributes: map[string]*ResourceAttrDiff{ ProviderResolver: providers.ResolverFixed(
"inputs.#": { map[string]providers.Factory{
Old: "0", "null": testProviderFuncFixed(p),
New: "1",
Type: DiffAttrInput,
},
"inputs.test": {
Old: "",
New: "yes",
Type: DiffAttrInput,
},
"outputs.#": {
Old: "",
New: "",
NewComputed: true,
Type: DiffAttrOutput,
},
}, },
),
State: state,
})
var readStateVal cty.Value
p.ReadDataSourceFn = func(req providers.ReadDataSourceRequest) providers.ReadDataSourceResponse {
m := req.Config.AsValueMap()
m["inputs"] = cty.MapVal(map[string]cty.Value{"test": cty.StringVal("yes")})
readStateVal = cty.ObjectVal(m)
return providers.ReadDataSourceResponse{
State: readStateVal,
} }
p.ReadDataApplyFn = nil // FIXME: should the "outputs" value here be added to the reutnred state?
p.ReadDataApplyReturn = &InstanceState{ // Attributes: map[string]*ResourceAttrDiff{
ID: "-", // "inputs.#": {
} // Old: "0",
// New: "1",
// Type: DiffAttrInput,
// },
// "inputs.test": {
// Old: "",
// New: "yes",
// Type: DiffAttrInput,
// },
// "outputs.#": {
// Old: "",
// New: "",
// NewComputed: true,
// Type: DiffAttrOutput,
// },
// },
}
s, diags := ctx.Refresh() s, diags := ctx.Refresh()
if diags.HasErrors() { if diags.HasErrors() {
t.Fatalf("refresh errors: %s", diags.Err()) t.Fatalf("refresh errors: %s", diags.Err())
} }
if !p.ReadDataDiffCalled { if !p.ReadDataSourceCalled {
t.Fatal("ReadDataDiff should have been called") t.Fatal("ReadDataSource should have been called")
} }
if !p.ReadDataApplyCalled {
t.Fatal("ReadDataApply should have been called")
}
mod := s.RootModule() // mod := s.RootModule()
if got := mod.Resources["data.null_data_source.testing"].Primary.ID; got != "-" { // if got := mod.Resources["data.null_data_source.testing"].Primary.ID; got != "-" {
t.Fatalf("resource id is %q; want %s", got, "-") // t.Fatalf("resource id is %q; want %s", got, "-")
} // }
if !reflect.DeepEqual(mod.Resources["data.null_data_source.testing"].Primary, p.ReadDataApplyReturn) { // if !reflect.DeepEqual(mod.Resources["data.null_data_source.testing"].Primary, p.ReadDataApplyReturn) {
t.Fatalf("bad: %#v", mod.Resources) // t.Fatalf("bad: %#v", mod.Resources)
} // }
*/
mod := s.RootModule()
newState, err := mod.Resources["data.null_data_source.testing"].Instances[addrs.NoKey].Current.Decode(schema.ImpliedType())
if err != nil {
t.Fatal(err)
}
if !cmp.Equal(readStateVal, newState.Value, valueComparer, equateEmpty) {
t.Fatal(cmp.Diff(readStateVal, newState.Value, valueComparer, equateEmpty))
}
} }
func TestContext2Refresh_dataStateRefData(t *testing.T) { func TestContext2Refresh_dataStateRefData(t *testing.T) {
@ -1026,6 +1046,10 @@ func TestContext2Refresh_dataStateRefData(t *testing.T) {
DataSources: map[string]*configschema.Block{ DataSources: map[string]*configschema.Block{
"null_data_source": { "null_data_source": {
Attributes: map[string]*configschema.Attribute{ Attributes: map[string]*configschema.Attribute{
"id": {
Type: cty.String,
Computed: true,
},
"foo": { "foo": {
Type: cty.String, Type: cty.String,
Optional: true, Optional: true,
@ -1062,8 +1086,12 @@ func TestContext2Refresh_dataStateRefData(t *testing.T) {
}) })
p.ReadDataSourceFn = func(req providers.ReadDataSourceRequest) providers.ReadDataSourceResponse { p.ReadDataSourceFn = func(req providers.ReadDataSourceRequest) providers.ReadDataSourceResponse {
// add the required id
m := req.Config.AsValueMap()
m["id"] = cty.StringVal("foo")
return providers.ReadDataSourceResponse{ return providers.ReadDataSourceResponse{
State: req.Config, State: cty.ObjectVal(m),
} }
} }
@ -1107,12 +1135,14 @@ func TestContext2Refresh_tainted(t *testing.T) {
), ),
State: state, State: state,
}) })
p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
// add the required id
m := req.PriorState.AsValueMap()
m["id"] = cty.StringVal("foo")
p.ReadResourceFn = nil return providers.ReadResourceResponse{
p.ReadResourceResponse = providers.ReadResourceResponse{ NewState: cty.ObjectVal(m),
NewState: cty.ObjectVal(map[string]cty.Value{ }
"id": cty.StringVal("foo"),
}),
} }
s, diags := ctx.Refresh() s, diags := ctx.Refresh()
@ -1172,79 +1202,95 @@ func TestContext2Refresh_unknownProvider(t *testing.T) {
} }
func TestContext2Refresh_vars(t *testing.T) { func TestContext2Refresh_vars(t *testing.T) {
t.Fatalf("not yet updated for new provider interface") p := testProvider("aws")
/*
p := testProvider("aws") schema := &configschema.Block{
p.GetSchemaReturn = &ProviderSchema{ Attributes: map[string]*configschema.Attribute{
Provider: &configschema.Block{}, "ami": {
ResourceTypes: map[string]*configschema.Block{ Type: cty.String,
"aws_instance": { Optional: true,
Attributes: map[string]*configschema.Attribute{
"ami": {
Type: cty.String,
Optional: true,
},
"id": {
Type: cty.String,
Computed: true,
},
},
},
}, },
} "id": {
Type: cty.String,
Computed: true,
},
},
}
m := testModule(t, "refresh-vars") p.GetSchemaReturn = &ProviderSchema{
ctx := testContext2(t, &ContextOpts{ Provider: &configschema.Block{},
Config: m, ResourceTypes: map[string]*configschema.Block{"aws_instance": schema},
ProviderResolver: providers.ResolverFixed( }
map[string]providers.Factory{
"aws": testProviderFuncFixed(p),
},
),
State: mustShimLegacyState(&State{
Modules: []*ModuleState{ m := testModule(t, "refresh-vars")
&ModuleState{ ctx := testContext2(t, &ContextOpts{
Path: rootModulePath, Config: m,
Resources: map[string]*ResourceState{ ProviderResolver: providers.ResolverFixed(
"aws_instance.web": &ResourceState{ map[string]providers.Factory{
Type: "aws_instance", "aws": testProviderFuncFixed(p),
Primary: &InstanceState{ },
ID: "foo", ),
}, State: mustShimLegacyState(&State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.web": &ResourceState{
Type: "aws_instance",
Primary: &InstanceState{
ID: "foo",
}, },
}, },
}, },
}, },
}), },
}) }),
})
p.RefreshFn = nil readStateVal, err := schema.CoerceValue(cty.ObjectVal(map[string]cty.Value{
p.RefreshReturn = &InstanceState{ "id": cty.StringVal("foo"),
ID: "foo", }))
} if err != nil {
t.Fatal(err)
}
s, diags := ctx.Refresh() p.ReadResourceFn = nil
if diags.HasErrors() { p.ReadResourceResponse = providers.ReadResourceResponse{
t.Fatalf("refresh errors: %s", diags.Err()) NewState: readStateVal,
} }
mod := s.RootModule()
if !p.RefreshCalled {
t.Fatal("refresh should be called")
}
if p.RefreshState.ID != "foo" {
t.Fatalf("bad: %#v", p.RefreshState)
}
if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) {
t.Fatalf("bad: %#v", mod.Resources["aws_instance.web"])
}
for _, r := range mod.Resources { p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
if r.Addr.Type == "" { return providers.PlanResourceChangeResponse{
t.Fatalf("no type: %#v", r) PlannedState: req.ProposedNewState,
}
} }
*/ }
s, diags := ctx.Refresh()
if diags.HasErrors() {
t.Fatalf("refresh errors: %s", diags.Err())
}
if !p.ReadResourceCalled {
t.Fatal("read resource should be called")
}
mod := s.RootModule()
newState, err := mod.Resources["aws_instance.web"].Instances[addrs.NoKey].Current.Decode(schema.ImpliedType())
if err != nil {
t.Fatal(err)
}
if !cmp.Equal(readStateVal, newState.Value, valueComparer, equateEmpty) {
t.Fatal(cmp.Diff(readStateVal, newState.Value, valueComparer, equateEmpty))
}
for _, r := range mod.Resources {
if r.Addr.Type == "" {
t.Fatalf("no type: %#v", r)
}
}
} }
func TestContext2Refresh_orphanModule(t *testing.T) { func TestContext2Refresh_orphanModule(t *testing.T) {
@ -1263,12 +1309,6 @@ func TestContext2Refresh_orphanModule(t *testing.T) {
NewState: req.PriorState, NewState: req.PriorState,
} }
} }
p.GetSchemaReturn = &ProviderSchema{
Provider: &configschema.Block{},
ResourceTypes: map[string]*configschema.Block{
"aws_instance": {},
},
}
state := mustShimLegacyState(&State{ state := mustShimLegacyState(&State{
Modules: []*ModuleState{ Modules: []*ModuleState{
@ -1280,6 +1320,7 @@ func TestContext2Refresh_orphanModule(t *testing.T) {
Primary: &InstanceState{ Primary: &InstanceState{
ID: "i-abc123", ID: "i-abc123",
Attributes: map[string]string{ Attributes: map[string]string{
"id": "i-abc123",
"childid": "i-bcd234", "childid": "i-bcd234",
"grandchildid": "i-cde345", "grandchildid": "i-cde345",
}, },
@ -1300,6 +1341,7 @@ func TestContext2Refresh_orphanModule(t *testing.T) {
Primary: &InstanceState{ Primary: &InstanceState{
ID: "i-bcd234", ID: "i-bcd234",
Attributes: map[string]string{ Attributes: map[string]string{
"id": "i-bcd234",
"grandchildid": "i-cde345", "grandchildid": "i-cde345",
}, },
}, },
@ -1327,6 +1369,9 @@ func TestContext2Refresh_orphanModule(t *testing.T) {
Type: "aws_instance", Type: "aws_instance",
Primary: &InstanceState{ Primary: &InstanceState{
ID: "i-cde345", ID: "i-cde345",
Attributes: map[string]string{
"id": "i-cde345",
},
}, },
Provider: "provider.aws", Provider: "provider.aws",
}, },
@ -1409,13 +1454,6 @@ func TestContext2Refresh_noDiffHookOnScaleOut(t *testing.T) {
h := new(MockHook) h := new(MockHook)
p := testProvider("aws") p := testProvider("aws")
m := testModule(t, "refresh-resource-scale-inout") m := testModule(t, "refresh-resource-scale-inout")
p.ReadResourceFn = nil
p.GetSchemaReturn = &ProviderSchema{
Provider: &configschema.Block{},
ResourceTypes: map[string]*configschema.Block{
"aws_instance": {},
},
}
// Refresh creates a partial plan for any instances that don't have // Refresh creates a partial plan for any instances that don't have
// remote objects yet, to get stub values for interpolation. Therefore // remote objects yet, to get stub values for interpolation. Therefore
@ -1432,6 +1470,9 @@ func TestContext2Refresh_noDiffHookOnScaleOut(t *testing.T) {
Deposed: []*InstanceState{ Deposed: []*InstanceState{
&InstanceState{ &InstanceState{
ID: "foo", ID: "foo",
Attributes: map[string]string{
"id": "foo",
},
}, },
}, },
}, },
@ -1440,6 +1481,9 @@ func TestContext2Refresh_noDiffHookOnScaleOut(t *testing.T) {
Deposed: []*InstanceState{ Deposed: []*InstanceState{
&InstanceState{ &InstanceState{
ID: "bar", ID: "bar",
Attributes: map[string]string{
"id": "foo",
},
}, },
}, },
}, },
@ -1476,12 +1520,6 @@ func TestContext2Refresh_updateProviderInState(t *testing.T) {
p := testProvider("aws") p := testProvider("aws")
p.DiffFn = testDiffFn p.DiffFn = testDiffFn
p.ApplyFn = testApplyFn p.ApplyFn = testApplyFn
p.GetSchemaReturn = &ProviderSchema{
Provider: &configschema.Block{},
ResourceTypes: map[string]*configschema.Block{
"aws_instance": {},
},
}
s := mustShimLegacyState(&State{ s := mustShimLegacyState(&State{
Modules: []*ModuleState{ Modules: []*ModuleState{
@ -1492,6 +1530,9 @@ func TestContext2Refresh_updateProviderInState(t *testing.T) {
Type: "aws_instance", Type: "aws_instance",
Primary: &InstanceState{ Primary: &InstanceState{
ID: "foo", ID: "foo",
Attributes: map[string]string{
"id": "foo",
},
}, },
Provider: "provider.aws.baz", Provider: "provider.aws.baz",
}, },

View File

@ -63,6 +63,10 @@ func (n *EvalWriteOutput) Eval(ctx EvalContext) (interface{}, error) {
return nil, diags.Err() return nil, diags.Err()
} }
state.SetOutputValue(addr, val, n.Sensitive) if val.IsKnown() && !val.IsNull() {
state.SetOutputValue(addr, val, n.Sensitive)
} else {
state.RemoveOutputValue(addr)
}
return nil, nil return nil, nil
} }

View File

@ -136,13 +136,14 @@ func (n *EvalReadDataDiff) Eval(ctx EvalContext) (interface{}, error) {
// EvalReadDataApply is an EvalNode implementation that executes a data // EvalReadDataApply is an EvalNode implementation that executes a data
// resource's ReadDataApply method to read data from the data source. // resource's ReadDataApply method to read data from the data source.
type EvalReadDataApply struct { type EvalReadDataApply struct {
Addr addrs.ResourceInstance Addr addrs.ResourceInstance
Provider *providers.Interface Provider *providers.Interface
ProviderAddr addrs.AbsProviderConfig ProviderAddr addrs.AbsProviderConfig
ProviderSchema **ProviderSchema ProviderSchema **ProviderSchema
Output **states.ResourceInstanceObject Output **states.ResourceInstanceObject
Config *configs.Resource Config *configs.Resource
Change **plans.ResourceInstanceChange Change **plans.ResourceInstanceChange
StateReferences []addrs.Referenceable
} }
func (n *EvalReadDataApply) Eval(ctx EvalContext) (interface{}, error) { func (n *EvalReadDataApply) Eval(ctx EvalContext) (interface{}, error) {
@ -214,8 +215,9 @@ func (n *EvalReadDataApply) Eval(ctx EvalContext) (interface{}, error) {
if n.Output != nil { if n.Output != nil {
*n.Output = &states.ResourceInstanceObject{ *n.Output = &states.ResourceInstanceObject{
Value: newVal, Value: newVal,
Status: states.ObjectReady, Status: states.ObjectReady,
Dependencies: n.StateReferences,
} }
} }

View File

@ -76,7 +76,7 @@ func (n *EvalRefresh) Eval(ctx EvalContext) (interface{}, error) {
tfdiags.Error, tfdiags.Error,
"Provider produced invalid object", "Provider produced invalid object",
fmt.Sprintf( fmt.Sprintf(
"Provider %q planned an invalid value for %s%s during refresh.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.", "Provider %q planned an invalid value for %s: %s during refresh.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
n.ProviderAddr.ProviderConfig.Type, absAddr, tfdiags.FormatError(err), n.ProviderAddr.ProviderConfig.Type, absAddr, tfdiags.FormatError(err),
), ),
)) ))

View File

@ -55,10 +55,12 @@ func (n *EvalReadState) Eval(ctx EvalContext) (interface{}, error) {
*/ */
schema := (*n.ProviderSchema).SchemaForResourceAddr(n.Addr.ContainingResource()) schema := (*n.ProviderSchema).SchemaForResourceAddr(n.Addr.ContainingResource())
obj, err := src.Decode(schema.ImpliedType()) obj, err := src.Decode(schema.ImpliedType())
if err != nil { if err != nil {
return nil, err return nil, err
} }
if n.Output != nil { if n.Output != nil {
*n.Output = obj *n.Output = obj
} }
@ -193,7 +195,7 @@ func (n *EvalWriteState) Eval(ctx EvalContext) (interface{}, error) {
state := ctx.State() state := ctx.State()
obj := *n.State obj := *n.State
if obj == nil { if obj == nil || obj.Value.IsNull() {
// No need to encode anything: we'll just write it directly. // No need to encode anything: we'll just write it directly.
state.SetResourceInstanceCurrent(absAddr, nil, n.ProviderAddr) state.SetResourceInstanceCurrent(absAddr, nil, n.ProviderAddr)
log.Printf("[TRACE] EvalWriteState: removing state object for %s", absAddr) log.Printf("[TRACE] EvalWriteState: removing state object for %s", absAddr)

View File

@ -177,13 +177,14 @@ func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode {
}, },
&EvalReadDataApply{ &EvalReadDataApply{
Addr: addr.Resource, Addr: addr.Resource,
Config: n.Config, Config: n.Config,
Change: &change, Change: &change,
Provider: &provider, Provider: &provider,
ProviderAddr: n.ResolvedProvider, ProviderAddr: n.ResolvedProvider,
ProviderSchema: &providerSchema, ProviderSchema: &providerSchema,
Output: &state, Output: &state,
StateReferences: n.StateReferences(),
}, },
&EvalWriteState{ &EvalWriteState{

View File

@ -158,13 +158,14 @@ func (n *NodeApplyableResourceInstance) evalTreeDataResource(addr addrs.AbsResou
}, },
&EvalReadDataApply{ &EvalReadDataApply{
Addr: addr.Resource, Addr: addr.Resource,
Config: n.Config, Config: n.Config,
Change: &change, Change: &change,
Provider: &provider, Provider: &provider,
ProviderAddr: n.ResolvedProvider, ProviderAddr: n.ResolvedProvider,
ProviderSchema: &providerSchema, ProviderSchema: &providerSchema,
Output: &state, Output: &state,
StateReferences: n.StateReferences(),
}, },
&EvalWriteState{ &EvalWriteState{

View File

@ -1800,7 +1800,6 @@ data.null_data_source.bar:
ID = foo ID = foo
provider = provider.null provider = provider.null
bar = yes bar = yes
type = null_data_source
Dependencies: Dependencies:
data.null_data_source.foo data.null_data_source.foo
@ -1808,5 +1807,4 @@ data.null_data_source.foo:
ID = foo ID = foo
provider = provider.null provider = provider.null
foo = yes foo = yes
type = null_data_source
` `