Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 0 additions & 80 deletions internal/cmd/agent/deployer/internal/diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ import (
"errors"
"fmt"
"reflect"
"sort"

jsonpatch "github.com/evanphx/json-patch"

corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/jsonmergepatch"
Expand Down Expand Up @@ -425,8 +423,6 @@ func Normalize(un *unstructured.Unstructured, opts ...Option) {
normalizeRole(un, o)
} else if gvk.Group == "" && gvk.Kind == "Endpoints" {
normalizeEndpoint(un, o)
} else if gvk.Group == "discovery.k8s.io" && gvk.Kind == "EndpointSlice" {
normalizeEndpointSlice(un, o)
}

err := o.normalizer.Normalize(un)
Expand Down Expand Up @@ -521,82 +517,6 @@ func normalizeEndpoint(un *unstructured.Unstructured, o options) {
un.Object = newObj
}

// normalizeEndpointSlice normalizes EndpointSlice by sorting endpoints and ports lexicographically
// and setting default protocols. EndpointSlice is the successor to the deprecated Endpoints API.
func normalizeEndpointSlice(un *unstructured.Unstructured, o options) {
if un == nil {
return
}
gvk := un.GroupVersionKind()
if gvk.Group != "discovery.k8s.io" || gvk.Kind != "EndpointSlice" {
return
}

var eps discoveryv1.EndpointSlice
err := runtime.DefaultUnstructuredConverter.FromUnstructured(un.Object, &eps)
if err != nil {
o.log.Error(err, "Failed to convert from unstructured into EndpointSlice")
return
}

// add default protocol to ports if it is empty
for p, port := range eps.Ports {
if port.Protocol == nil {
tcp := corev1.ProtocolTCP
port.Protocol = &tcp
eps.Ports[p] = port
}
}

// Sort endpoints by their addresses for consistent comparison
sortEndpointSliceEndpoints(eps.Endpoints)
sortEndpointSlicePorts(eps.Ports)

newObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&eps)
if err != nil {
o.log.Info(fmt.Sprintf(couldNotMarshalErrMsg, gvk, err))
return
}
un.Object = newObj
}

// sortEndpointSliceEndpoints sorts EndpointSlice endpoints by their addresses
func sortEndpointSliceEndpoints(endpoints []discoveryv1.Endpoint) {
sort.Slice(endpoints, func(i, j int) bool {
// Sort by first address if available
if len(endpoints[i].Addresses) > 0 && len(endpoints[j].Addresses) > 0 {
addrCmp := bytes.Compare([]byte(endpoints[i].Addresses[0]), []byte(endpoints[j].Addresses[0]))
if addrCmp != 0 {
return addrCmp < 0
}
}
// Sort by target ref if available
if endpoints[i].TargetRef != nil && endpoints[j].TargetRef != nil {
return endpoints[i].TargetRef.UID < endpoints[j].TargetRef.UID
}
return false
})
}

// sortEndpointSlicePorts sorts EndpointSlice ports by port number and protocol
func sortEndpointSlicePorts(ports []discoveryv1.EndpointPort) {
sort.Slice(ports, func(i, j int) bool {
// Compare by port number first
if ports[i].Port != nil && ports[j].Port != nil && *ports[i].Port != *ports[j].Port {
return *ports[i].Port < *ports[j].Port
}
// Then by name
if ports[i].Name != nil && ports[j].Name != nil && *ports[i].Name != *ports[j].Name {
return *ports[i].Name < *ports[j].Name
}
// Then by protocol
if ports[i].Protocol != nil && ports[j].Protocol != nil {
return *ports[i].Protocol < *ports[j].Protocol
}
return false
})
}

// normalizeRole mutates the supplied Role/ClusterRole and sets rules to null if it is an empty list or an aggregated role
func normalizeRole(un *unstructured.Unstructured, o options) {
if un == nil {
Expand Down