diff --git a/Dockerfile b/Dockerfile index 03a064bd63..2cffa6bbed 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ # limitations under the License. # Build the manager binary -FROM golang:1.20.10 as builder +FROM golang:1.21.6 as builder WORKDIR /workspace # Run this with docker build --build_arg goproxy=$(go env GOPROXY) to override the goproxy diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go index 75e2201779..00730d673e 100644 --- a/pkg/cloud/services/loadbalancer/loadbalancer.go +++ b/pkg/cloud/services/loadbalancer/loadbalancer.go @@ -19,7 +19,7 @@ package loadbalancer import ( "errors" "fmt" - "reflect" + "slices" "time" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners" @@ -275,11 +275,11 @@ func (s *Service) getOrUpdateAllowedCIDRS(openStackCluster *infrav1.OpenStackClu // Validate CIDRs and convert any given IP into a CIDR. allowedCIDRs = validateIPs(openStackCluster, allowedCIDRs) - // Remove duplicates. - allowedCIDRs = capostrings.Unique(allowedCIDRs) - listener.AllowedCIDRs = capostrings.Unique(listener.AllowedCIDRs) + // Sort and remove duplicates + allowedCIDRs = capostrings.Canonicalize(allowedCIDRs) + listener.AllowedCIDRs = capostrings.Canonicalize(listener.AllowedCIDRs) - if !reflect.DeepEqual(allowedCIDRs, listener.AllowedCIDRs) { + if !slices.Equal(allowedCIDRs, listener.AllowedCIDRs) { s.scope.Logger().Info("CIDRs do not match, updating listener", "expectedCIDRs", allowedCIDRs, "currentCIDRs", listener.AllowedCIDRs) listenerUpdateOpts := listeners.UpdateOpts{ AllowedCIDRs: &allowedCIDRs, diff --git a/pkg/utils/strings/strings.go b/pkg/utils/strings/strings.go index 6db532e1d8..ec97911fe2 100644 --- a/pkg/utils/strings/strings.go +++ b/pkg/utils/strings/strings.go @@ -16,14 +16,12 @@ limitations under the License. package strings -func Unique(s []string) []string { - inResult := make(map[string]bool) - var result []string - for _, str := range s { - if _, ok := inResult[str]; !ok { - inResult[str] = true - result = append(result, str) - } - } - return result +import ( + "cmp" + "slices" +) + +func Canonicalize[S ~[]E, E cmp.Ordered](s S) S { + slices.Sort(s) + return slices.Compact(s) } diff --git a/pkg/utils/strings/strings_test.go b/pkg/utils/strings/strings_test.go new file mode 100644 index 0000000000..7502f060ad --- /dev/null +++ b/pkg/utils/strings/strings_test.go @@ -0,0 +1,60 @@ +/* +Copyright 2024 The Kubernetes 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 strings + +import ( + "slices" + "testing" +) + +func TestCanonicalize(t *testing.T) { + tests := []struct { + name string + value []string + want []string + }{ + { + name: "Empty list", + value: []string{}, + want: []string{}, + }, + { + name: "Identity", + value: []string{"a", "b", "c"}, + want: []string{"a", "b", "c"}, + }, + { + name: "Out of order", + value: []string{"c", "b", "a"}, + want: []string{"a", "b", "c"}, + }, + { + name: "Duplicate elements", + value: []string{"c", "b", "a", "c"}, + want: []string{"a", "b", "c"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := Canonicalize(tt.value) + if !slices.Equal(got, tt.want) { + t.Errorf("CompareLists() = %v, want %v", got, tt.want) + } + }) + } +}