mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-25 01:00:16 -05:00
engine/planning: Find "orphan" resource instances
The eval system gradually reports the "desired" declarations at various different levels of granularity, and so the planning engine should compare that with the instances in the previous run state to notice when any existing resource instance is no longer in the desired state. This doesn't yet include a real implementation of planning the deletion of such resource instances. Real planning behaviors depend on us having some sort of provider instance and ephemeral resource instance manager to be able to make requests to configured providers, so that will follow in subsequent commits before we can implement the actual planning behaviors. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This commit is contained in:
@@ -61,7 +61,7 @@ type PlanGlue interface {
|
||||
// different levels of granularity and so the implementation must also
|
||||
// keep track of all of the orphan resource instances it has already
|
||||
// detected and handled to avoid generating duplicate planned actions.
|
||||
PlanResourceInstanceOrphans(ctx context.Context, resourceAddr addrs.AbsResource, desiredInstances iter.Seq[addrs.InstanceKey]) tfdiags.Diagnostics
|
||||
PlanResourceInstanceOrphans(ctx context.Context, resourceAddr addrs.AbsResource, desiredInstances iter.Seq[addrs.InstanceKey], oracle *PlanningOracle) tfdiags.Diagnostics
|
||||
|
||||
// PlanResourceOrphans creates planned actions for any instances of
|
||||
// resources in the given module instance that that existed in the prior
|
||||
@@ -71,7 +71,7 @@ type PlanGlue interface {
|
||||
// with entirely-removed resources instead of removed instances of a
|
||||
// resource that is still configured. The same caveat about wildcard
|
||||
// instances applies here too.
|
||||
PlanResourceOrphans(ctx context.Context, moduleInstAddr addrs.ModuleInstance, desiredResources iter.Seq[addrs.Resource]) tfdiags.Diagnostics
|
||||
PlanResourceOrphans(ctx context.Context, moduleInstAddr addrs.ModuleInstance, desiredResources iter.Seq[addrs.Resource], oracle *PlanningOracle) tfdiags.Diagnostics
|
||||
|
||||
// PlanModuleCallInstanceOrphans creates planned actions for any prior
|
||||
// state resource instances that belong to instances of the given module
|
||||
@@ -81,7 +81,7 @@ type PlanGlue interface {
|
||||
// the removal of an entire module instance containing resource instances
|
||||
// instead of removal of the resources themselves. The same caveat about
|
||||
// wildcard instances applies here too.
|
||||
PlanModuleCallInstanceOrphans(ctx context.Context, moduleCallAddr addrs.AbsModuleCall, desiredInstances iter.Seq[addrs.InstanceKey]) tfdiags.Diagnostics
|
||||
PlanModuleCallInstanceOrphans(ctx context.Context, moduleCallAddr addrs.AbsModuleCall, desiredInstances iter.Seq[addrs.InstanceKey], oracle *PlanningOracle) tfdiags.Diagnostics
|
||||
|
||||
// PlanModuleCallOrphans creates planned actions for any prior state
|
||||
// resource instances that belong to any module calls within
|
||||
@@ -91,7 +91,7 @@ type PlanGlue interface {
|
||||
// with the removal of an entire module call containing resource instances,
|
||||
// instead of removal of just one dynamic instance of a module call that's
|
||||
// still declared.
|
||||
PlanModuleCallOrphans(ctx context.Context, callerModuleInstAddr addrs.ModuleInstance, desiredCalls iter.Seq[addrs.ModuleCall]) tfdiags.Diagnostics
|
||||
PlanModuleCallOrphans(ctx context.Context, callerModuleInstAddr addrs.ModuleInstance, desiredCalls iter.Seq[addrs.ModuleCall], oracle *PlanningOracle) tfdiags.Diagnostics
|
||||
}
|
||||
|
||||
// DrivePlanning uses this configuration instance to drive forward a planning
|
||||
@@ -145,7 +145,7 @@ func (c *ConfigInstance) DrivePlanning(ctx context.Context, glue PlanGlue) (*Pla
|
||||
})
|
||||
wg.Go(func() {
|
||||
ctx := grapheval.ContextWithNewWorker(ctx)
|
||||
orphanDiags = announcePlanOrphans(ctx, glue, rootModuleInstance)
|
||||
orphanDiags = announcePlanOrphans(ctx, glue, evalGlue.oracle, rootModuleInstance)
|
||||
})
|
||||
wg.Wait()
|
||||
diags = diags.Append(checkDiags)
|
||||
@@ -212,17 +212,17 @@ func (p *planningEvalGlue) ResourceInstanceValue(ctx context.Context, ri *config
|
||||
return p.planEngineGlue.PlanDesiredResourceInstance(ctx, desired, p.oracle)
|
||||
}
|
||||
|
||||
func announcePlanOrphans(ctx context.Context, glue PlanGlue, rootModuleInstance evalglue.CompiledModuleInstance) tfdiags.Diagnostics {
|
||||
func announcePlanOrphans(ctx context.Context, glue PlanGlue, oracle *PlanningOracle, rootModuleInstance evalglue.CompiledModuleInstance) tfdiags.Diagnostics {
|
||||
var diags collectedDiagnostics
|
||||
announcePlanOrphansRecursive(ctx, glue, &diags, addrs.RootModuleInstance, rootModuleInstance)
|
||||
announcePlanOrphansRecursive(ctx, glue, oracle, &diags, addrs.RootModuleInstance, rootModuleInstance)
|
||||
return diags.diags
|
||||
}
|
||||
|
||||
func announcePlanOrphansRecursive(ctx context.Context, glue PlanGlue, diags *collectedDiagnostics, currentModuleInstAddr addrs.ModuleInstance, currentModuleInstance evalglue.CompiledModuleInstance) {
|
||||
func announcePlanOrphansRecursive(ctx context.Context, glue PlanGlue, oracle *PlanningOracle, diags *collectedDiagnostics, currentModuleInstAddr addrs.ModuleInstance, currentModuleInstance evalglue.CompiledModuleInstance) {
|
||||
var wg sync.WaitGroup
|
||||
// Announce the module calls themselves
|
||||
diags.Append(
|
||||
glue.PlanModuleCallOrphans(ctx, currentModuleInstAddr, currentModuleInstance.ChildModuleCalls(ctx)),
|
||||
glue.PlanModuleCallOrphans(ctx, currentModuleInstAddr, currentModuleInstance.ChildModuleCalls(ctx), oracle),
|
||||
)
|
||||
// Announce the instances of each module call and recurse into each one
|
||||
// to deal with the declarations within it.
|
||||
@@ -237,17 +237,17 @@ func announcePlanOrphansRecursive(ctx context.Context, glue PlanGlue, diags *col
|
||||
return
|
||||
}
|
||||
}
|
||||
}),
|
||||
}, oracle),
|
||||
)
|
||||
for callInstAddr, childInst := range currentModuleInstance.ChildModuleInstancesForCall(ctx, callAddr) {
|
||||
childInstAddr := currentModuleInstAddr.Child(callInstAddr.Call.Name, callInstAddr.Key)
|
||||
announcePlanOrphansRecursive(ctx, glue, diags, childInstAddr, childInst)
|
||||
announcePlanOrphansRecursive(ctx, glue, oracle, diags, childInstAddr, childInst)
|
||||
}
|
||||
}
|
||||
})
|
||||
// Announce the resource declarations themselves
|
||||
diags.Append(
|
||||
glue.PlanResourceOrphans(ctx, currentModuleInstAddr, currentModuleInstance.Resources(ctx)),
|
||||
glue.PlanResourceOrphans(ctx, currentModuleInstAddr, currentModuleInstance.Resources(ctx), oracle),
|
||||
)
|
||||
// Announce the instances of each resource
|
||||
wg.Go(func() {
|
||||
@@ -261,7 +261,7 @@ func announcePlanOrphansRecursive(ctx context.Context, glue PlanGlue, diags *col
|
||||
return
|
||||
}
|
||||
}
|
||||
}),
|
||||
}, oracle),
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -346,28 +346,28 @@ func (p *planGlueCallLog) PlanDesiredResourceInstance(ctx context.Context, inst
|
||||
}
|
||||
|
||||
// PlanModuleCallInstanceOrphans implements eval.PlanGlue.
|
||||
func (p *planGlueCallLog) PlanModuleCallInstanceOrphans(ctx context.Context, moduleCallAddr addrs.AbsModuleCall, desiredInstances iter.Seq[addrs.InstanceKey]) tfdiags.Diagnostics {
|
||||
func (p *planGlueCallLog) PlanModuleCallInstanceOrphans(ctx context.Context, moduleCallAddr addrs.AbsModuleCall, desiredInstances iter.Seq[addrs.InstanceKey], oracle *eval.PlanningOracle) tfdiags.Diagnostics {
|
||||
// We don't currently do anything with calls to this method, because
|
||||
// no tests we've written so far rely on it.
|
||||
return nil
|
||||
}
|
||||
|
||||
// PlanModuleCallOrphans implements eval.PlanGlue.
|
||||
func (p *planGlueCallLog) PlanModuleCallOrphans(ctx context.Context, callerModuleInstAddr addrs.ModuleInstance, desiredCalls iter.Seq[addrs.ModuleCall]) tfdiags.Diagnostics {
|
||||
func (p *planGlueCallLog) PlanModuleCallOrphans(ctx context.Context, callerModuleInstAddr addrs.ModuleInstance, desiredCalls iter.Seq[addrs.ModuleCall], oracle *eval.PlanningOracle) tfdiags.Diagnostics {
|
||||
// We don't currently do anything with calls to this method, because
|
||||
// no tests we've written so far rely on it.
|
||||
return nil
|
||||
}
|
||||
|
||||
// PlanResourceInstanceOrphans implements eval.PlanGlue.
|
||||
func (p *planGlueCallLog) PlanResourceInstanceOrphans(ctx context.Context, resourceAddr addrs.AbsResource, desiredInstances iter.Seq[addrs.InstanceKey]) tfdiags.Diagnostics {
|
||||
func (p *planGlueCallLog) PlanResourceInstanceOrphans(ctx context.Context, resourceAddr addrs.AbsResource, desiredInstances iter.Seq[addrs.InstanceKey], oracle *eval.PlanningOracle) tfdiags.Diagnostics {
|
||||
// We don't currently do anything with calls to this method, because
|
||||
// no tests we've written so far rely on it.
|
||||
return nil
|
||||
}
|
||||
|
||||
// PlanResourceOrphans implements eval.PlanGlue.
|
||||
func (p *planGlueCallLog) PlanResourceOrphans(ctx context.Context, moduleInstAddr addrs.ModuleInstance, desiredResources iter.Seq[addrs.Resource]) tfdiags.Diagnostics {
|
||||
func (p *planGlueCallLog) PlanResourceOrphans(ctx context.Context, moduleInstAddr addrs.ModuleInstance, desiredResources iter.Seq[addrs.Resource], oracle *eval.PlanningOracle) tfdiags.Diagnostics {
|
||||
// We don't currently do anything with calls to this method, because
|
||||
// no tests we've written so far rely on it.
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user