github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/general/common.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 general 18 19 import ( 20 "bytes" 21 "crypto/sha256" 22 "encoding/json" 23 "fmt" 24 "math" 25 "sort" 26 "strconv" 27 "strings" 28 "time" 29 30 "k8s.io/apimachinery/pkg/api/resource" 31 "k8s.io/apimachinery/pkg/util/sets" 32 ) 33 34 func Max(a, b int) int { 35 if a >= b { 36 return a 37 } else { 38 return b 39 } 40 } 41 42 func MaxUInt64(a, b uint64) uint64 { 43 if a >= b { 44 return a 45 } else { 46 return b 47 } 48 } 49 50 func MaxInt64(a, b int64) int64 { 51 if a >= b { 52 return a 53 } else { 54 return b 55 } 56 } 57 58 func MaxFloat64(a, b float64) float64 { 59 if a >= b { 60 return a 61 } else { 62 return b 63 } 64 } 65 66 func MaxTimePtr(a, b *time.Time) *time.Time { 67 if a == nil { 68 return b 69 } else if b == nil { 70 return a 71 } else if a.After(*b) { 72 return a 73 } 74 return b 75 } 76 77 func Min(a, b int) int { 78 if a >= b { 79 return b 80 } else { 81 return a 82 } 83 } 84 85 func MinUInt64(a, b uint64) uint64 { 86 if a <= b { 87 return a 88 } else { 89 return b 90 } 91 } 92 93 func MinInt64(a, b int64) int64 { 94 if a <= b { 95 return a 96 } else { 97 return b 98 } 99 } 100 101 func MinUInt32(a, b uint32) uint32 { 102 if a <= b { 103 return a 104 } else { 105 return b 106 } 107 } 108 109 func MinFloat64(a, b float64) float64 { 110 if a >= b { 111 return b 112 } else { 113 return a 114 } 115 } 116 117 // IsNameEnabled check if a specified name enabled or not. 118 func IsNameEnabled(name string, disabledByDefault sets.String, enableNames []string) bool { 119 hasStar := false 120 for _, ctrl := range enableNames { 121 if ctrl == name { 122 return true 123 } 124 if ctrl == "-"+name { 125 return false 126 } 127 if ctrl == "*" { 128 hasStar = true 129 } 130 } 131 // if we get here, there was no explicit choice 132 if !hasStar { 133 // nothing on by default 134 return false 135 } 136 137 if disabledByDefault != nil { 138 return !disabledByDefault.Has(name) 139 } 140 return true 141 } 142 143 func ParseUint64PointerToString(v *uint64) string { 144 if v == nil { 145 return "nil" 146 } else { 147 return fmt.Sprintf("%d", *v) 148 } 149 } 150 151 func ParseStringToUint64Pointer(s string) (*uint64, error) { 152 if s == "nil" { 153 return nil, nil 154 } else { 155 v, err := strconv.ParseUint(s, 10, 64) 156 if err != nil { 157 return nil, err 158 } 159 160 return &v, nil 161 } 162 } 163 164 func GetInt64PointerFromUint64Pointer(v *uint64) (*int64, error) { 165 if v == nil { 166 return nil, nil 167 } 168 169 ret := int64(*v) 170 171 if ret < 0 { 172 return &ret, fmt.Errorf("transformation overflows") 173 } else { 174 return &ret, nil 175 } 176 } 177 178 func GenerateHash(data []byte, length int) string { 179 h := sha256.New() 180 h.Write(data) 181 result := fmt.Sprintf("%x", h.Sum(nil)) 182 if len(result) > length { 183 return result[:length] 184 } 185 return result 186 } 187 188 func UIntPointerToFloat64(p *uint) float64 { 189 if p == nil { 190 return 0 191 } 192 return float64(*p) 193 } 194 195 func UInt64PointerToFloat64(p *uint64) float64 { 196 if p == nil { 197 return 0 198 } 199 return float64(*p) 200 } 201 202 // JsonPathEmpty is used to check whether the given str is empty for json-patch 203 func JsonPathEmpty(str []byte) bool { 204 if "{}" == string(str) || "" == string(str) { 205 return true 206 } 207 return false 208 } 209 210 // GetValueWithDefault gets value from the given map, and returns default if key not exist 211 func GetValueWithDefault(m map[string]string, key, defaultV string) string { 212 if _, ok := m[key]; !ok { 213 return defaultV 214 } 215 return m[key] 216 } 217 218 func GetStringValueFromMap(m map[string]string, key string) string { 219 if value, found := m[key]; found { 220 return value 221 } 222 return "" 223 } 224 225 // SumUpMultipleMapValues accumulates total values for the given multi-level map 226 func SumUpMultipleMapValues(m map[string]map[string]int) int { 227 total := 0 228 for _, v := range m { 229 total += SumUpMapValues(v) 230 } 231 return total 232 } 233 234 // SumUpMapValues accumulates total values for the given map 235 func SumUpMapValues(m map[string]int) int { 236 total := 0 237 for _, quantity := range m { 238 total += quantity 239 } 240 return total 241 } 242 243 func CheckMapEqual(pre, cur map[string]string) bool { 244 if len(pre) != len(cur) { 245 return false 246 } 247 248 for key, value := range pre { 249 if value != cur[key] { 250 return false 251 } 252 } 253 return true 254 } 255 256 // MergeMap merges the contents from override into the src 257 func MergeMap(src, override map[string]string) map[string]string { 258 res := map[string]string{} 259 for k, v := range src { 260 res[k] = v 261 } 262 for k, v := range override { 263 res[k] = v 264 } 265 return res 266 } 267 268 // MergeMapInt merges the contents from override into the src 269 func MergeMapInt(src, override map[string]int) map[string]int { 270 res := map[string]int{} 271 for k, v := range src { 272 res[k] = v 273 } 274 for k, v := range override { 275 res[k] = v 276 } 277 return res 278 } 279 280 // GetSortedMapKeys returns a slice containing sorted keys for the given map 281 func GetSortedMapKeys(m map[string]int) []string { 282 ret := make([]string, 0, len(m)) 283 for key := range m { 284 ret = append(ret, key) 285 } 286 sort.Strings(ret) 287 return ret 288 } 289 290 // ParseMapWithPrefix converts selector string to label map 291 // and validates keys and values 292 func ParseMapWithPrefix(prefix, selector string) (map[string]string, error) { 293 labelsMap := make(map[string]string) 294 295 if len(selector) == 0 { 296 return labelsMap, nil 297 } 298 299 labels := strings.Split(selector, ",") 300 for _, label := range labels { 301 l := strings.Split(label, "=") 302 if len(l) != 2 { 303 return labelsMap, fmt.Errorf("invalid selector: %s", l) 304 } 305 306 key := strings.TrimSpace(l[0]) 307 value := strings.TrimSpace(l[1]) 308 labelsMap[prefix+key] = value 309 } 310 return labelsMap, nil 311 } 312 313 // ToString transform to string for better display etc. in log 314 func ToString(in interface{}) string { 315 var out bytes.Buffer 316 b, _ := json.Marshal(in) 317 _ = json.Indent(&out, b, "", " ") 318 return out.String() 319 } 320 321 func IntSliceToStringSlice(a []int) []string { 322 var ss []string 323 for _, i := range a { 324 ss = append(ss, strconv.Itoa(i)) 325 } 326 return ss 327 } 328 329 func CovertInt64ToInt(numInt64 int64) (int, error) { 330 numInt := int(numInt64) 331 if int64(numInt) != numInt64 { 332 return 0, fmt.Errorf("convert numInt64: %d to numInt: %d failed", numInt64, numInt) 333 } 334 return numInt, nil 335 } 336 337 func CovertUInt64ToInt(numUInt64 uint64) (int, error) { 338 numInt := int(numUInt64) 339 if numInt < 0 || uint64(numInt) != numUInt64 { 340 return 0, fmt.Errorf("convert numUInt64: %d to numInt: %d failed", numUInt64, numInt) 341 } 342 return numInt, nil 343 } 344 345 // Clamp returns value itself if min < value < max; min if value < min; max if value > max 346 func Clamp(value, min, max float64) float64 { 347 return math.Max(math.Min(value, max), min) 348 } 349 350 // FormatMemoryQuantity aligned to Gi Mi Ki 351 func FormatMemoryQuantity(q float64) string { 352 value := int64(q) 353 if (value >> 30) > 0 { 354 value = (value >> 30) << 30 355 } else if (value >> 20) > 0 { 356 value = (value >> 20) << 20 357 } else if (value >> 10) > 0 { 358 value = (value >> 10) << 10 359 } 360 quantity := resource.NewQuantity(value, resource.BinarySI) 361 362 return fmt.Sprintf("%v[%v]", q, quantity.String()) 363 } 364 365 // DedupStringSlice return deduplicated string slice from original 366 func DedupStringSlice(input []string) []string { 367 result := sets.NewString() 368 for _, v := range input { 369 result.Insert(v) 370 } 371 return result.UnsortedList() 372 }