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")
|
||||
}
|
||||
|
||||
// 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 {
|
||||
t.Fatalf(
|
||||
"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
|
||||
// resource provider: the thing that creates and manages the resources in
|
||||
// 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 {
|
||||
/*********************************************************************
|
||||
* Functions related to the provider
|
||||
|
|
|
@ -157,7 +157,7 @@ func (p *MockResourceProvider) Apply(
|
|||
return p.ApplyFn(info, state, diff)
|
||||
}
|
||||
|
||||
return p.ApplyReturn, p.ApplyReturnError
|
||||
return p.ApplyReturn.DeepCopy(), p.ApplyReturnError
|
||||
}
|
||||
|
||||
func (p *MockResourceProvider) Diff(
|
||||
|
@ -175,7 +175,7 @@ func (p *MockResourceProvider) Diff(
|
|||
return p.DiffFn(info, state, desired)
|
||||
}
|
||||
|
||||
return p.DiffReturn, p.DiffReturnError
|
||||
return p.DiffReturn.DeepCopy(), p.DiffReturnError
|
||||
}
|
||||
|
||||
func (p *MockResourceProvider) Refresh(
|
||||
|
@ -192,7 +192,7 @@ func (p *MockResourceProvider) Refresh(
|
|||
return p.RefreshFn(info, s)
|
||||
}
|
||||
|
||||
return p.RefreshReturn, p.RefreshReturnError
|
||||
return p.RefreshReturn.DeepCopy(), p.RefreshReturnError
|
||||
}
|
||||
|
||||
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.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) {
|
||||
|
@ -245,7 +253,7 @@ func (p *MockResourceProvider) ReadDataDiff(
|
|||
return p.ReadDataDiffFn(info, desired)
|
||||
}
|
||||
|
||||
return p.ReadDataDiffReturn, p.ReadDataDiffReturnError
|
||||
return p.ReadDataDiffReturn.DeepCopy(), p.ReadDataDiffReturnError
|
||||
}
|
||||
|
||||
func (p *MockResourceProvider) ReadDataApply(
|
||||
|
@ -262,7 +270,7 @@ func (p *MockResourceProvider) ReadDataApply(
|
|||
return p.ReadDataApplyFn(info, d)
|
||||
}
|
||||
|
||||
return p.ReadDataApplyReturn, p.ReadDataApplyReturnError
|
||||
return p.ReadDataApplyReturn.DeepCopy(), p.ReadDataApplyReturnError
|
||||
}
|
||||
|
||||
func (p *MockResourceProvider) DataSources() []DataSource {
|
||||
|
|
Loading…
Reference in New Issue