From 2d6534f9e97a559e3e5113e0e432a80b0a95ed53 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Fri, 1 Dec 2023 11:49:34 -0500 Subject: [PATCH] [1.1.x] Normalize partitions during CRD camparison. --- .changelog/3296.txt | 3 +++ .../api/v1alpha1/exportedservices_types.go | 12 +++++++++-- .../v1alpha1/exportedservices_types_test.go | 6 ++++-- .../api/v1alpha1/ingressgateway_types.go | 18 +++++++++++++--- .../api/v1alpha1/ingressgateway_types_test.go | 4 ++-- .../api/v1alpha1/servicedefaults_types.go | 17 ++++++++++++--- .../v1alpha1/servicedefaults_types_test.go | 4 ++-- .../api/v1alpha1/serviceresolver_types.go | 21 +++++++++++++++++-- .../v1alpha1/serviceresolver_types_test.go | 6 +++++- .../api/v1alpha1/servicerouter_types.go | 17 ++++++++++++--- .../api/v1alpha1/servicerouter_types_test.go | 4 +++- .../api/v1alpha1/servicesplitter_types.go | 15 +++++++++++-- .../v1alpha1/servicesplitter_types_test.go | 4 +++- 13 files changed, 107 insertions(+), 24 deletions(-) create mode 100644 .changelog/3296.txt diff --git a/.changelog/3296.txt b/.changelog/3296.txt new file mode 100644 index 0000000000..2ed983ed06 --- /dev/null +++ b/.changelog/3296.txt @@ -0,0 +1,3 @@ +```release-note:bug-fix +control-plane: normalize the `partition` and `namespace` fields in V1 CRDs when comparing with saved version of the config-entry. +``` \ No newline at end of file diff --git a/control-plane/api/v1alpha1/exportedservices_types.go b/control-plane/api/v1alpha1/exportedservices_types.go index e05f17a177..5c21e67d4d 100644 --- a/control-plane/api/v1alpha1/exportedservices_types.go +++ b/control-plane/api/v1alpha1/exportedservices_types.go @@ -5,7 +5,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/hashicorp/consul-k8s/control-plane/api/common" "github.com/hashicorp/consul/api" capi "github.com/hashicorp/consul/api" corev1 "k8s.io/api/core/v1" @@ -13,6 +12,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" + + "github.com/hashicorp/consul-k8s/control-plane/api/common" ) const ExportedServicesKubeKind = "exportedservices" @@ -182,8 +183,15 @@ func (in *ExportedServices) MatchesConsul(candidate api.ConfigEntry) bool { if !ok { return false } + + specialEquality := cmp.Options{ + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Services.Consumers.Partition" + }, cmp.Transformer("NormalizePartition", normalizeEmptyToDefault)), + } + // No datacenter is passed to ToConsul as we ignore the Meta field when checking for equality. - return cmp.Equal(in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.ExportedServicesConfigEntry{}, "Partition", "Meta", "ModifyIndex", "CreateIndex"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty()) + return cmp.Equal(in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.ExportedServicesConfigEntry{}, "Partition", "Meta", "ModifyIndex", "CreateIndex"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty(), specialEquality) } diff --git a/control-plane/api/v1alpha1/exportedservices_types_test.go b/control-plane/api/v1alpha1/exportedservices_types_test.go index 8826166a76..98d6fa2e6f 100644 --- a/control-plane/api/v1alpha1/exportedservices_types_test.go +++ b/control-plane/api/v1alpha1/exportedservices_types_test.go @@ -4,11 +4,12 @@ import ( "testing" "time" - "github.com/hashicorp/consul-k8s/control-plane/api/common" capi "github.com/hashicorp/consul/api" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/hashicorp/consul-k8s/control-plane/api/common" ) // Test MatchesConsul for cases that should return true. @@ -105,7 +106,8 @@ func TestExportedServices_MatchesConsul(t *testing.T) { Partition: "fifth", }, { - Peer: "third-peer", + Peer: "third-peer", + Partition: "default", }, }, }, diff --git a/control-plane/api/v1alpha1/ingressgateway_types.go b/control-plane/api/v1alpha1/ingressgateway_types.go index fde3cdd4e5..42e18c0f8e 100644 --- a/control-plane/api/v1alpha1/ingressgateway_types.go +++ b/control-plane/api/v1alpha1/ingressgateway_types.go @@ -3,16 +3,18 @@ package v1alpha1 import ( "encoding/json" "fmt" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/hashicorp/consul-k8s/control-plane/api/common" - "github.com/hashicorp/consul-k8s/control-plane/namespaces" capi "github.com/hashicorp/consul/api" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" + + "github.com/hashicorp/consul-k8s/control-plane/api/common" + "github.com/hashicorp/consul-k8s/control-plane/namespaces" ) const ( @@ -265,8 +267,18 @@ func (in *IngressGateway) MatchesConsul(candidate capi.ConfigEntry) bool { if !ok { return false } + + specialEquality := cmp.Options{ + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Listeners.Services.Namespace" + }, cmp.Transformer("NormalizeNamespace", normalizeEmptyToDefault)), + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Listeners.Services.Partition" + }, cmp.Transformer("NormalizePartition", normalizeEmptyToDefault)), + } + // No datacenter is passed to ToConsul as we ignore the Meta field when checking for equality. - return cmp.Equal(in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.IngressGatewayConfigEntry{}, "Partition", "Namespace", "Meta", "ModifyIndex", "CreateIndex"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty()) + return cmp.Equal(in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.IngressGatewayConfigEntry{}, "Partition", "Namespace", "Meta", "ModifyIndex", "CreateIndex"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty(), specialEquality) } func (in *IngressGateway) Validate(consulMeta common.ConsulMeta) error { diff --git a/control-plane/api/v1alpha1/ingressgateway_types_test.go b/control-plane/api/v1alpha1/ingressgateway_types_test.go index 37a23ff678..0863776578 100644 --- a/control-plane/api/v1alpha1/ingressgateway_types_test.go +++ b/control-plane/api/v1alpha1/ingressgateway_types_test.go @@ -5,12 +5,13 @@ import ( "time" "github.com/google/go-cmp/cmp" - "github.com/hashicorp/consul-k8s/control-plane/api/common" capi "github.com/hashicorp/consul/api" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/pointer" + + "github.com/hashicorp/consul-k8s/control-plane/api/common" ) func TestIngressGateway_MatchesConsul(t *testing.T) { @@ -99,7 +100,6 @@ func TestIngressGateway_MatchesConsul(t *testing.T) { Name: "name1", Hosts: []string{"host1_1", "host1_2"}, Namespace: "ns1", - Partition: "default", IngressServiceConfig: IngressServiceConfig{ MaxConnections: &maxConnections, MaxPendingRequests: &maxPendingRequests, diff --git a/control-plane/api/v1alpha1/servicedefaults_types.go b/control-plane/api/v1alpha1/servicedefaults_types.go index 97a549a606..b5a09db858 100644 --- a/control-plane/api/v1alpha1/servicedefaults_types.go +++ b/control-plane/api/v1alpha1/servicedefaults_types.go @@ -8,7 +8,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/hashicorp/consul-k8s/control-plane/api/common" capi "github.com/hashicorp/consul/api" "github.com/miekg/dns" corev1 "k8s.io/api/core/v1" @@ -16,6 +15,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" + + "github.com/hashicorp/consul-k8s/control-plane/api/common" ) const ( @@ -534,9 +535,19 @@ func (in *ServiceDefaults) MatchesConsul(candidate capi.ConfigEntry) bool { if !ok { return false } + + specialEquality := cmp.Options{ + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "UpstreamConfig.Overrides.Namespace" + }, cmp.Transformer("NormalizeNamespace", normalizeEmptyToDefault)), + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "UpstreamConfig.Overrides.Partition" + }, cmp.Transformer("NormalizePartition", normalizeEmptyToDefault)), + cmp.Comparer(transparentProxyConfigComparer), + } + // No datacenter is passed to ToConsul as we ignore the Meta field when checking for equality. - return cmp.Equal(in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.ServiceConfigEntry{}, "Partition", "Namespace", "Meta", "ModifyIndex", "CreateIndex"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty(), - cmp.Comparer(transparentProxyConfigComparer)) + return cmp.Equal(in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.ServiceConfigEntry{}, "Partition", "Namespace", "Meta", "ModifyIndex", "CreateIndex"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty(), specialEquality) } func (in *ServiceDefaults) ConsulGlobalResource() bool { diff --git a/control-plane/api/v1alpha1/servicedefaults_types_test.go b/control-plane/api/v1alpha1/servicedefaults_types_test.go index 05f1bdd3d9..a48b2499bc 100644 --- a/control-plane/api/v1alpha1/servicedefaults_types_test.go +++ b/control-plane/api/v1alpha1/servicedefaults_types_test.go @@ -525,7 +525,6 @@ func TestServiceDefaults_MatchesConsul(t *testing.T) { }, { Name: "upstream-default", - Namespace: "ns", EnvoyListenerJSON: `{"key": "value"}`, EnvoyClusterJSON: `{"key": "value"}`, Protocol: "http2", @@ -649,7 +648,8 @@ func TestServiceDefaults_MatchesConsul(t *testing.T) { }, { Name: "upstream-default", - Namespace: "ns", + Namespace: "default", + Partition: "default", EnvoyListenerJSON: `{"key": "value"}`, EnvoyClusterJSON: `{"key": "value"}`, Protocol: "http2", diff --git a/control-plane/api/v1alpha1/serviceresolver_types.go b/control-plane/api/v1alpha1/serviceresolver_types.go index fc5c952ed7..b8284d4e5f 100644 --- a/control-plane/api/v1alpha1/serviceresolver_types.go +++ b/control-plane/api/v1alpha1/serviceresolver_types.go @@ -5,15 +5,17 @@ package v1alpha1 import ( "encoding/json" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/hashicorp/consul-k8s/control-plane/api/common" capi "github.com/hashicorp/consul/api" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" + + "github.com/hashicorp/consul-k8s/control-plane/api/common" ) const ServiceResolverKubeKind string = "serviceresolver" @@ -311,8 +313,23 @@ func (in *ServiceResolver) MatchesConsul(candidate capi.ConfigEntry) bool { if !ok { return false } + + specialEquality := cmp.Options{ + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Redirect.Namespace" + }, cmp.Transformer("NormalizeNamespace", normalizeEmptyToDefault)), + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Redirect.Partition" + }, cmp.Transformer("NormalizePartition", normalizeEmptyToDefault)), + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Failover.Targets.Namespace" + }, cmp.Transformer("NormalizeNamespace", normalizeEmptyToDefault)), + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Failover.Targets.Partition" + }, cmp.Transformer("NormalizePartition", normalizeEmptyToDefault)), + } // No datacenter is passed to ToConsul as we ignore the Meta field when checking for equality. - return cmp.Equal(in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.ServiceResolverConfigEntry{}, "Partition", "Namespace", "Meta", "ModifyIndex", "CreateIndex"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty()) + return cmp.Equal(in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.ServiceResolverConfigEntry{}, "Partition", "Namespace", "Meta", "ModifyIndex", "CreateIndex"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty(), specialEquality) } func (in *ServiceResolver) ConsulGlobalResource() bool { diff --git a/control-plane/api/v1alpha1/serviceresolver_types_test.go b/control-plane/api/v1alpha1/serviceresolver_types_test.go index e216add619..71047c091a 100644 --- a/control-plane/api/v1alpha1/serviceresolver_types_test.go +++ b/control-plane/api/v1alpha1/serviceresolver_types_test.go @@ -4,11 +4,12 @@ import ( "testing" "time" - "github.com/hashicorp/consul-k8s/control-plane/api/common" capi "github.com/hashicorp/consul/api" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/hashicorp/consul-k8s/control-plane/api/common" ) func TestServiceResolver_MatchesConsul(t *testing.T) { @@ -78,6 +79,7 @@ func TestServiceResolver_MatchesConsul(t *testing.T) { Targets: []ServiceResolverFailoverTarget{ {Peer: "failover_peer3"}, {Partition: "failover_partition3", Namespace: "failover_namespace3"}, + {Peer: "failover_peer4"}, }, }, }, @@ -126,6 +128,7 @@ func TestServiceResolver_MatchesConsul(t *testing.T) { Service: "redirect", ServiceSubset: "redirect_subset", Namespace: "redirect_namespace", + Partition: "default", Datacenter: "redirect_datacenter", Peer: "redirect_peer", }, @@ -146,6 +149,7 @@ func TestServiceResolver_MatchesConsul(t *testing.T) { Targets: []capi.ServiceResolverFailoverTarget{ {Peer: "failover_peer3"}, {Partition: "failover_partition3", Namespace: "failover_namespace3"}, + {Partition: "default", Peer: "failover_peer4"}, }, }, }, diff --git a/control-plane/api/v1alpha1/servicerouter_types.go b/control-plane/api/v1alpha1/servicerouter_types.go index 931d5ccb3a..ffc5dea03b 100644 --- a/control-plane/api/v1alpha1/servicerouter_types.go +++ b/control-plane/api/v1alpha1/servicerouter_types.go @@ -5,14 +5,15 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/hashicorp/consul-k8s/control-plane/api/common" - "github.com/hashicorp/consul-k8s/control-plane/namespaces" capi "github.com/hashicorp/consul/api" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" + + "github.com/hashicorp/consul-k8s/control-plane/api/common" + "github.com/hashicorp/consul-k8s/control-plane/namespaces" ) func init() { @@ -250,8 +251,18 @@ func (in *ServiceRouter) MatchesConsul(candidate capi.ConfigEntry) bool { if !ok { return false } + + specialEquality := cmp.Options{ + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Routes.Destination.Namespace" + }, cmp.Transformer("NormalizeNamespace", normalizeEmptyToDefault)), + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Routes.Destination.Partition" + }, cmp.Transformer("NormalizePartition", normalizeEmptyToDefault)), + } + // No datacenter is passed to ToConsul as we ignore the Meta field when checking for equality. - return cmp.Equal(in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.ServiceRouterConfigEntry{}, "Partition", "Namespace", "Meta", "ModifyIndex", "CreateIndex"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty()) + return cmp.Equal(in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.ServiceRouterConfigEntry{}, "Partition", "Namespace", "Meta", "ModifyIndex", "CreateIndex"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty(), specialEquality) } func (in *ServiceRouter) Validate(consulMeta common.ConsulMeta) error { diff --git a/control-plane/api/v1alpha1/servicerouter_types_test.go b/control-plane/api/v1alpha1/servicerouter_types_test.go index 3110922210..e6ffe20aca 100644 --- a/control-plane/api/v1alpha1/servicerouter_types_test.go +++ b/control-plane/api/v1alpha1/servicerouter_types_test.go @@ -5,11 +5,12 @@ import ( "time" "github.com/google/go-cmp/cmp" - "github.com/hashicorp/consul-k8s/control-plane/api/common" capi "github.com/hashicorp/consul/api" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/hashicorp/consul-k8s/control-plane/api/common" ) // Test MatchesConsul. @@ -155,6 +156,7 @@ func TestServiceRouter_MatchesConsul(t *testing.T) { Service: "service", ServiceSubset: "serviceSubset", Namespace: "namespace", + Partition: "default", PrefixRewrite: "prefixRewrite", IdleTimeout: 1 * time.Second, RequestTimeout: 1 * time.Second, diff --git a/control-plane/api/v1alpha1/servicesplitter_types.go b/control-plane/api/v1alpha1/servicesplitter_types.go index b61b1a320b..5c91d080a6 100644 --- a/control-plane/api/v1alpha1/servicesplitter_types.go +++ b/control-plane/api/v1alpha1/servicesplitter_types.go @@ -6,13 +6,14 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/hashicorp/consul-k8s/control-plane/api/common" capi "github.com/hashicorp/consul/api" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" + + "github.com/hashicorp/consul-k8s/control-plane/api/common" ) func init() { @@ -165,8 +166,18 @@ func (in *ServiceSplitter) MatchesConsul(candidate capi.ConfigEntry) bool { if !ok { return false } + + specialEquality := cmp.Options{ + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Splits.Namespace" + }, cmp.Transformer("NormalizeNamespace", normalizeEmptyToDefault)), + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Splits.Partition" + }, cmp.Transformer("NormalizePartition", normalizeEmptyToDefault)), + } + // No datacenter is passed to ToConsul as we ignore the Meta field when checking for equality. - return cmp.Equal(in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.ServiceSplitterConfigEntry{}, "Partition", "Namespace", "Meta", "ModifyIndex", "CreateIndex"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty()) + return cmp.Equal(in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.ServiceSplitterConfigEntry{}, "Partition", "Namespace", "Meta", "ModifyIndex", "CreateIndex"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty(), specialEquality) } func (in *ServiceSplitter) Validate(consulMeta common.ConsulMeta) error { diff --git a/control-plane/api/v1alpha1/servicesplitter_types_test.go b/control-plane/api/v1alpha1/servicesplitter_types_test.go index 48e9eeac54..84c416b5ff 100644 --- a/control-plane/api/v1alpha1/servicesplitter_types_test.go +++ b/control-plane/api/v1alpha1/servicesplitter_types_test.go @@ -4,11 +4,12 @@ import ( "testing" "time" - "github.com/hashicorp/consul-k8s/control-plane/api/common" capi "github.com/hashicorp/consul/api" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/hashicorp/consul-k8s/control-plane/api/common" ) // Test MatchesConsul. @@ -93,6 +94,7 @@ func TestServiceSplitter_MatchesConsul(t *testing.T) { Service: "foo", ServiceSubset: "bar", Namespace: "baz", + Partition: "default", RequestHeaders: &capi.HTTPHeaderModifiers{ Add: map[string]string{ "foo": "bar",