terraform: resource provider must never return pointers to same data
This is a requirement for the parallelism of Terraform to work sanely. We could deep copy every result but I think this would be unrealistic and impose a performance cost when it isn't necessary in most cases.
This commit is contained in:
parent
baa59ff75d
commit
e2c415a87e
|
@ -1088,6 +1088,10 @@ func TestContext2Plan_dataResourceBecomesComputed(t *testing.T) {
|
||||||
t.Fatalf("missing diff for data.aws_data_resource.foo")
|
t.Fatalf("missing diff for data.aws_data_resource.foo")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is added by the diff but we want to verify that we got
|
||||||
|
// the same diff as above minus the dynamic stuff.
|
||||||
|
delete(iDiff.Attributes, "id")
|
||||||
|
|
||||||
if same, _ := p.ReadDataDiffReturn.Same(iDiff); !same {
|
if same, _ := p.ReadDataDiffReturn.Same(iDiff); !same {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
"incorrect diff for data.data_resource.foo\ngot: %#v\nwant: %#v",
|
"incorrect diff for data.data_resource.foo\ngot: %#v\nwant: %#v",
|
||||||
|
|
|
@ -3,6 +3,12 @@ package terraform
|
||||||
// ResourceProvider is an interface that must be implemented by any
|
// ResourceProvider is an interface that must be implemented by any
|
||||||
// resource provider: the thing that creates and manages the resources in
|
// resource provider: the thing that creates and manages the resources in
|
||||||
// a Terraform configuration.
|
// a Terraform configuration.
|
||||||
|
//
|
||||||
|
// Important implementation note: All returned pointers, such as
|
||||||
|
// *ResourceConfig, *InstanceState, *InstanceDiff, etc. must not point to
|
||||||
|
// shared data. Terraform is highly parallel and assumes that this data is safe
|
||||||
|
// to read/write in parallel so it must be unique references. Note that it is
|
||||||
|
// safe to return arguments as results, however.
|
||||||
type ResourceProvider interface {
|
type ResourceProvider interface {
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* Functions related to the provider
|
* Functions related to the provider
|
||||||
|
|
|
@ -157,7 +157,7 @@ func (p *MockResourceProvider) Apply(
|
||||||
return p.ApplyFn(info, state, diff)
|
return p.ApplyFn(info, state, diff)
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.ApplyReturn, p.ApplyReturnError
|
return p.ApplyReturn.DeepCopy(), p.ApplyReturnError
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *MockResourceProvider) Diff(
|
func (p *MockResourceProvider) Diff(
|
||||||
|
@ -175,7 +175,7 @@ func (p *MockResourceProvider) Diff(
|
||||||
return p.DiffFn(info, state, desired)
|
return p.DiffFn(info, state, desired)
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.DiffReturn, p.DiffReturnError
|
return p.DiffReturn.DeepCopy(), p.DiffReturnError
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *MockResourceProvider) Refresh(
|
func (p *MockResourceProvider) Refresh(
|
||||||
|
@ -192,7 +192,7 @@ func (p *MockResourceProvider) Refresh(
|
||||||
return p.RefreshFn(info, s)
|
return p.RefreshFn(info, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.RefreshReturn, p.RefreshReturnError
|
return p.RefreshReturn.DeepCopy(), p.RefreshReturnError
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *MockResourceProvider) Resources() []ResourceType {
|
func (p *MockResourceProvider) Resources() []ResourceType {
|
||||||
|
@ -214,7 +214,15 @@ func (p *MockResourceProvider) ImportState(info *InstanceInfo, id string) ([]*In
|
||||||
return p.ImportStateFn(info, id)
|
return p.ImportStateFn(info, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.ImportStateReturn, p.ImportStateReturnError
|
var result []*InstanceState
|
||||||
|
if p.ImportStateReturn != nil {
|
||||||
|
result = make([]*InstanceState, len(p.ImportStateReturn))
|
||||||
|
for i, v := range p.ImportStateReturn {
|
||||||
|
result[i] = v.DeepCopy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, p.ImportStateReturnError
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *MockResourceProvider) ValidateDataSource(t string, c *ResourceConfig) ([]string, []error) {
|
func (p *MockResourceProvider) ValidateDataSource(t string, c *ResourceConfig) ([]string, []error) {
|
||||||
|
@ -245,7 +253,7 @@ func (p *MockResourceProvider) ReadDataDiff(
|
||||||
return p.ReadDataDiffFn(info, desired)
|
return p.ReadDataDiffFn(info, desired)
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.ReadDataDiffReturn, p.ReadDataDiffReturnError
|
return p.ReadDataDiffReturn.DeepCopy(), p.ReadDataDiffReturnError
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *MockResourceProvider) ReadDataApply(
|
func (p *MockResourceProvider) ReadDataApply(
|
||||||
|
@ -262,7 +270,7 @@ func (p *MockResourceProvider) ReadDataApply(
|
||||||
return p.ReadDataApplyFn(info, d)
|
return p.ReadDataApplyFn(info, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.ReadDataApplyReturn, p.ReadDataApplyReturnError
|
return p.ReadDataApplyReturn.DeepCopy(), p.ReadDataApplyReturnError
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *MockResourceProvider) DataSources() []DataSource {
|
func (p *MockResourceProvider) DataSources() []DataSource {
|
||||||
|
|
Loading…
Reference in New Issue