modify ProvidedBy to indicate no provider needed

Because of the composition pattern used within core, we can't easily
remove a behavior from an embedded type. Rather than trying to
re-implement all necessary methods on the
NodePlannableResourceInstnaceOrphan to exclude orphaned data resources
from GraphNodeProviderConsumer, we can modify ProvidedBy to indicate
when there is no provider required.
This commit is contained in:
James Bardin 2020-12-16 14:10:51 -05:00
parent 21d6fb5a37
commit c85adf191a
3 changed files with 68 additions and 1 deletions

View File

@ -6616,3 +6616,55 @@ resource "test_instance" "a" {
t.Fatal(diags.Err())
}
}
func TestContext2Plan_dataRemovalNoProvider(t *testing.T) {
m := testModuleInline(t, map[string]string{
"main.tf": `
resource "test_instance" "a" {
}
`,
})
p := testProvider("test")
p.PlanResourceChangeFn = testDiffFn
state := states.NewState()
root := state.EnsureModule(addrs.RootModuleInstance)
root.SetResourceInstanceCurrent(
mustResourceInstanceAddr("test_instance.a").Resource,
&states.ResourceInstanceObjectSrc{
Status: states.ObjectReady,
AttrsJSON: []byte(`{"id":"a","data":"foo"}`),
Dependencies: []addrs.ConfigResource{},
},
mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`),
)
// the provider for this data source is no longer in the config, but that
// should not matter for state removal.
root.SetResourceInstanceCurrent(
mustResourceInstanceAddr("data.test_data_source.d").Resource,
&states.ResourceInstanceObjectSrc{
Status: states.ObjectReady,
AttrsJSON: []byte(`{"id":"d"}`),
Dependencies: []addrs.ConfigResource{},
},
mustProviderConfig(`provider["registry.terraform.io/local/test"]`),
)
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
// We still need to be able to locate the provider to decode the
// state, since we do not know during init that this provider is
// only used for an orphaned data source.
addrs.NewProvider("registry.terraform.io", "local", "test"): testProviderFuncFixed(p),
},
State: state,
})
_, diags := ctx.Plan()
if diags.HasErrors() {
t.Fatal(diags.Err())
}
}

View File

@ -27,6 +27,7 @@ var (
_ GraphNodeAttachResourceConfig = (*NodePlannableResourceInstanceOrphan)(nil)
_ GraphNodeAttachResourceState = (*NodePlannableResourceInstanceOrphan)(nil)
_ GraphNodeExecutable = (*NodePlannableResourceInstanceOrphan)(nil)
_ GraphNodeProviderConsumer = (*NodePlannableResourceInstanceOrphan)(nil)
)
func (n *NodePlannableResourceInstanceOrphan) Name() string {
@ -48,6 +49,14 @@ func (n *NodePlannableResourceInstanceOrphan) Execute(ctx EvalContext, op walkOp
}
}
func (n *NodePlannableResourceInstanceOrphan) ProvidedBy() (addr addrs.ProviderConfig, exact bool) {
if n.Addr.Resource.Resource.Mode == addrs.DataResourceMode {
// indicate that this node does not require a configured provider
return nil, true
}
return n.NodeAbstractResourceInstance.ProvidedBy()
}
func (n *NodePlannableResourceInstanceOrphan) dataResourceExecute(ctx EvalContext) tfdiags.Diagnostics {
// A data source that is no longer in the config is removed from the state
log.Printf("[TRACE] NodePlannableResourceInstanceOrphan: removing state object for %s", n.Addr)

View File

@ -67,6 +67,7 @@ type GraphNodeProviderConsumer interface {
// ProvidedBy returns the address of the provider configuration the node
// refers to, if available. The following value types may be returned:
//
// nil + exact true: the node does not require a provider
// * addrs.LocalProviderConfig: the provider was set in the resource config
// * addrs.AbsProviderConfig + exact true: the provider configuration was
// taken from the instance state.
@ -111,9 +112,14 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
for _, v := range g.Vertices() {
// Does the vertex _directly_ use a provider?
if pv, ok := v.(GraphNodeProviderConsumer); ok {
providerAddr, exact := pv.ProvidedBy()
if providerAddr == nil && exact {
// no provider is required
continue
}
requested[v] = make(map[string]ProviderRequest)
providerAddr, exact := pv.ProvidedBy()
var absPc addrs.AbsProviderConfig
switch p := providerAddr.(type) {