Merge pull request #6252 from ctripcloud/svc-aggregate-status-dedup
Deduplicate and sort status for Service and Ingress when aggregating status
This commit is contained in:
commit
5ce16455bb
|
@ -147,6 +147,7 @@ func aggregateServiceStatus(object *unstructured.Unstructured, aggregatedStatusI
|
||||||
|
|
||||||
newStatus.LoadBalancer.Ingress = append(newStatus.LoadBalancer.Ingress, temp.LoadBalancer.Ingress...)
|
newStatus.LoadBalancer.Ingress = append(newStatus.LoadBalancer.Ingress, temp.LoadBalancer.Ingress...)
|
||||||
}
|
}
|
||||||
|
newStatus.LoadBalancer.Ingress = helper.DedupeAndSortServiceLoadBalancerIngress(newStatus.LoadBalancer.Ingress)
|
||||||
|
|
||||||
if reflect.DeepEqual(service.Status, *newStatus) {
|
if reflect.DeepEqual(service.Status, *newStatus) {
|
||||||
klog.V(3).Infof("Ignore update service(%s/%s) status as up to date", service.Namespace, service.Name)
|
klog.V(3).Infof("Ignore update service(%s/%s) status as up to date", service.Namespace, service.Name)
|
||||||
|
@ -179,6 +180,7 @@ func aggregateIngressStatus(object *unstructured.Unstructured, aggregatedStatusI
|
||||||
|
|
||||||
newStatus.LoadBalancer.Ingress = append(newStatus.LoadBalancer.Ingress, temp.LoadBalancer.Ingress...)
|
newStatus.LoadBalancer.Ingress = append(newStatus.LoadBalancer.Ingress, temp.LoadBalancer.Ingress...)
|
||||||
}
|
}
|
||||||
|
newStatus.LoadBalancer.Ingress = helper.DedupeAndSortIngressLoadBalancerIngress(newStatus.LoadBalancer.Ingress)
|
||||||
|
|
||||||
if reflect.DeepEqual(ingress.Status, *newStatus) {
|
if reflect.DeepEqual(ingress.Status, *newStatus) {
|
||||||
klog.V(3).Infof("Ignore update ingress(%s/%s) status as up to date", ingress.Namespace, ingress.Name)
|
klog.V(3).Infof("Ignore update ingress(%s/%s) status as up to date", ingress.Namespace, ingress.Name)
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Karmada Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DedupeAndSortIngressLoadBalancerIngress dedupes and sorts the IngressLoadBalancerIngress slice.
|
||||||
|
func DedupeAndSortIngressLoadBalancerIngress(ingresses []networkingv1.IngressLoadBalancerIngress) []networkingv1.IngressLoadBalancerIngress {
|
||||||
|
errMap := make(map[string]*string)
|
||||||
|
for _, ingress := range ingresses {
|
||||||
|
for j, port := range ingress.Ports {
|
||||||
|
if port.Error != nil {
|
||||||
|
// let same error use same ptr, to let *Error be comparable
|
||||||
|
if errMap[*port.Error] == nil {
|
||||||
|
errMap[*port.Error] = port.Error
|
||||||
|
} else {
|
||||||
|
ingress.Ports[j].Error = errMap[*port.Error]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ingressMap := make(map[string]*networkingv1.IngressLoadBalancerIngress)
|
||||||
|
portStatusMap := make(map[string]sets.Set[networkingv1.IngressPortStatus])
|
||||||
|
for _, ingress := range ingresses {
|
||||||
|
key := fmt.Sprintf("%s/%s", ingress.Hostname, ingress.IP)
|
||||||
|
if portStatusMap[key] == nil {
|
||||||
|
portStatusMap[key] = sets.New[networkingv1.IngressPortStatus]()
|
||||||
|
}
|
||||||
|
portStatusMap[key].Insert(ingress.Ports...)
|
||||||
|
ingress.Ports = nil
|
||||||
|
ingressMap[key] = &ingress
|
||||||
|
}
|
||||||
|
for key, portStatus := range portStatusMap {
|
||||||
|
for port := range portStatus {
|
||||||
|
ingressMap[key].Ports = append(ingressMap[key].Ports, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
sortIngressPortStatus(ingressMap[key].Ports)
|
||||||
|
}
|
||||||
|
out := make([]networkingv1.IngressLoadBalancerIngress, 0, len(ingressMap))
|
||||||
|
for _, v := range ingressMap {
|
||||||
|
out = append(out, *v)
|
||||||
|
}
|
||||||
|
|
||||||
|
sortIngressLoadBalancerIngress(out)
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortIngressPortStatus(ports []networkingv1.IngressPortStatus) {
|
||||||
|
sort.Slice(ports, func(i, j int) bool {
|
||||||
|
if ports[i].Port != ports[j].Port {
|
||||||
|
return ports[i].Port < ports[j].Port
|
||||||
|
}
|
||||||
|
|
||||||
|
if ports[i].Protocol != ports[j].Protocol {
|
||||||
|
return ports[i].Protocol < ports[j].Protocol
|
||||||
|
}
|
||||||
|
|
||||||
|
if ports[i].Error == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ports[j].Error == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return *ports[i].Error < *ports[j].Error
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortIngressLoadBalancerIngress(ingresses []networkingv1.IngressLoadBalancerIngress) {
|
||||||
|
sort.Slice(ingresses, func(i, j int) bool {
|
||||||
|
if ingresses[i].Hostname != ingresses[j].Hostname {
|
||||||
|
if ingresses[j].Hostname == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ingresses[i].Hostname == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return ingresses[i].Hostname < ingresses[j].Hostname
|
||||||
|
}
|
||||||
|
|
||||||
|
return ingresses[i].IP < ingresses[j].IP
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Karmada Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
|
"k8s.io/utils/ptr"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDedupeAndSortIngressLoadBalancerIngress(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
ingresses []networkingv1.IngressLoadBalancerIngress
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want []networkingv1.IngressLoadBalancerIngress
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "sort hostname",
|
||||||
|
args: args{
|
||||||
|
ingresses: []networkingv1.IngressLoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-2"},
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []networkingv1.IngressLoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
{Hostname: "hostname-2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "sort ip",
|
||||||
|
args: args{
|
||||||
|
ingresses: []networkingv1.IngressLoadBalancerIngress{
|
||||||
|
{IP: "2.2.2.2"},
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []networkingv1.IngressLoadBalancerIngress{
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
{IP: "2.2.2.2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "hostname should in front of ip",
|
||||||
|
args: args{
|
||||||
|
ingresses: []networkingv1.IngressLoadBalancerIngress{
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []networkingv1.IngressLoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "merge hostname and ip",
|
||||||
|
args: args{
|
||||||
|
ingresses: []networkingv1.IngressLoadBalancerIngress{
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []networkingv1.IngressLoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "merge and sort ports",
|
||||||
|
args: args{
|
||||||
|
ingresses: []networkingv1.IngressLoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1", Ports: []networkingv1.IngressPortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP"},
|
||||||
|
}},
|
||||||
|
{Hostname: "hostname-1", Ports: []networkingv1.IngressPortStatus{
|
||||||
|
{Port: 81, Protocol: "TCP"},
|
||||||
|
}},
|
||||||
|
{Hostname: "hostname-1", Ports: []networkingv1.IngressPortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []networkingv1.IngressLoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1", Ports: []networkingv1.IngressPortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP"},
|
||||||
|
{Port: 81, Protocol: "TCP"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "merge and sort errors",
|
||||||
|
args: args{
|
||||||
|
ingresses: []networkingv1.IngressLoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1", Ports: []networkingv1.IngressPortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP", Error: ptr.To("error-1")},
|
||||||
|
}},
|
||||||
|
{Hostname: "hostname-1", Ports: []networkingv1.IngressPortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP", Error: ptr.To("error-1")},
|
||||||
|
}},
|
||||||
|
{Hostname: "hostname-1", Ports: []networkingv1.IngressPortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP", Error: ptr.To("error-2")},
|
||||||
|
}},
|
||||||
|
{Hostname: "hostname-1", Ports: []networkingv1.IngressPortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []networkingv1.IngressLoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1", Ports: []networkingv1.IngressPortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP"},
|
||||||
|
{Port: 80, Protocol: "TCP", Error: ptr.To("error-1")},
|
||||||
|
{Port: 80, Protocol: "TCP", Error: ptr.To("error-2")},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
for i := 0; i < 1000; i++ { // eliminate randomness in sorting
|
||||||
|
pass := assert.Equalf(t, tt.want, DedupeAndSortIngressLoadBalancerIngress(tt.args.ingresses), "DedupeAndSortIngressLoadBalancerIngress(%v)", tt.args.ingresses)
|
||||||
|
if !pass {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Karmada Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DedupeAndSortServiceLoadBalancerIngress dedupes and sorts the ServiceLoadBalancerIngress slice.
|
||||||
|
func DedupeAndSortServiceLoadBalancerIngress(ingresses []corev1.LoadBalancerIngress) []corev1.LoadBalancerIngress {
|
||||||
|
ipModeMap := make(map[corev1.LoadBalancerIPMode]*corev1.LoadBalancerIPMode)
|
||||||
|
errMap := make(map[string]*string)
|
||||||
|
for i, ingress := range ingresses {
|
||||||
|
if ingress.IPMode != nil {
|
||||||
|
// let same IPMode use same ptr, to let *IPMode be comparable
|
||||||
|
if ipModeMap[*ingress.IPMode] == nil {
|
||||||
|
ipModeMap[*ingress.IPMode] = ingress.IPMode
|
||||||
|
} else {
|
||||||
|
ingresses[i].IPMode = ipModeMap[*ingress.IPMode]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for j, port := range ingress.Ports {
|
||||||
|
if port.Error != nil {
|
||||||
|
// let same error use same ptr, to let *Error be comparable
|
||||||
|
if errMap[*port.Error] == nil {
|
||||||
|
errMap[*port.Error] = port.Error
|
||||||
|
} else {
|
||||||
|
ingress.Ports[j].Error = errMap[*port.Error]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ingressMap := make(map[string]*corev1.LoadBalancerIngress)
|
||||||
|
portStatusMap := make(map[string]sets.Set[corev1.PortStatus])
|
||||||
|
for _, ingress := range ingresses {
|
||||||
|
key := fmt.Sprintf("%s/%s/%p", ingress.Hostname, ingress.IP, ingress.IPMode)
|
||||||
|
if portStatusMap[key] == nil {
|
||||||
|
portStatusMap[key] = sets.New[corev1.PortStatus]()
|
||||||
|
}
|
||||||
|
portStatusMap[key].Insert(ingress.Ports...)
|
||||||
|
ingress.Ports = nil
|
||||||
|
ingressMap[key] = &ingress
|
||||||
|
}
|
||||||
|
for key, portStatus := range portStatusMap {
|
||||||
|
for port := range portStatus {
|
||||||
|
ingressMap[key].Ports = append(ingressMap[key].Ports, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
sortServicePortStatus(ingressMap[key].Ports)
|
||||||
|
}
|
||||||
|
out := make([]corev1.LoadBalancerIngress, 0, len(ingressMap))
|
||||||
|
for _, v := range ingressMap {
|
||||||
|
out = append(out, *v)
|
||||||
|
}
|
||||||
|
|
||||||
|
sortServiceLoadBalancerIngress(out)
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortServicePortStatus(ports []corev1.PortStatus) {
|
||||||
|
sort.Slice(ports, func(i, j int) bool {
|
||||||
|
if ports[i].Port != ports[j].Port {
|
||||||
|
return ports[i].Port < ports[j].Port
|
||||||
|
}
|
||||||
|
|
||||||
|
if ports[i].Protocol != ports[j].Protocol {
|
||||||
|
return ports[i].Protocol < ports[j].Protocol
|
||||||
|
}
|
||||||
|
|
||||||
|
if ports[i].Error == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ports[j].Error == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return *ports[i].Error < *ports[j].Error
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortServiceLoadBalancerIngress(ingresses []corev1.LoadBalancerIngress) {
|
||||||
|
sort.Slice(ingresses, func(i, j int) bool {
|
||||||
|
if ingresses[i].Hostname != ingresses[j].Hostname {
|
||||||
|
if ingresses[j].Hostname == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ingresses[i].Hostname == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return ingresses[i].Hostname < ingresses[j].Hostname
|
||||||
|
}
|
||||||
|
|
||||||
|
if ingresses[i].IP != ingresses[j].IP {
|
||||||
|
return ingresses[i].IP < ingresses[j].IP
|
||||||
|
}
|
||||||
|
|
||||||
|
if ingresses[j].IPMode == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ingresses[i].IPMode == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return *ingresses[i].IPMode < *ingresses[j].IPMode
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,176 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Karmada Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/utils/ptr"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDedupeAndSortServiceLoadBalancerIngress(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
ingresses []corev1.LoadBalancerIngress
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want []corev1.LoadBalancerIngress
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "sort hostname",
|
||||||
|
args: args{
|
||||||
|
ingresses: []corev1.LoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-2"},
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []corev1.LoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
{Hostname: "hostname-2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "sort ip",
|
||||||
|
args: args{
|
||||||
|
ingresses: []corev1.LoadBalancerIngress{
|
||||||
|
{IP: "2.2.2.2"},
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []corev1.LoadBalancerIngress{
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
{IP: "2.2.2.2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "hostname should in front of ip",
|
||||||
|
args: args{
|
||||||
|
ingresses: []corev1.LoadBalancerIngress{
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []corev1.LoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "sort ipMode",
|
||||||
|
args: args{
|
||||||
|
ingresses: []corev1.LoadBalancerIngress{
|
||||||
|
{IP: "1.1.1.1", IPMode: ptr.To(corev1.LoadBalancerIPModeProxy)},
|
||||||
|
{IP: "1.1.1.1", IPMode: ptr.To(corev1.LoadBalancerIPModeVIP)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []corev1.LoadBalancerIngress{
|
||||||
|
{IP: "1.1.1.1", IPMode: ptr.To(corev1.LoadBalancerIPModeProxy)},
|
||||||
|
{IP: "1.1.1.1", IPMode: ptr.To(corev1.LoadBalancerIPModeVIP)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "merge ipMode",
|
||||||
|
args: args{
|
||||||
|
ingresses: []corev1.LoadBalancerIngress{
|
||||||
|
{IP: "1.1.1.1", IPMode: ptr.To(corev1.LoadBalancerIPModeVIP)},
|
||||||
|
{IP: "1.1.1.1", IPMode: ptr.To(corev1.LoadBalancerIPModeVIP)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []corev1.LoadBalancerIngress{
|
||||||
|
{IP: "1.1.1.1", IPMode: ptr.To(corev1.LoadBalancerIPModeVIP)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "merge hostname and ip",
|
||||||
|
args: args{
|
||||||
|
ingresses: []corev1.LoadBalancerIngress{
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []corev1.LoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1"},
|
||||||
|
{IP: "1.1.1.1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "merge and sort ports",
|
||||||
|
args: args{
|
||||||
|
ingresses: []corev1.LoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1", Ports: []corev1.PortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP"},
|
||||||
|
}},
|
||||||
|
{Hostname: "hostname-1", Ports: []corev1.PortStatus{
|
||||||
|
{Port: 81, Protocol: "TCP"},
|
||||||
|
}},
|
||||||
|
{Hostname: "hostname-1", Ports: []corev1.PortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []corev1.LoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1", Ports: []corev1.PortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP"},
|
||||||
|
{Port: 81, Protocol: "TCP"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "merge and sort errors",
|
||||||
|
args: args{
|
||||||
|
ingresses: []corev1.LoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1", Ports: []corev1.PortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP", Error: ptr.To("error-1")},
|
||||||
|
}},
|
||||||
|
{Hostname: "hostname-1", Ports: []corev1.PortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP", Error: ptr.To("error-1")},
|
||||||
|
}},
|
||||||
|
{Hostname: "hostname-1", Ports: []corev1.PortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP", Error: ptr.To("error-2")},
|
||||||
|
}},
|
||||||
|
{Hostname: "hostname-1", Ports: []corev1.PortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []corev1.LoadBalancerIngress{
|
||||||
|
{Hostname: "hostname-1", Ports: []corev1.PortStatus{
|
||||||
|
{Port: 80, Protocol: "TCP"},
|
||||||
|
{Port: 80, Protocol: "TCP", Error: ptr.To("error-1")},
|
||||||
|
{Port: 80, Protocol: "TCP", Error: ptr.To("error-2")},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
for i := 0; i < 1000; i++ { // eliminate randomness in sorting
|
||||||
|
pass := assert.Equalf(t, tt.want, DedupeAndSortServiceLoadBalancerIngress(tt.args.ingresses), "DedupeAndSortServiceLoadBalancerIngress(%v)", tt.args.ingresses)
|
||||||
|
if !pass {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue