mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
engine/planning: Shallow adoption of states.ResourceInstanceObjectFull
This is just a minimal set of changes to introduce uses of the new states.ResourceInstanceObjectFull to all of the leaf functions related to planning managed and data resource instances. The main goal here was just to prove that we'd reasonably be able to look up objects with the new type in all of the places we'd need to. We're planning some more substantial changes to the planning engine in future commits (e.g. to generate execution graphs instead of traditional plans) and so we'll plumb this in better as part of that work. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This commit is contained in:
@@ -102,8 +102,23 @@ func PlanChanges(ctx context.Context, prevRoundState *states.State, configInst *
|
|||||||
for instKey, instState := range resourceState.Instances {
|
for instKey, instState := range resourceState.Instances {
|
||||||
instAddr := resourceState.Addr.Instance(instKey)
|
instAddr := resourceState.Addr.Instance(instKey)
|
||||||
for dk := range instState.Deposed {
|
for dk := range instState.Deposed {
|
||||||
|
// We currently have a schism where we do all of the
|
||||||
|
// discovery work using the traditional state model but
|
||||||
|
// we then switch to using our new-style "full" object model
|
||||||
|
// to act on what we've discovered. This is hopefully just
|
||||||
|
// a temporary situation while we're operating in a mixed
|
||||||
|
// world where most of the system doesn't know about the
|
||||||
|
// new runtime yet.
|
||||||
|
objState := prevRoundState.SyncWrapper().ResourceInstanceObjectFull(instAddr, dk)
|
||||||
|
if objState == nil {
|
||||||
|
// If we get here then there's a bug in the
|
||||||
|
// ResourceInstanceObjectFull function, because we
|
||||||
|
// should only be here if instAddr and dk correspond.
|
||||||
|
// to an actual deposed object.
|
||||||
|
panic(fmt.Sprintf("state has %s deposed object %q, but ResourceInstanceObjectFull didn't return it", instAddr, dk))
|
||||||
|
}
|
||||||
diags = diags.Append(
|
diags = diags.Append(
|
||||||
planGlue.planDeposedResourceInstanceObject(ctx, instAddr, dk, instState),
|
planGlue.planDeposedResourceInstanceObject(ctx, instAddr, dk, objState),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,19 +83,15 @@ func (p *planGlue) planDesiredDataResourceInstance(ctx context.Context, inst *ev
|
|||||||
panic("unimplemented")
|
panic("unimplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *planGlue) planOrphanDataResourceInstance(_ context.Context, addr addrs.AbsResourceInstance, state *states.ResourceInstance) tfdiags.Diagnostics {
|
func (p *planGlue) planOrphanDataResourceInstance(_ context.Context, addr addrs.AbsResourceInstance, state *states.ResourceInstanceObjectFullSrc) tfdiags.Diagnostics {
|
||||||
// Regardless of outcome we'll always report that we completed planning.
|
// Regardless of outcome we'll always report that we completed planning.
|
||||||
defer p.planCtx.reportResourceInstancePlanCompletion(addr)
|
defer p.planCtx.reportResourceInstancePlanCompletion(addr)
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
|
|
||||||
// An orphan data resource is always just discarded completely, because
|
// An orphan data object is always just discarded completely, because
|
||||||
// OpenTofu retains them only for esoteric uses like the "tofu console"
|
// OpenTofu retains them only for esoteric uses like the "tofu console"
|
||||||
// command: they are not actually expected to persist between rounds.
|
// command: they are not actually expected to persist between rounds.
|
||||||
//
|
p.planCtx.refreshedState.SetResourceInstanceObjectFull(addr, states.NotDeposed, nil)
|
||||||
// FIXME: We can't actually populate the provider instance address here
|
|
||||||
// because in our current model it's split awkwardly across *states.Resource
|
|
||||||
// and *states.ResourceInstance, and we only have the latter here.
|
|
||||||
p.planCtx.refreshedState.SetResourceInstanceCurrent(addr, nil, addrs.AbsProviderConfig{}, state.ProviderKey)
|
|
||||||
|
|
||||||
return diags
|
return diags
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func (p *planGlue) PlanDesiredResourceInstance(ctx context.Context, inst *eval.D
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *planGlue) planOrphanResourceInstance(ctx context.Context, addr addrs.AbsResourceInstance, state *states.ResourceInstance) tfdiags.Diagnostics {
|
func (p *planGlue) planOrphanResourceInstance(ctx context.Context, addr addrs.AbsResourceInstance, state *states.ResourceInstanceObjectFullSrc) tfdiags.Diagnostics {
|
||||||
log.Printf("[TRACE] planContext: planning orphan resource instance %s", addr)
|
log.Printf("[TRACE] planContext: planning orphan resource instance %s", addr)
|
||||||
switch mode := addr.Resource.Resource.Mode; mode {
|
switch mode := addr.Resource.Resource.Mode; mode {
|
||||||
case addrs.ManagedResourceMode:
|
case addrs.ManagedResourceMode:
|
||||||
@@ -90,7 +90,7 @@ func (p *planGlue) planOrphanResourceInstance(ctx context.Context, addr addrs.Ab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *planGlue) planDeposedResourceInstanceObject(ctx context.Context, addr addrs.AbsResourceInstance, deposedKey states.DeposedKey, state *states.ResourceInstance) tfdiags.Diagnostics {
|
func (p *planGlue) planDeposedResourceInstanceObject(ctx context.Context, addr addrs.AbsResourceInstance, deposedKey states.DeposedKey, state *states.ResourceInstanceObjectFullSrc) tfdiags.Diagnostics {
|
||||||
log.Printf("[TRACE] planContext: planning deposed resource instance object %s %s", addr, deposedKey)
|
log.Printf("[TRACE] planContext: planning deposed resource instance object %s %s", addr, deposedKey)
|
||||||
if addr.Resource.Resource.Mode != addrs.ManagedResourceMode {
|
if addr.Resource.Resource.Mode != addrs.ManagedResourceMode {
|
||||||
// Should not be possible because only managed resource instances
|
// Should not be possible because only managed resource instances
|
||||||
@@ -369,16 +369,37 @@ func (p *planGlue) resourceInstancePlaceholderValue(ctx context.Context, provide
|
|||||||
// should adopt a different representation of state which uses a tree structure
|
// should adopt a different representation of state which uses a tree structure
|
||||||
// where we can efficiently scan over subtrees that match a particular prefix,
|
// where we can efficiently scan over subtrees that match a particular prefix,
|
||||||
// rather than always scanning over everything.
|
// rather than always scanning over everything.
|
||||||
func resourceInstancesFilter(state *states.State, want func(addrs.AbsResourceInstance) bool) iter.Seq2[addrs.AbsResourceInstance, *states.ResourceInstance] {
|
func resourceInstancesFilter(state *states.State, want func(addrs.AbsResourceInstance) bool) iter.Seq2[addrs.AbsResourceInstance, *states.ResourceInstanceObjectFullSrc] {
|
||||||
return func(yield func(addrs.AbsResourceInstance, *states.ResourceInstance) bool) {
|
return func(yield func(addrs.AbsResourceInstance, *states.ResourceInstanceObjectFullSrc) bool) {
|
||||||
for _, modState := range state.Modules {
|
for _, modState := range state.Modules {
|
||||||
for _, resourceState := range modState.Resources {
|
for _, resourceState := range modState.Resources {
|
||||||
for instKey, instanceState := range resourceState.Instances {
|
for instKey, instanceState := range resourceState.Instances {
|
||||||
|
if instanceState.Current == nil {
|
||||||
|
// Only the current object for a resource instance
|
||||||
|
// can be an "orphan". (Deposed objects are handled
|
||||||
|
// elsewhere.)
|
||||||
|
continue
|
||||||
|
}
|
||||||
instAddr := resourceState.Addr.Instance(instKey)
|
instAddr := resourceState.Addr.Instance(instKey)
|
||||||
if !want(instAddr) {
|
if !want(instAddr) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !yield(instAddr, instanceState) {
|
// We currently have a schism where we do all of the
|
||||||
|
// discovery work using the traditional state model but
|
||||||
|
// we then switch to using our new-style "full" object model
|
||||||
|
// to act on what we've discovered. This is hopefully just
|
||||||
|
// a temporary situation while we're operating in a mixed
|
||||||
|
// world where most of the system doesn't know about the
|
||||||
|
// new runtime yet.
|
||||||
|
objState := state.SyncWrapper().ResourceInstanceObjectFull(instAddr, states.NotDeposed)
|
||||||
|
if objState == nil {
|
||||||
|
// If we get here then there's a bug in the
|
||||||
|
// ResourceInstanceObjectFull function, because we
|
||||||
|
// should only be here if instAddr corresponds to a
|
||||||
|
// to an instance with a current object.
|
||||||
|
panic(fmt.Sprintf("state has %s, but ResourceInstanceObjectFull didn't return it", instAddr))
|
||||||
|
}
|
||||||
|
if !yield(instAddr, objState) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ func (p *planGlue) planDesiredManagedResourceInstance(ctx context.Context, inst
|
|||||||
|
|
||||||
var prevRoundVal cty.Value
|
var prevRoundVal cty.Value
|
||||||
var prevRoundPrivate []byte
|
var prevRoundPrivate []byte
|
||||||
prevRoundState := p.planCtx.prevRoundState.ResourceInstance(inst.Addr)
|
prevRoundState := p.planCtx.prevRoundState.SyncWrapper().ResourceInstanceObjectFull(inst.Addr, states.NotDeposed)
|
||||||
if prevRoundState != nil && prevRoundState.Current != nil {
|
if prevRoundState != nil {
|
||||||
obj, err := prevRoundState.Current.Decode(schema.Block.ImpliedType())
|
obj, err := states.DecodeResourceInstanceObjectFull(prevRoundState, schema.Block.ImpliedType())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
diags = diags.Append(tfdiags.AttributeValue(
|
diags = diags.Append(tfdiags.AttributeValue(
|
||||||
tfdiags.Error,
|
tfdiags.Error,
|
||||||
@@ -223,7 +223,7 @@ func (p *planGlue) planDesiredManagedResourceInstance(ctx context.Context, inst
|
|||||||
return planResp.PlannedState, diags
|
return planResp.PlannedState, diags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *planGlue) planOrphanManagedResourceInstance(ctx context.Context, addr addrs.AbsResourceInstance, state *states.ResourceInstance) tfdiags.Diagnostics {
|
func (p *planGlue) planOrphanManagedResourceInstance(ctx context.Context, addr addrs.AbsResourceInstance, state *states.ResourceInstanceObjectFullSrc) tfdiags.Diagnostics {
|
||||||
// Regardless of outcome we'll always report that we completed planning.
|
// Regardless of outcome we'll always report that we completed planning.
|
||||||
defer p.planCtx.reportResourceInstancePlanCompletion(addr)
|
defer p.planCtx.reportResourceInstancePlanCompletion(addr)
|
||||||
|
|
||||||
@@ -231,7 +231,7 @@ func (p *planGlue) planOrphanManagedResourceInstance(ctx context.Context, addr a
|
|||||||
panic("unimplemented")
|
panic("unimplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *planGlue) planDeposedManagedResourceInstanceObject(ctx context.Context, addr addrs.AbsResourceInstance, deposedKey states.DeposedKey, state *states.ResourceInstance) tfdiags.Diagnostics {
|
func (p *planGlue) planDeposedManagedResourceInstanceObject(ctx context.Context, addr addrs.AbsResourceInstance, deposedKey states.DeposedKey, state *states.ResourceInstanceObjectFullSrc) tfdiags.Diagnostics {
|
||||||
// Regardless of outcome we'll always report that we completed planning.
|
// Regardless of outcome we'll always report that we completed planning.
|
||||||
defer p.planCtx.reportResourceInstanceDeposedPlanCompletion(addr, deposedKey)
|
defer p.planCtx.reportResourceInstanceDeposedPlanCompletion(addr, deposedKey)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user