Skip to content

Commit

Permalink
Make plugin-framework provider configuration code treat empty values …
Browse files Browse the repository at this point in the history
…like the SDK (#8798) (#15844)

* Make PF config code change `project = ""` to null value before checking ENVs

* Make plugin framework config code change all empty strings in config to null values

* Fix defect in unit test for `project`, uncomment

* Uncomment empty string unit tests

* Fix defect in test; expeceted value should be null list

* Add handling of empty lists in `HandleZeroValues`

* Fix typo in comment

* Add test case asserting `impersonate_service_account` empty strings are overridden by an ENV

* Update SDK `batching` tests: rename test cases,  make it clear values are arbitary

* Update `HandleZeroValues` to handle `batching` argument

* Uncomment empty string test

* Change test inputs from 123s to 45s

This is because 123s is transformed to 2m3s, but 45s remains 45s

* Protect against Batching being null/unknown in `HandleZeroValues`

* Add non-VCR acceptance test that shows provider behaviour when `credentials=""` and `GOOGLE_CREDENTIALS` interact

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Sep 14, 2023
1 parent 2b0330e commit aced908
Show file tree
Hide file tree
Showing 5 changed files with 310 additions and 147 deletions.
3 changes: 3 additions & 0 deletions .changelog/8798.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
provider: fixed the provider so it resumes ignoring empty strings set in the `provider` block
```
81 changes: 81 additions & 0 deletions google/fwtransport/framework_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"google.golang.org/grpc"

"github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
Expand Down Expand Up @@ -151,6 +152,15 @@ type FrameworkProviderConfig struct {
// LoadAndValidateFramework handles the bulk of configuring the provider
// it is pulled out so that we can manually call this from our testing provider as well
func (p *FrameworkProviderConfig) LoadAndValidateFramework(ctx context.Context, data *fwmodels.ProviderModel, tfVersion string, diags *diag.Diagnostics, providerversion string) {

// Make the plugin framwork code behave like the SDK by ignoring zero values. This means re-setting zero values to null.
// This is added to fix https://github.com/hashicorp/terraform-provider-google/issues/14255 in a v4.x.x release
// TODO(SarahFrench) remove as part of https://github.com/hashicorp/terraform-provider-google/issues/14447 in 5.0.0
p.HandleZeroValues(ctx, data, diags)
if diags.HasError() {
return
}

// Set defaults if needed
p.HandleDefaults(ctx, data, diags)
if diags.HasError() {
Expand Down Expand Up @@ -295,6 +305,77 @@ func (p *FrameworkProviderConfig) LoadAndValidateFramework(ctx context.Context,
p.RequestBatcherIam = transport_tpg.NewRequestBatcher("IAM", ctx, batchingConfig)
}

// HandleZeroValues will make the plugin framework act like the SDK; zero value, particularly empty strings, are converted to null.
// This causes the plugin framework to treat the field as unset, just like how the SDK ignores empty strings.
func (p *FrameworkProviderConfig) HandleZeroValues(ctx context.Context, data *fwmodels.ProviderModel, diags *diag.Diagnostics) {

// Change empty strings to null values
if data.AccessToken.Equal(types.StringValue("")) {
data.AccessToken = types.StringNull()
}
if data.BillingProject.Equal(types.StringValue("")) {
data.BillingProject = types.StringNull()
}
if data.Credentials.Equal(types.StringValue("")) {
data.Credentials = types.StringNull()
}
if data.ImpersonateServiceAccount.Equal(types.StringValue("")) {
data.ImpersonateServiceAccount = types.StringNull()
}
if data.Project.Equal(types.StringValue("")) {
data.Project = types.StringNull()
}
if data.Region.Equal(types.StringValue("")) {
data.Region = types.StringNull()
}
if data.RequestReason.Equal(types.StringValue("")) {
data.RequestReason = types.StringNull()
}
if data.RequestTimeout.Equal(types.StringValue("")) {
data.RequestTimeout = types.StringNull()
}
if data.Zone.Equal(types.StringValue("")) {
data.Zone = types.StringNull()
}

// Change lists that aren't null or unknown with length of zero to null lists
if !data.Scopes.IsNull() && !data.Scopes.IsUnknown() && (len(data.Scopes.Elements()) == 0) {
data.Scopes = types.ListNull(types.StringType)
}
if !data.ImpersonateServiceAccountDelegates.IsNull() && !data.ImpersonateServiceAccountDelegates.IsUnknown() && (len(data.ImpersonateServiceAccountDelegates.Elements()) == 0) {
data.ImpersonateServiceAccountDelegates = types.ListNull(types.StringType)
}

// Batching implementation will change in future, but this code will be removed in 5.0.0 so may be unaffected
if !data.Batching.IsNull() && !data.Batching.IsUnknown() && (len(data.Batching.Elements()) > 0) {
var pbConfigs []fwmodels.ProviderBatching
d := data.Batching.ElementsAs(ctx, &pbConfigs, true)
diags.Append(d...)
if diags.HasError() {
return
}
if pbConfigs[0].SendAfter.Equal(types.StringValue("")) {
pbConfigs[0].SendAfter = types.StringNull() // Convert empty string to null
}
b, _ := types.ObjectValue(
map[string]attr.Type{
"enable_batching": types.BoolType,
"send_after": types.StringType,
},
map[string]attr.Value{
"enable_batching": pbConfigs[0].EnableBatching,
"send_after": pbConfigs[0].SendAfter,
},
)
newBatching, d := types.ListValue(types.ObjectType{}.WithAttributeTypes(fwmodels.ProviderBatchingAttributes), []attr.Value{b})
diags.Append(d...)
if diags.HasError() {
return
}
data.Batching = newBatching
}
}

// HandleDefaults will handle all the defaults necessary in the provider
func (p *FrameworkProviderConfig) HandleDefaults(ctx context.Context, data *fwmodels.ProviderModel, diags *diag.Diagnostics) {
if data.AccessToken.IsNull() && data.Credentials.IsNull() {
Expand Down
Loading

0 comments on commit aced908

Please sign in to comment.