github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/spd_indicator.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 "k8s.io/apimachinery/pkg/util/errors" 23 "k8s.io/utils/pointer" 24 25 workloadapis "github.com/kubewharf/katalyst-api/pkg/apis/workload/v1alpha1" 26 ) 27 28 type IndicatorTarget struct { 29 UpperBound *float64 30 LowerBound *float64 31 } 32 33 // GetServiceBusinessIndicatorTarget get service business indicator target from spd 34 // if there are duplicate upper bound or lower bound, return error 35 func GetServiceBusinessIndicatorTarget(spd *workloadapis.ServiceProfileDescriptor) (map[string]IndicatorTarget, error) { 36 var errList []error 37 indicators := make(map[string]IndicatorTarget) 38 for _, indicator := range spd.Spec.BusinessIndicator { 39 _, ok := indicators[string(indicator.Name)] 40 if ok { 41 errList = append(errList, fmt.Errorf("duplicate indicator %s", indicator.Name)) 42 continue 43 } 44 45 targetIndicator, err := getIndicatorTarget(indicator.Indicators) 46 if err != nil { 47 errList = append(errList, fmt.Errorf("get indicator %s failed: %v", indicator.Name, err)) 48 } 49 50 indicators[string(indicator.Name)] = *targetIndicator 51 } 52 53 if len(errList) > 0 { 54 return nil, fmt.Errorf("failed to get service business indicators: %v", errors.NewAggregate(errList)) 55 } 56 57 return indicators, nil 58 } 59 60 // GetServiceSystemIndicatorTarget get service system indicator target from spd 61 // if there are duplicate upper bound or lower bound, return error 62 func GetServiceSystemIndicatorTarget(spd *workloadapis.ServiceProfileDescriptor) (map[string]IndicatorTarget, error) { 63 var errList []error 64 indicators := make(map[string]IndicatorTarget) 65 for _, indicator := range spd.Spec.SystemIndicator { 66 _, ok := indicators[string(indicator.Name)] 67 if ok { 68 errList = append(errList, fmt.Errorf("duplicate indicator %s", indicator.Name)) 69 continue 70 } 71 72 targetIndicator, err := getIndicatorTarget(indicator.Indicators) 73 if err != nil { 74 errList = append(errList, fmt.Errorf("get indicator %s failed: %v", indicator.Name, err)) 75 } 76 77 indicators[string(indicator.Name)] = *targetIndicator 78 } 79 80 if len(errList) > 0 { 81 return nil, fmt.Errorf("failed to get service system indicators: %v", errors.NewAggregate(errList)) 82 } 83 84 return indicators, nil 85 } 86 87 // GetServiceBusinessIndicatorValue returns the current value of business indicators 88 // The returned map is a map from indicator name to its current value, and if duplicate 89 // indicators are found, the first one is used 90 func GetServiceBusinessIndicatorValue(spd *workloadapis.ServiceProfileDescriptor) (map[string]float64, error) { 91 indicatorValues := make(map[string]float64) 92 for _, indicator := range spd.Status.BusinessStatus { 93 if indicator.Current == nil { 94 continue 95 } 96 97 _, ok := indicatorValues[string(indicator.Name)] 98 if ok { 99 continue 100 } 101 102 indicatorValues[string(indicator.Name)] = float64(*indicator.Current) 103 } 104 105 return indicatorValues, nil 106 } 107 108 func getIndicatorTarget(indicators []workloadapis.Indicator) (*IndicatorTarget, error) { 109 targetIndicator := &IndicatorTarget{} 110 for _, target := range indicators { 111 switch target.IndicatorLevel { 112 case workloadapis.IndicatorLevelUpperBound: 113 if targetIndicator.UpperBound != nil { 114 return nil, fmt.Errorf("duplicate upper bound for indicator") 115 } 116 targetIndicator.UpperBound = pointer.Float64(float64(target.Value)) 117 case workloadapis.IndicatorLevelLowerBound: 118 if targetIndicator.LowerBound != nil { 119 return nil, fmt.Errorf("duplicate lower bound for indicator") 120 } 121 targetIndicator.LowerBound = pointer.Float64(float64(target.Value)) 122 default: 123 return nil, fmt.Errorf("invalid indicator level %s", target.IndicatorLevel) 124 } 125 } 126 127 // check whether target indicator is validated 128 if targetIndicator.LowerBound != nil && targetIndicator.UpperBound != nil && 129 *targetIndicator.LowerBound > *targetIndicator.UpperBound { 130 return nil, fmt.Errorf("lower bound %v is higher than uppoer bound %v for indicator", 131 *targetIndicator.LowerBound, *targetIndicator.UpperBound) 132 } 133 134 return targetIndicator, nil 135 }