From 11e322186bfd215bf728b4f952c497098d2cea37 Mon Sep 17 00:00:00 2001 From: Mikhail Mazurskiy <126021+ash2k@users.noreply.github.com> Date: Wed, 21 Apr 2021 03:54:02 +1000 Subject: [PATCH] refactor: reduce usage of k8s.io/kubernetes packages (#258) Signed-off-by: Mikhail Mazurskiy --- go.mod | 1 + .../pkg/api/v1/endpoints/util.go | 90 +++++++++++++++++++ .../kubernetes_vendor/pkg/util/hash/hash.go | 37 ++++++++ pkg/diff/diff.go | 2 +- pkg/health/health_pod.go | 4 +- 5 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 internal/kubernetes_vendor/pkg/api/v1/endpoints/util.go create mode 100644 internal/kubernetes_vendor/pkg/util/hash/hash.go diff --git a/go.mod b/go.mod index ffad4d4f2..9575ca06e 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/argoproj/gitops-engine go 1.15 require ( + github.com/davecgh/go-spew v1.1.1 github.com/evanphx/json-patch v4.9.0+incompatible github.com/go-logr/logr v0.3.0 github.com/golang/mock v1.4.4 diff --git a/internal/kubernetes_vendor/pkg/api/v1/endpoints/util.go b/internal/kubernetes_vendor/pkg/api/v1/endpoints/util.go new file mode 100644 index 000000000..58b7c1333 --- /dev/null +++ b/internal/kubernetes_vendor/pkg/api/v1/endpoints/util.go @@ -0,0 +1,90 @@ +/* +Copyright 2015 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 endpoints + +import ( + "bytes" + "crypto/md5" + "hash" + "sort" + + hashutil "github.com/argoproj/gitops-engine/internal/kubernetes_vendor/pkg/util/hash" + v1 "k8s.io/api/core/v1" +) + +// LessEndpointAddress compares IP addresses lexicographically and returns true if first argument is lesser than second +func LessEndpointAddress(a, b *v1.EndpointAddress) bool { + ipComparison := bytes.Compare([]byte(a.IP), []byte(b.IP)) + if ipComparison != 0 { + return ipComparison < 0 + } + if b.TargetRef == nil { + return false + } + if a.TargetRef == nil { + return true + } + return a.TargetRef.UID < b.TargetRef.UID +} + +// SortSubsets sorts an array of EndpointSubset objects in place. For ease of +// use it returns the input slice. +func SortSubsets(subsets []v1.EndpointSubset) []v1.EndpointSubset { + for i := range subsets { + ss := &subsets[i] + sort.Sort(addrsByIPAndUID(ss.Addresses)) + sort.Sort(addrsByIPAndUID(ss.NotReadyAddresses)) + sort.Sort(portsByHash(ss.Ports)) + } + sort.Sort(subsetsByHash(subsets)) + return subsets +} + +func hashObject(hasher hash.Hash, obj interface{}) []byte { + hashutil.DeepHashObject(hasher, obj) + return hasher.Sum(nil) +} + +type subsetsByHash []v1.EndpointSubset + +func (sl subsetsByHash) Len() int { return len(sl) } +func (sl subsetsByHash) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] } +func (sl subsetsByHash) Less(i, j int) bool { + hasher := md5.New() + h1 := hashObject(hasher, sl[i]) + h2 := hashObject(hasher, sl[j]) + return bytes.Compare(h1, h2) < 0 +} + +type addrsByIPAndUID []v1.EndpointAddress + +func (sl addrsByIPAndUID) Len() int { return len(sl) } +func (sl addrsByIPAndUID) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] } +func (sl addrsByIPAndUID) Less(i, j int) bool { + return LessEndpointAddress(&sl[i], &sl[j]) +} + +type portsByHash []v1.EndpointPort + +func (sl portsByHash) Len() int { return len(sl) } +func (sl portsByHash) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] } +func (sl portsByHash) Less(i, j int) bool { + hasher := md5.New() + h1 := hashObject(hasher, sl[i]) + h2 := hashObject(hasher, sl[j]) + return bytes.Compare(h1, h2) < 0 +} diff --git a/internal/kubernetes_vendor/pkg/util/hash/hash.go b/internal/kubernetes_vendor/pkg/util/hash/hash.go new file mode 100644 index 000000000..803f066a4 --- /dev/null +++ b/internal/kubernetes_vendor/pkg/util/hash/hash.go @@ -0,0 +1,37 @@ +/* +Copyright 2015 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 hash + +import ( + "hash" + + "github.com/davecgh/go-spew/spew" +) + +// DeepHashObject writes specified object to hash using the spew library +// which follows pointers and prints actual values of the nested objects +// ensuring the hash does not change when a pointer changes. +func DeepHashObject(hasher hash.Hash, objectToWrite interface{}) { + hasher.Reset() + printer := spew.ConfigState{ + Indent: " ", + SortKeys: true, + DisableMethods: true, + SpewKeys: true, + } + printer.Fprintf(hasher, "%#v", objectToWrite) +} diff --git a/pkg/diff/diff.go b/pkg/diff/diff.go index c6270b1dd..c4b43ccef 100644 --- a/pkg/diff/diff.go +++ b/pkg/diff/diff.go @@ -18,8 +18,8 @@ import ( "k8s.io/apimachinery/pkg/util/jsonmergepatch" "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/client-go/kubernetes/scheme" - "k8s.io/kubernetes/pkg/api/v1/endpoints" + "github.com/argoproj/gitops-engine/internal/kubernetes_vendor/pkg/api/v1/endpoints" jsonutil "github.com/argoproj/gitops-engine/pkg/utils/json" kubescheme "github.com/argoproj/gitops-engine/pkg/utils/kube/scheme" ) diff --git a/pkg/health/health_pod.go b/pkg/health/health_pod.go index 3db253279..25db283ef 100644 --- a/pkg/health/health_pod.go +++ b/pkg/health/health_pod.go @@ -8,7 +8,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - podutil "k8s.io/kubernetes/pkg/api/v1/pod" + "k8s.io/kubectl/pkg/util/podutils" ) func getPodHealth(obj *unstructured.Unstructured) (*HealthStatus, error) { @@ -96,7 +96,7 @@ func getCorev1PodHealth(pod *corev1.Pod) (*HealthStatus, error) { switch pod.Spec.RestartPolicy { case corev1.RestartPolicyAlways: // if pod is ready, it is automatically healthy - if podutil.IsPodReady(pod) { + if podutils.IsPodReady(pod) { return &HealthStatus{ Status: HealthStatusHealthy, Message: pod.Status.Message,