istio.io/istio@v0.0.0-20240520182934-d79c90f27776/operator/pkg/util/util.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package util 16 17 import ( 18 "bytes" 19 "fmt" 20 "os" 21 "path/filepath" 22 "strconv" 23 "strings" 24 "text/template" 25 26 "google.golang.org/protobuf/types/known/structpb" 27 ) 28 29 type FileFilter func(fileName string) bool 30 31 // StringBoolMapToSlice creates and returns a slice of all the map keys with true. 32 func StringBoolMapToSlice(m map[string]bool) []string { 33 s := make([]string, 0, len(m)) 34 for k, v := range m { 35 if v { 36 s = append(s, k) 37 } 38 } 39 return s 40 } 41 42 // ReadFilesWithFilter reads files from path, for a directory it recursively reads files and filters the results 43 // for single file it directly reads the file. It returns a concatenated output of all matching files' content. 44 func ReadFilesWithFilter(path string, filter FileFilter) (string, error) { 45 fileList, err := FindFiles(path, filter) 46 if err != nil { 47 return "", err 48 } 49 var sb strings.Builder 50 for _, file := range fileList { 51 a, err := os.ReadFile(file) 52 if err != nil { 53 return "", err 54 } 55 if _, err := sb.WriteString(string(a) + "\n"); err != nil { 56 return "", err 57 } 58 } 59 return sb.String(), nil 60 } 61 62 // FindFiles reads files from path, and returns the file names that match the filter. 63 func FindFiles(path string, filter FileFilter) ([]string, error) { 64 fi, err := os.Stat(path) 65 if err != nil { 66 return nil, err 67 } 68 var fileList []string 69 if fi.IsDir() { 70 err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error { 71 if err != nil { 72 return err 73 } 74 if info.IsDir() || !filter(path) { 75 return nil 76 } 77 fileList = append(fileList, path) 78 return nil 79 }) 80 if err != nil { 81 return nil, err 82 } 83 } else { 84 fileList = append(fileList, path) 85 } 86 return fileList, nil 87 } 88 89 // ParseValue parses string into a value 90 func ParseValue(valueStr string) any { 91 var value any 92 if v, err := strconv.Atoi(valueStr); err == nil { 93 value = v 94 } else if v, err := strconv.ParseFloat(valueStr, 64); err == nil { 95 value = v 96 } else if v, err := strconv.ParseBool(valueStr); err == nil { 97 value = v 98 } else { 99 value = strings.ReplaceAll(valueStr, "\\,", ",") 100 } 101 return value 102 } 103 104 // ConsolidateLog is a helper function to dedup the log message. 105 func ConsolidateLog(logMessage string) string { 106 logCountMap := make(map[string]int) 107 stderrSlice := strings.Split(logMessage, "\n") 108 for _, item := range stderrSlice { 109 if item == "" { 110 continue 111 } 112 _, exist := logCountMap[item] 113 if exist { 114 logCountMap[item]++ 115 } else { 116 logCountMap[item] = 1 117 } 118 } 119 var sb strings.Builder 120 for _, item := range stderrSlice { 121 if logCountMap[item] == 0 { 122 continue 123 } 124 sb.WriteString(fmt.Sprintf("%s (repeated %v times)\n", item, logCountMap[item])) 125 // reset seen log count 126 logCountMap[item] = 0 127 } 128 return sb.String() 129 } 130 131 // RenderTemplate is a helper method to render a template with the given values. 132 func RenderTemplate(tmpl string, ts any) (string, error) { 133 t, err := template.New("").Parse(tmpl) 134 if err != nil { 135 return "", err 136 } 137 buf := new(bytes.Buffer) 138 err = t.Execute(buf, ts) 139 if err != nil { 140 return "", err 141 } 142 return buf.String(), nil 143 } 144 145 func ValueString(v *structpb.Value) string { 146 switch x := v.Kind.(type) { 147 case *structpb.Value_StringValue: 148 return x.StringValue 149 case *structpb.Value_NumberValue: 150 return fmt.Sprint(x.NumberValue) 151 default: 152 return v.String() 153 } 154 } 155 156 func MustStruct(m map[string]any) *structpb.Struct { 157 s, _ := structpb.NewStruct(m) 158 return s 159 }