Flow allowUnknows for Diff/Check Config

We pass this information for Diff and Check on specific resources, so
we can correctly block unknows from flowing to plugins during applies.
This commit is contained in:
Matt Ellis 2019-05-23 10:54:18 -07:00
parent e574f33fa0
commit f897bf8b4b
7 changed files with 43 additions and 31 deletions

View file

@ -715,7 +715,8 @@ func TestSingleResourceDefaultProviderReplace(t *testing.T) {
loaders := []*deploytest.ProviderLoader{
deploytest.NewProviderLoader("pkgA", semver.MustParse("1.0.0"), func() (plugin.Provider, error) {
return &deploytest.Provider{
DiffConfigF: func(urn resource.URN, olds, news resource.PropertyMap) (plugin.DiffResult, error) {
DiffConfigF: func(urn resource.URN, olds, news resource.PropertyMap,
allowUnknowns bool) (plugin.DiffResult, error) {
// Always require replacement.
keys := []resource.PropertyKey{}
for k := range news {
@ -793,7 +794,8 @@ func TestSingleResourceExplicitProviderReplace(t *testing.T) {
loaders := []*deploytest.ProviderLoader{
deploytest.NewProviderLoader("pkgA", semver.MustParse("1.0.0"), func() (plugin.Provider, error) {
return &deploytest.Provider{
DiffConfigF: func(urn resource.URN, olds, news resource.PropertyMap) (plugin.DiffResult, error) {
DiffConfigF: func(urn resource.URN, olds, news resource.PropertyMap,
allowUnknowns bool) (plugin.DiffResult, error) {
// Always require replacement.
keys := []resource.PropertyKey{}
for k := range news {
@ -882,7 +884,8 @@ func TestSingleResourceExplicitProviderDeleteBeforeReplace(t *testing.T) {
loaders := []*deploytest.ProviderLoader{
deploytest.NewProviderLoader("pkgA", semver.MustParse("1.0.0"), func() (plugin.Provider, error) {
return &deploytest.Provider{
DiffConfigF: func(urn resource.URN, olds, news resource.PropertyMap) (plugin.DiffResult, error) {
DiffConfigF: func(urn resource.URN, olds, news resource.PropertyMap,
allowUnknowns bool) (plugin.DiffResult, error) {
// Always require replacement.
keys := []resource.PropertyKey{}
for k := range news {
@ -2598,7 +2601,8 @@ func TestDeleteBeforeReplace(t *testing.T) {
loaders := []*deploytest.ProviderLoader{
deploytest.NewProviderLoader("pkgA", semver.MustParse("1.0.0"), func() (plugin.Provider, error) {
return &deploytest.Provider{
DiffConfigF: func(urn resource.URN, olds, news resource.PropertyMap) (plugin.DiffResult, error) {
DiffConfigF: func(urn resource.URN, olds, news resource.PropertyMap,
allowUnknowns bool) (plugin.DiffResult, error) {
if !olds["A"].DeepEquals(news["A"]) {
return plugin.DiffResult{
ReplaceKeys: []resource.PropertyKey{"A"},

View file

@ -39,13 +39,14 @@ func (p *builtinProvider) Pkg() tokens.Package {
// CheckConfig validates the configuration for this resource provider.
func (p *builtinProvider) CheckConfig(urn resource.URN, olds,
news resource.PropertyMap) (resource.PropertyMap, []plugin.CheckFailure, error) {
news resource.PropertyMap, allowUnknowns bool) (resource.PropertyMap, []plugin.CheckFailure, error) {
return nil, nil, nil
}
// DiffConfig checks what impacts a hypothetical change to this provider's configuration will have on the provider.
func (p *builtinProvider) DiffConfig(urn resource.URN, olds, news resource.PropertyMap) (plugin.DiffResult, error) {
func (p *builtinProvider) DiffConfig(urn resource.URN, olds, news resource.PropertyMap,
allowUnknowns bool) (plugin.DiffResult, error) {
return plugin.DiffResult{Changes: plugin.DiffNone}, nil
}

View file

@ -33,8 +33,8 @@ type Provider struct {
configured bool
CheckConfigF func(urn resource.URN, olds,
news resource.PropertyMap) (resource.PropertyMap, []plugin.CheckFailure, error)
DiffConfigF func(urn resource.URN, olds, news resource.PropertyMap) (plugin.DiffResult, error)
news resource.PropertyMap, allowUnknowns bool) (resource.PropertyMap, []plugin.CheckFailure, error)
DiffConfigF func(urn resource.URN, olds, news resource.PropertyMap, allowUnknowns bool) (plugin.DiffResult, error)
ConfigureF func(news resource.PropertyMap) error
CheckF func(urn resource.URN,
@ -77,17 +77,18 @@ func (prov *Provider) GetPluginInfo() (workspace.PluginInfo, error) {
}
func (prov *Provider) CheckConfig(urn resource.URN, olds,
news resource.PropertyMap) (resource.PropertyMap, []plugin.CheckFailure, error) {
news resource.PropertyMap, allowUnknowns bool) (resource.PropertyMap, []plugin.CheckFailure, error) {
if prov.CheckConfigF == nil {
return news, nil, nil
}
return prov.CheckConfigF(urn, olds, news)
return prov.CheckConfigF(urn, olds, news, allowUnknowns)
}
func (prov *Provider) DiffConfig(urn resource.URN, olds, news resource.PropertyMap) (plugin.DiffResult, error) {
func (prov *Provider) DiffConfig(urn resource.URN, olds, news resource.PropertyMap,
allowUnknowns bool) (plugin.DiffResult, error) {
if prov.DiffConfigF == nil {
return plugin.DiffResult{}, nil
}
return prov.DiffConfigF(urn, olds, news)
return prov.DiffConfigF(urn, olds, news, allowUnknowns)
}
func (prov *Provider) Configure(inputs resource.PropertyMap) error {
contract.Assert(!prov.configured)

View file

@ -186,14 +186,15 @@ func (r *Registry) label() string {
// CheckConfig validates the configuration for this resource provider.
func (r *Registry) CheckConfig(urn resource.URN, olds,
news resource.PropertyMap) (resource.PropertyMap, []plugin.CheckFailure, error) {
news resource.PropertyMap, allowUnknowns bool) (resource.PropertyMap, []plugin.CheckFailure, error) {
contract.Fail()
return nil, nil, errors.New("the provider registry is not configurable")
}
// DiffConfig checks what impacts a hypothetical change to this provider's configuration will have on the provider.
func (r *Registry) DiffConfig(urn resource.URN, olds, news resource.PropertyMap) (plugin.DiffResult, error) {
func (r *Registry) DiffConfig(urn resource.URN, olds, news resource.PropertyMap,
allowUnknowns bool) (plugin.DiffResult, error) {
contract.Fail()
return plugin.DiffResult{}, errors.New("the provider registry is not configurable")
}
@ -233,7 +234,7 @@ func (r *Registry) Check(urn resource.URN, olds, news resource.PropertyMap,
}
// Check the provider's config. If the check fails, unload the provider.
inputs, failures, err := provider.CheckConfig(urn, olds, news)
inputs, failures, err := provider.CheckConfig(urn, olds, news, allowUnknowns)
if len(failures) != 0 || err != nil {
closeErr := r.host.CloseProvider(provider)
contract.IgnoreError(closeErr)
@ -276,7 +277,7 @@ func (r *Registry) Diff(urn resource.URN, id resource.ID, olds, news resource.Pr
provider, ok = r.GetProvider(mustNewReference(urn, id))
contract.Assertf(ok, "Provider must have been registered by NewRegistry for DBR Diff (%v::%v)", urn, id)
diff, err := provider.DiffConfig(urn, olds, news)
diff, err := provider.DiffConfig(urn, olds, news, allowUnknowns)
if err != nil {
return plugin.DiffResult{Changes: plugin.DiffUnknown}, err
}
@ -284,7 +285,7 @@ func (r *Registry) Diff(urn resource.URN, id resource.ID, olds, news resource.Pr
}
// Diff the properties.
diff, err := provider.DiffConfig(urn, olds, news)
diff, err := provider.DiffConfig(urn, olds, news, allowUnknowns)
if err != nil {
return plugin.DiffResult{Changes: plugin.DiffUnknown}, err
}

View file

@ -78,8 +78,8 @@ type testProvider struct {
version semver.Version
configured bool
checkConfig func(resource.URN, resource.PropertyMap,
resource.PropertyMap) (resource.PropertyMap, []plugin.CheckFailure, error)
diffConfig func(resource.URN, resource.PropertyMap, resource.PropertyMap) (plugin.DiffResult, error)
resource.PropertyMap, bool) (resource.PropertyMap, []plugin.CheckFailure, error)
diffConfig func(resource.URN, resource.PropertyMap, resource.PropertyMap, bool) (plugin.DiffResult, error)
config func(resource.PropertyMap) error
}
@ -93,11 +93,12 @@ func (prov *testProvider) Pkg() tokens.Package {
return prov.pkg
}
func (prov *testProvider) CheckConfig(urn resource.URN, olds,
news resource.PropertyMap) (resource.PropertyMap, []plugin.CheckFailure, error) {
return prov.checkConfig(urn, olds, news)
news resource.PropertyMap, allowUnknowns bool) (resource.PropertyMap, []plugin.CheckFailure, error) {
return prov.checkConfig(urn, olds, news, allowUnknowns)
}
func (prov *testProvider) DiffConfig(urn resource.URN, olds, news resource.PropertyMap) (plugin.DiffResult, error) {
return prov.diffConfig(urn, olds, news)
func (prov *testProvider) DiffConfig(urn resource.URN, olds, news resource.PropertyMap,
allowUnknowns bool) (plugin.DiffResult, error) {
return prov.diffConfig(urn, olds, news, allowUnknowns)
}
func (prov *testProvider) Configure(inputs resource.PropertyMap) error {
if err := prov.config(inputs); err != nil {
@ -204,10 +205,11 @@ func newSimpleLoader(t *testing.T, pkg, version string, config func(resource.Pro
pkg: pkg,
version: ver,
checkConfig: func(urn resource.URN, olds,
news resource.PropertyMap) (resource.PropertyMap, []plugin.CheckFailure, error) {
news resource.PropertyMap, allowUnknowns bool) (resource.PropertyMap, []plugin.CheckFailure, error) {
return news, nil, nil
},
diffConfig: func(urn resource.URN, olds, news resource.PropertyMap) (plugin.DiffResult, error) {
diffConfig: func(urn resource.URN, olds, news resource.PropertyMap,
allowUnknowns bool) (plugin.DiffResult, error) {
return plugin.DiffResult{}, nil
},
config: config,
@ -515,10 +517,11 @@ func TestCRUDPreview(t *testing.T) {
pkg: pkg,
version: ver,
checkConfig: func(urn resource.URN, olds,
news resource.PropertyMap) (resource.PropertyMap, []plugin.CheckFailure, error) {
news resource.PropertyMap, allowUnknowns bool) (resource.PropertyMap, []plugin.CheckFailure, error) {
return news, nil, nil
},
diffConfig: func(urn resource.URN, olds, news resource.PropertyMap) (plugin.DiffResult, error) {
diffConfig: func(urn resource.URN, olds, news resource.PropertyMap,
allowUnknowns bool) (plugin.DiffResult, error) {
// Always reuquire replacement.
return plugin.DiffResult{ReplaceKeys: []resource.PropertyKey{"id"}}, nil
},

View file

@ -39,9 +39,10 @@ type Provider interface {
Pkg() tokens.Package
// CheckConfig validates the configuration for this resource provider.
CheckConfig(urn resource.URN, olds, news resource.PropertyMap) (resource.PropertyMap, []CheckFailure, error)
CheckConfig(urn resource.URN, olds, news resource.PropertyMap,
allowUnknowns bool) (resource.PropertyMap, []CheckFailure, error)
// DiffConfig checks what impacts a hypothetical change to this provider's configuration will have on the provider.
DiffConfig(urn resource.URN, olds, news resource.PropertyMap) (DiffResult, error)
DiffConfig(urn resource.URN, olds, news resource.PropertyMap, allowUnknowns bool) (DiffResult, error)
// Configure configures the resource provider with "globals" that control its behavior.
Configure(inputs resource.PropertyMap) error

View file

@ -86,7 +86,7 @@ func (p *provider) label() string {
// CheckConfig validates the configuration for this resource provider.
func (p *provider) CheckConfig(urn resource.URN, olds,
news resource.PropertyMap) (resource.PropertyMap, []CheckFailure, error) {
news resource.PropertyMap, allowUnknowns bool) (resource.PropertyMap, []CheckFailure, error) {
// Ensure that all config values are strings or unknowns.
var failures []CheckFailure
for k, v := range news {
@ -112,7 +112,8 @@ func (p *provider) CheckConfig(urn resource.URN, olds,
}
// DiffConfig checks what impacts a hypothetical change to this provider's configuration will have on the provider.
func (p *provider) DiffConfig(urn resource.URN, olds, news resource.PropertyMap) (DiffResult, error) {
func (p *provider) DiffConfig(urn resource.URN, olds, news resource.PropertyMap,
allowUnknowns bool) (DiffResult, error) {
// There are two interesting scenarios with the present gRPC interface:
// 1. Configuration differences in which all properties are known
// 2. Configuration differences in which some new property is unknown.