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  }