From d8db276011acc4f72b2f22ac24f61aa88a8d8f5b Mon Sep 17 00:00:00 2001 From: Sean Gillespie Date: Fri, 19 Jan 2024 12:45:39 -0800 Subject: [PATCH] map empty certificate filter lists to null lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Terraform considers the null list and the empty list to be two separate values, in the same way that Go does. To ensure consistency, this commit explicitly transforms missing certificate filter lists into null lists in both directions (TF -> API and API -> TF). Fixes this issue: ``` │ Error: Provider produced inconsistent result after apply │ │ When applying changes to temporalcloud_namespace.terraform, provider "provider[\"registry.terraform.io/hashicorp/temporalcloud\"]" │ produced an unexpected new value: .certificate_filters: was null, but now │ cty.ListValEmpty(cty.Object(map[string]cty.Type{"common_name":cty.String, "organization":cty.String, │ "organizational_unit":cty.String, "subject_alternative_name":cty.String})). │ │ This is a bug in the provider, which should be reported in the provider's own issue tracker. ``` --- internal/provider/namespace_resource.go | 38 ++++++++----- internal/provider/namespace_resource_test.go | 57 ++++++++++++++++++-- 2 files changed, 78 insertions(+), 17 deletions(-) diff --git a/internal/provider/namespace_resource.go b/internal/provider/namespace_resource.go index e94156f..7ef849d 100644 --- a/internal/provider/namespace_resource.go +++ b/internal/provider/namespace_resource.go @@ -351,27 +351,33 @@ func updateModelFromSpec(ctx context.Context, diags diag.Diagnostics, state *nam return } - certificateFilterObjects := make([]types.Object, len(ns.GetSpec().GetMtlsAuth().GetCertificateFilters())) - for i, certFilter := range ns.GetSpec().GetMtlsAuth().GetCertificateFilters() { - model := namespaceCertificateFilterModel{ - CommonName: stringOrNull(certFilter.GetCommonName()), - Organization: stringOrNull(certFilter.GetOrganization()), - OrganizationalUnit: stringOrNull(certFilter.GetOrganizationalUnit()), - SubjectAlternativeName: stringOrNull(certFilter.GetSubjectAlternativeName()), + certificateFilter := types.ListNull(types.ObjectType{AttrTypes: namespaceCertificateFilterAttrs}) + if len(ns.GetSpec().GetMtlsAuth().GetCertificateFilters()) > 0 { + certificateFilterObjects := make([]types.Object, len(ns.GetSpec().GetMtlsAuth().GetCertificateFilters())) + for i, certFilter := range ns.GetSpec().GetMtlsAuth().GetCertificateFilters() { + model := namespaceCertificateFilterModel{ + CommonName: stringOrNull(certFilter.GetCommonName()), + Organization: stringOrNull(certFilter.GetOrganization()), + OrganizationalUnit: stringOrNull(certFilter.GetOrganizationalUnit()), + SubjectAlternativeName: stringOrNull(certFilter.GetSubjectAlternativeName()), + } + obj, diag := types.ObjectValueFrom(ctx, namespaceCertificateFilterAttrs, model) + diags.Append(diag...) + if diags.HasError() { + return + } + certificateFilterObjects[i] = obj } - obj, diag := types.ObjectValueFrom(ctx, namespaceCertificateFilterAttrs, model) + + filters, diag := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: namespaceCertificateFilterAttrs}, certificateFilterObjects) diags.Append(diag...) if diags.HasError() { return } - certificateFilterObjects[i] = obj - } - certificateFilter, diag := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: namespaceCertificateFilterAttrs}, certificateFilterObjects) - diags.Append(diag...) - if diags.HasError() { - return + certificateFilter = filters } + state.Regions = planRegions state.CertificateFilters = certificateFilter state.AcceptedClientCA = types.StringValue(ns.GetSpec().GetMtlsAuth().GetAcceptedClientCa()) @@ -386,6 +392,10 @@ func getCertFiltersFromModel(ctx context.Context, diags diag.Diagnostics, model return nil } + if len(elements) == 0 { + return nil + } + certificateFilters := make([]*namespacev1.CertificateFilterSpec, len(elements)) for i, filter := range elements { var model namespaceCertificateFilterModel diff --git a/internal/provider/namespace_resource_test.go b/internal/provider/namespace_resource_test.go index 85f9e39..a453795 100644 --- a/internal/provider/namespace_resource_test.go +++ b/internal/provider/namespace_resource_test.go @@ -8,13 +8,42 @@ import ( ) func TestAccBasicNamespace(t *testing.T) { + config := func(name string, retention int) string { + return fmt.Sprintf(` +provider "temporalcloud" { + +} + +resource "temporalcloud_namespace" "terraform" { + name = "%s" + regions = ["aws-us-east-1"] + accepted_client_ca = base64encode(<