1// Copyright 2019 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 15package util 16 17import ( 18 "bytes" 19 "fmt" 20 "html/template" 21 "io/ioutil" 22 "os" 23 "path/filepath" 24 "strconv" 25 "strings" 26) 27 28type FileFilter func(fileName string) bool 29 30// StringBoolMapToSlice creates and returns a slice of all the map keys with true. 31func StringBoolMapToSlice(m map[string]bool) []string { 32 s := make([]string, 0, len(m)) 33 for k, v := range m { 34 if v { 35 s = append(s, k) 36 } 37 } 38 return s 39} 40 41// ReadFilesWithFilter reads files from path, for a directory it recursively reads files and filters the results 42// for single file it directly reads the file. It returns a concatenated output of all matching files' content. 43func ReadFilesWithFilter(path string, filter FileFilter) (string, error) { 44 fileList, err := FindFiles(path, filter) 45 if err != nil { 46 return "", err 47 } 48 var sb strings.Builder 49 for _, file := range fileList { 50 a, err := ioutil.ReadFile(file) 51 if err != nil { 52 return "", err 53 } 54 if _, err := sb.WriteString(string(a) + "\n"); err != nil { 55 return "", err 56 } 57 } 58 return sb.String(), nil 59} 60 61// FindFiles reads files from path, and returns the file names that match the filter. 62func FindFiles(path string, filter FileFilter) ([]string, error) { 63 fi, err := os.Stat(path) 64 if err != nil { 65 return nil, err 66 } 67 var fileList []string 68 if fi.IsDir() { 69 err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error { 70 if err != nil { 71 return err 72 } 73 if info.IsDir() || !filter(path) { 74 return nil 75 } 76 fileList = append(fileList, path) 77 return nil 78 }) 79 if err != nil { 80 return nil, err 81 } 82 } else { 83 fileList = append(fileList, path) 84 } 85 return fileList, nil 86} 87 88// ParseValue parses string into a value 89func ParseValue(valueStr string) interface{} { 90 var value interface{} 91 if v, err := strconv.Atoi(valueStr); err == nil { 92 value = v 93 } else if v, err := strconv.ParseFloat(valueStr, 64); err == nil { 94 value = v 95 } else if v, err := strconv.ParseBool(valueStr); err == nil { 96 value = v 97 } else { 98 value = strings.ReplaceAll(valueStr, "\\,", ",") 99 } 100 return value 101} 102 103// ConsolidateLog is a helper function to dedup the log message. 104func ConsolidateLog(logMessage string) string { 105 logCountMap := make(map[string]int) 106 stderrSlice := strings.Split(logMessage, "\n") 107 for _, item := range stderrSlice { 108 if item == "" { 109 continue 110 } 111 _, exist := logCountMap[item] 112 if exist { 113 logCountMap[item]++ 114 } else { 115 logCountMap[item] = 1 116 } 117 } 118 var sb strings.Builder 119 for _, item := range stderrSlice { 120 if logCountMap[item] == 0 { 121 continue 122 } 123 sb.WriteString(fmt.Sprintf("%s (repeated %v times)\n", item, logCountMap[item])) 124 // reset seen log count 125 logCountMap[item] = 0 126 } 127 return sb.String() 128} 129 130// RenderTemplate is a helper method to render a template with the given values. 131func RenderTemplate(tmpl string, ts interface{}) (string, error) { 132 t, err := template.New("").Parse(tmpl) 133 if err != nil { 134 return "", err 135 } 136 buf := new(bytes.Buffer) 137 err = t.Execute(buf, ts) 138 if err != nil { 139 return "", err 140 } 141 return buf.String(), nil 142} 143