core: Re-implement EvalWriteDiff to work with new plan types
This commit is contained in:
parent
686018ae12
commit
bd299b9a22
|
@ -55,6 +55,15 @@ func (c *Changes) ResourceInstanceDeposed(addr addrs.AbsResourceInstance, key st
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncWrapper returns a wrapper object around the receiver that can be used
|
||||||
|
// to make certain changes to the receiver in a concurrency-safe way, as long
|
||||||
|
// as all callers share the same wrapper object.
|
||||||
|
func (c *Changes) SyncWrapper() *ChangesSync {
|
||||||
|
return &ChangesSync{
|
||||||
|
changes: c,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ResourceInstanceChange describes a change to a particular resource instance
|
// ResourceInstanceChange describes a change to a particular resource instance
|
||||||
// object.
|
// object.
|
||||||
type ResourceInstanceChange struct {
|
type ResourceInstanceChange struct {
|
||||||
|
|
|
@ -66,6 +66,38 @@ func (rcs *ResourceInstanceChangeSrc) Decode(ty cty.Type) (*ResourceInstanceChan
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopy creates a copy of the receiver where any pointers to nested mutable
|
||||||
|
// values are also copied, thus ensuring that future mutations of the receiver
|
||||||
|
// will not affect the copy.
|
||||||
|
//
|
||||||
|
// Some types used within a resource change are immutable by convention even
|
||||||
|
// though the Go language allows them to be mutated, such as the types from
|
||||||
|
// the addrs package. These are _not_ copied by this method, under the
|
||||||
|
// assumption that callers will behave themselves.
|
||||||
|
func (rcs *ResourceInstanceChangeSrc) DeepCopy() *ResourceInstanceChangeSrc {
|
||||||
|
if rcs == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ret := *rcs
|
||||||
|
|
||||||
|
if len(ret.RequiredReplace) != 0 {
|
||||||
|
rr := make([]cty.Path, len(ret.RequiredReplace))
|
||||||
|
copy(rr, ret.RequiredReplace)
|
||||||
|
ret.RequiredReplace = rr
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ret.Private) != 0 {
|
||||||
|
private := make([]byte, len(ret.Private))
|
||||||
|
copy(private, ret.Private)
|
||||||
|
ret.Private = private
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.ChangeSrc.Before = ret.ChangeSrc.Before.Copy()
|
||||||
|
ret.ChangeSrc.After = ret.ChangeSrc.After.Copy()
|
||||||
|
|
||||||
|
return &ret
|
||||||
|
}
|
||||||
|
|
||||||
// OutputChange describes a change to an output value.
|
// OutputChange describes a change to an output value.
|
||||||
type OutputChangeSrc struct {
|
type OutputChangeSrc struct {
|
||||||
// ChangeSrc is an embedded description of the not-yet-decoded change.
|
// ChangeSrc is an embedded description of the not-yet-decoded change.
|
||||||
|
|
|
@ -16,3 +16,20 @@ type ChangesSync struct {
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
changes *Changes
|
changes *Changes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendResourceInstanceChange records the given resource instance change in
|
||||||
|
// the set of planned resource changes.
|
||||||
|
//
|
||||||
|
// The caller must ensure that there are no concurrent writes to the given
|
||||||
|
// change while this method is running, but it is safe to resume mutating
|
||||||
|
// it after this method returns without affecting the saved change.
|
||||||
|
func (cs *ChangesSync) AppendResourceInstanceChange(changeSrc *ResourceInstanceChangeSrc) {
|
||||||
|
if cs == nil {
|
||||||
|
panic("AppendResourceInstanceChange on nil ChangesSync")
|
||||||
|
}
|
||||||
|
cs.lock.Lock()
|
||||||
|
defer cs.lock.Unlock()
|
||||||
|
|
||||||
|
s := changeSrc.DeepCopy()
|
||||||
|
cs.changes.Resources = append(cs.changes.Resources, s)
|
||||||
|
}
|
||||||
|
|
|
@ -83,3 +83,14 @@ func (v DynamicValue) Decode(ty cty.Type) (cty.Value, error) {
|
||||||
func (v DynamicValue) ImpliedType() (cty.Type, error) {
|
func (v DynamicValue) ImpliedType() (cty.Type, error) {
|
||||||
return ctymsgpack.ImpliedType([]byte(v))
|
return ctymsgpack.ImpliedType([]byte(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy produces a copy of the receiver with a distinct backing array.
|
||||||
|
func (v DynamicValue) Copy() DynamicValue {
|
||||||
|
if len(v) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := make(DynamicValue, len(v))
|
||||||
|
copy(ret, v)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
|
@ -718,6 +718,7 @@ func (c *Context) graphWalker(operation walkOperation) *ContextGraphWalker {
|
||||||
return &ContextGraphWalker{
|
return &ContextGraphWalker{
|
||||||
Context: c,
|
Context: c,
|
||||||
State: c.state.SyncWrapper(),
|
State: c.state.SyncWrapper(),
|
||||||
|
Changes: c.changes.SyncWrapper(),
|
||||||
Operation: operation,
|
Operation: operation,
|
||||||
StopContext: c.runContext,
|
StopContext: c.runContext,
|
||||||
RootVariableValues: c.variables,
|
RootVariableValues: c.variables,
|
||||||
|
|
|
@ -732,41 +732,40 @@ func (n *EvalReadDiff) Eval(ctx EvalContext) (interface{}, error) {
|
||||||
// EvalWriteDiff is an EvalNode implementation that saves a planned change
|
// EvalWriteDiff is an EvalNode implementation that saves a planned change
|
||||||
// for an instance object into the set of global planned changes.
|
// for an instance object into the set of global planned changes.
|
||||||
type EvalWriteDiff struct {
|
type EvalWriteDiff struct {
|
||||||
Addr addrs.ResourceInstance
|
Addr addrs.ResourceInstance
|
||||||
DeposedKey states.DeposedKey
|
DeposedKey states.DeposedKey
|
||||||
Change **plans.ResourceInstanceChange
|
ProviderSchema **ProviderSchema
|
||||||
|
Change **plans.ResourceInstanceChange
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test
|
// TODO: test
|
||||||
func (n *EvalWriteDiff) Eval(ctx EvalContext) (interface{}, error) {
|
func (n *EvalWriteDiff) Eval(ctx EvalContext) (interface{}, error) {
|
||||||
return nil, fmt.Errorf("EvalWriteDiff not yet updated for new plan types")
|
providerSchema := *n.ProviderSchema
|
||||||
/*
|
change := *n.Change
|
||||||
diff, lock := ctx.Diff()
|
|
||||||
|
|
||||||
// The diff to write, if its empty it should write nil
|
if change.Addr.String() != n.Addr.String() || change.DeposedKey != n.DeposedKey {
|
||||||
var diffVal *InstanceDiff
|
// Should never happen, and indicates a bug in the caller.
|
||||||
if n.Diff != nil {
|
panic("inconsistent address and/or deposed key in EvalWriteDiff")
|
||||||
diffVal = *n.Diff
|
}
|
||||||
}
|
|
||||||
if diffVal.Empty() {
|
|
||||||
diffVal = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Acquire the lock so that we can do this safely concurrently
|
schema := providerSchema.ResourceTypes[n.Addr.Resource.Type]
|
||||||
lock.Lock()
|
if schema == nil {
|
||||||
defer lock.Unlock()
|
// Should be caught during validation, so we don't bother with a pretty error here
|
||||||
|
return nil, fmt.Errorf("provider does not support resource type %q", n.Addr.Resource.Type)
|
||||||
|
}
|
||||||
|
|
||||||
// Write the diff
|
csrc, err := change.Encode(schema.ImpliedType())
|
||||||
modDiff := diff.ModuleByPath(ctx.Path())
|
if err != nil {
|
||||||
if modDiff == nil {
|
return nil, fmt.Errorf("failed to encode planned changes for %s: %s", n.Addr, err)
|
||||||
modDiff = diff.AddModule(ctx.Path())
|
}
|
||||||
}
|
|
||||||
if diffVal != nil {
|
|
||||||
modDiff.Resources[n.Name] = diffVal
|
|
||||||
} else {
|
|
||||||
delete(modDiff.Resources, n.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
changes := ctx.Changes()
|
||||||
*/
|
changes.AppendResourceInstanceChange(csrc)
|
||||||
|
if n.DeposedKey == states.NotDeposed {
|
||||||
|
log.Printf("[TRACE] EvalWriteDiff: recorded %s change for %s", change.Action, n.Addr)
|
||||||
|
} else {
|
||||||
|
log.Printf("[TRACE] EvalWriteDiff: recorded %s change for %s deposed object %s", change.Action, n.Addr, n.DeposedKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,8 +181,9 @@ func (n *NodeApplyableResourceInstance) evalTreeDataResource(addr addrs.AbsResou
|
||||||
// Clear the diff now that we've applied it, so
|
// Clear the diff now that we've applied it, so
|
||||||
// later nodes won't see a diff that's now a no-op.
|
// later nodes won't see a diff that's now a no-op.
|
||||||
&EvalWriteDiff{
|
&EvalWriteDiff{
|
||||||
Addr: addr.Resource,
|
Addr: addr.Resource,
|
||||||
Change: nil,
|
ProviderSchema: &providerSchema,
|
||||||
|
Change: nil,
|
||||||
},
|
},
|
||||||
|
|
||||||
&EvalUpdateStateHook{},
|
&EvalUpdateStateHook{},
|
||||||
|
@ -347,8 +348,9 @@ func (n *NodeApplyableResourceInstance) evalTreeManagedResource(addr addrs.AbsRe
|
||||||
// don't see a diff that is already complete. There
|
// don't see a diff that is already complete. There
|
||||||
// is no longer a diff!
|
// is no longer a diff!
|
||||||
&EvalWriteDiff{
|
&EvalWriteDiff{
|
||||||
Addr: addr.Resource,
|
Addr: addr.Resource,
|
||||||
Change: nil,
|
ProviderSchema: &providerSchema,
|
||||||
|
Change: nil,
|
||||||
},
|
},
|
||||||
|
|
||||||
&EvalApplyPost{
|
&EvalApplyPost{
|
||||||
|
|
|
@ -78,8 +78,9 @@ func (n *NodePlanDestroyableResourceInstance) EvalTree() EvalNode {
|
||||||
Change: &change,
|
Change: &change,
|
||||||
},
|
},
|
||||||
&EvalWriteDiff{
|
&EvalWriteDiff{
|
||||||
Addr: addr.Resource,
|
Addr: addr.Resource,
|
||||||
Change: &change,
|
ProviderSchema: &providerSchema,
|
||||||
|
Change: &change,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,8 +99,9 @@ func (n *NodePlannableResourceInstance) evalTreeDataResource(addr addrs.AbsResou
|
||||||
},
|
},
|
||||||
|
|
||||||
&EvalWriteDiff{
|
&EvalWriteDiff{
|
||||||
Addr: addr.Resource,
|
Addr: addr.Resource,
|
||||||
Change: &change,
|
ProviderSchema: &providerSchema,
|
||||||
|
Change: &change,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -157,8 +158,9 @@ func (n *NodePlannableResourceInstance) evalTreeManagedResource(addr addrs.AbsRe
|
||||||
ProviderSchema: &providerSchema,
|
ProviderSchema: &providerSchema,
|
||||||
},
|
},
|
||||||
&EvalWriteDiff{
|
&EvalWriteDiff{
|
||||||
Addr: addr.Resource,
|
Addr: addr.Resource,
|
||||||
Change: &change,
|
ProviderSchema: &providerSchema,
|
||||||
|
Change: &change,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,8 +68,9 @@ func (n *NodePlannableResourceInstanceOrphan) EvalTree() EvalNode {
|
||||||
Change: &change,
|
Change: &change,
|
||||||
},
|
},
|
||||||
&EvalWriteDiff{
|
&EvalWriteDiff{
|
||||||
Addr: addr.Resource,
|
Addr: addr.Resource,
|
||||||
Change: &change,
|
ProviderSchema: &providerSchema,
|
||||||
|
Change: &change,
|
||||||
},
|
},
|
||||||
&EvalWriteState{
|
&EvalWriteState{
|
||||||
Addr: addr.Resource,
|
Addr: addr.Resource,
|
||||||
|
|
Loading…
Reference in New Issue