Use prepared config in provider.Configure

Core is only using the PrepareProviderConfig call for the validation
part of the method, but we should be re-validating the final config
immediately before Configure.

This change elects to not start using the PreparedConfig here, since
there is no useful reason for it at this point, and it would
introduce a functional difference between terraform releases that can be
avoided.
This commit is contained in:
James Bardin 2020-11-02 18:23:00 -05:00
parent fd43bc7847
commit e7b2d98ca3
4 changed files with 31 additions and 6 deletions

View File

@ -798,9 +798,6 @@ func TestApply_planNoModuleFiles(t *testing.T) {
planPath, planPath,
} }
apply.Run(args) apply.Run(args)
if p.PrepareProviderConfigCalled {
t.Fatal("Prepare provider config should not be called with a plan")
}
} }
func TestApply_refresh(t *testing.T) { func TestApply_refresh(t *testing.T) {

View File

@ -78,6 +78,11 @@ func TestContext2Plan_basic(t *testing.T) {
t.Fatal("unknown instance:", i) t.Fatal("unknown instance:", i)
} }
} }
if !p.PrepareProviderConfigCalled {
t.Fatal("provider config was not checked before Configure")
}
} }
func TestContext2Plan_createBefore_deposed(t *testing.T) { func TestContext2Plan_createBefore_deposed(t *testing.T) {

View File

@ -8,6 +8,7 @@ import (
"github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
"github.com/zclconf/go-cty/cty"
) )
// NodeApplyableProvider represents a provider during an apply. // NodeApplyableProvider represents a provider during an apply.
@ -108,8 +109,29 @@ func (n *NodeApplyableProvider) ConfigureProvider(ctx EvalContext, provider prov
return diags return diags
} }
configDiags := ctx.ConfigureProvider(n.Addr, configVal) // Allow the provider to validate and insert any defaults into the full
configDiags = configDiags.InConfigBody(configBody) // configuration.
req := providers.PrepareProviderConfigRequest{
Config: configVal,
}
return configDiags // PrepareProviderConfig is only used for validation. We are intentionally
// ignoring the PreparedConfig field to maintain existing behavior.
prepareResp := provider.PrepareProviderConfig(req)
diags = diags.Append(prepareResp.Diagnostics)
if diags.HasErrors() {
return diags
}
// If the provider returns something different, log a warning to help
// indicate to provider developers that the value is not used.
preparedCfg := prepareResp.PreparedConfig
if preparedCfg != cty.NilVal && !preparedCfg.IsNull() && !preparedCfg.RawEquals(configVal) {
log.Printf("[WARN] PrepareProviderConfig from %q changed the config value, but that value is unused", n.Addr)
}
configDiags := ctx.ConfigureProvider(n.Addr, configVal)
diags = diags.Append(configDiags.InConfigBody(configBody))
return diags
} }

View File

@ -133,6 +133,7 @@ func (p *MockProvider) PrepareProviderConfig(r providers.PrepareProviderConfigRe
if p.PrepareProviderConfigFn != nil { if p.PrepareProviderConfigFn != nil {
return p.PrepareProviderConfigFn(r) return p.PrepareProviderConfigFn(r)
} }
p.PrepareProviderConfigResponse.PreparedConfig = r.Config
return p.PrepareProviderConfigResponse return p.PrepareProviderConfigResponse
} }