github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/vparec.go (about) 1 /* 2 Copyright 2022 The Katalyst Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package util 18 19 import ( 20 "fmt" 21 22 "github.com/pkg/errors" 23 apierrors "k8s.io/apimachinery/pkg/api/errors" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/labels" 26 "k8s.io/client-go/tools/cache" 27 "sigs.k8s.io/controller-runtime/pkg/client/apiutil" 28 29 apis "github.com/kubewharf/katalyst-api/pkg/apis/autoscaling/v1alpha1" 30 "github.com/kubewharf/katalyst-api/pkg/client/clientset/versioned/scheme" 31 autoscalelister "github.com/kubewharf/katalyst-api/pkg/client/listers/autoscaling/v1alpha1" 32 apiconsts "github.com/kubewharf/katalyst-api/pkg/consts" 33 "github.com/kubewharf/katalyst-core/pkg/consts" 34 "github.com/kubewharf/katalyst-core/pkg/util/native" 35 ) 36 37 /* 38 helper functions to get vpa-rec-related objects with indexed informer 39 */ 40 41 // GetVPARecForVPA is used to get vpaRec that should be managed the given vpa 42 func getVPARecFroVPAWithIndex(vpa *apis.KatalystVerticalPodAutoscaler, vpaRecIndexer cache.Indexer) (*apis.VerticalPodAutoscalerRecommendation, error) { 43 gvk, err := apiutil.GVKForObject(vpa, scheme.Scheme) 44 if err != nil { 45 return nil, err 46 } 47 ownerRef := metav1.OwnerReference{ 48 Name: vpa.GetName(), 49 Kind: gvk.Kind, 50 APIVersion: gvk.GroupVersion().String(), 51 UID: vpa.GetUID(), 52 } 53 54 objs, err := vpaRecIndexer.ByIndex(consts.OwnerReferenceIndex, native.GenerateObjectOwnerReferenceKey(ownerRef)) 55 if err != nil { 56 return nil, errors.Wrapf(err, "vpaRec for vpa %s not exist", vpa.Name) 57 } else if len(objs) > 1 || len(objs) == 0 { 58 return nil, fmt.Errorf("vpaRec for vpa %s invalid", vpa.Name) 59 } 60 61 vpaRec, ok := objs[0].(*apis.VerticalPodAutoscalerRecommendation) 62 if !ok { 63 return nil, fmt.Errorf("invalid vpaRec") 64 } 65 return vpaRec, nil 66 } 67 68 /* 69 helper functions to build indexed informer for vpa-rec-related objects 70 */ 71 72 // GetVPAForVPARec is used to get vpa that should manage the given vpaRec 73 func GetVPAForVPARec(vpaRec *apis.VerticalPodAutoscalerRecommendation, 74 vpaLister autoscalelister.KatalystVerticalPodAutoscalerLister, 75 ) (*apis.KatalystVerticalPodAutoscaler, error) { 76 ownerReferences := vpaRec.GetOwnerReferences() 77 if len(ownerReferences) == 0 { 78 return nil, fmt.Errorf(" vpaRec %v has no owner", vpaRec.Name) 79 } else if len(ownerReferences) > 1 { 80 return nil, fmt.Errorf(" vpaRec %v has more than one owner", vpaRec.Name) 81 } 82 83 vpa, err := vpaLister.KatalystVerticalPodAutoscalers(vpaRec.Namespace).Get(ownerReferences[0].Name) 84 if err != nil { 85 return nil, fmt.Errorf("failed to get vpa %v : %v", ownerReferences[0].Name, err) 86 } 87 88 if !CheckVPARecommendationMatchVPA(vpaRec, vpa) { 89 return nil, fmt.Errorf("VPA UID mismatch, VPA %s may be deleted", vpa.Name) 90 } 91 92 return vpa, nil 93 } 94 95 // GetVPARecForVPA is used to get vpaRec that should be managed the given vpa 96 func GetVPARecForVPA(vpa *apis.KatalystVerticalPodAutoscaler, vpaRecIndexer cache.Indexer, 97 recLister autoscalelister.VerticalPodAutoscalerRecommendationLister, 98 ) (*apis.VerticalPodAutoscalerRecommendation, error) { 99 if recName, ok := vpa.GetAnnotations()[apiconsts.VPAAnnotationVPARecNameKey]; ok { 100 vpaRec, err := recLister.VerticalPodAutoscalerRecommendations(vpa.Namespace).Get(recName) 101 if err == nil && CheckVPARecommendationMatchVPA(vpaRec, vpa) { 102 return vpaRec, nil 103 } 104 } 105 106 if vpaRecIndexer != nil { 107 if vpaRec, err := getVPARecFroVPAWithIndex(vpa, vpaRecIndexer); err == nil { 108 return vpaRec, nil 109 } 110 } 111 112 recList, err := recLister.List(labels.Everything()) 113 if err != nil { 114 return nil, err 115 } 116 117 for _, vpaRec := range recList { 118 if CheckVPARecommendationMatchVPA(vpaRec, vpa) { 119 return vpaRec, nil 120 } 121 } 122 return nil, apierrors.NewNotFound(apis.Resource(apis.ResourceNameVPARecommendation), "vparec for vpa") 123 }