github.com/verrazzano/verrazzano@v1.7.0/tools/vz/pkg/analysis/internal/util/files/files.go (about) 1 // Copyright (c) 2021, 2023, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 // Package files handles searching 5 package files 6 7 import ( 8 "encoding/json" 9 "errors" 10 "fmt" 11 "io" 12 "os" 13 "path/filepath" 14 "regexp" 15 16 "go.uber.org/zap" 17 corev1 "k8s.io/api/core/v1" 18 ) 19 20 // GetMatchingFiles returns the filenames for files that match a regular expression. 21 func GetMatchingFiles(log *zap.SugaredLogger, rootDirectory string, fileMatchRe *regexp.Regexp) (fileMatches []string, err error) { 22 log.Debugf("GetMatchingFiles called with rootDirectory: %s", rootDirectory) 23 if len(rootDirectory) == 0 { 24 log.Debugf("GetMatchingFiles requires a rootDirectory") 25 return nil, errors.New("GetMatchingFiles requires a rootDirectory") 26 } 27 28 if fileMatchRe == nil { 29 return nil, fmt.Errorf("GetMatchingFiles requires a regular expression") 30 } 31 32 walkFunc := func(fileName string, fileInfo os.FileInfo, err error) error { 33 if !fileMatchRe.MatchString(fileName) { 34 return nil 35 } 36 if !fileInfo.IsDir() { 37 log.Debugf("GetMatchingFiles %s matched", fileName) 38 fileMatches = append(fileMatches, fileName) 39 } 40 return nil 41 } 42 43 err = filepath.Walk(rootDirectory, walkFunc) 44 if err != nil { 45 log.Debugf("GetMatchingFiles failed to walk the filepath", err) 46 return nil, err 47 } 48 return fileMatches, err 49 } 50 51 // GetMatchingDirectories returns the filenames for directories that match a regular expression. 52 func GetMatchingDirectories(log *zap.SugaredLogger, rootDirectory string, fileMatchRe *regexp.Regexp) (fileMatches []string, err error) { 53 log.Debugf("GetMatchingFiles called with rootDirectory: %s", rootDirectory) 54 if len(rootDirectory) == 0 { 55 log.Debugf("GetMatchingDirectories requires a root directory") 56 return nil, errors.New("GetMatchingDirectories requires a rootDirectory") 57 } 58 59 if fileMatchRe == nil { 60 return nil, fmt.Errorf("GetMatchingDirectories requires a regular expression") 61 } 62 63 walkFunc := func(fileName string, fileInfo os.FileInfo, err error) error { 64 if !fileMatchRe.MatchString(fileName) { 65 return nil 66 } 67 if fileInfo.IsDir() { 68 log.Debugf("GetMatchingDirectories %s matched", fileName) 69 fileMatches = append(fileMatches, fileName) 70 } 71 return nil 72 } 73 74 err = filepath.Walk(rootDirectory, walkFunc) 75 if err != nil { 76 log.Debugf("GetMatchingFiles failed to walk the filepath", err) 77 return nil, err 78 } 79 return fileMatches, nil 80 } 81 82 // FindNamespaces relies on the directory structure of the cluster-snapshot/namespaces to 83 // determine the namespaces that were found in the dump. It will return the 84 // namespace only here and not the entire path. 85 func FindNamespaces(log *zap.SugaredLogger, clusterRoot string) (namespaces []string, err error) { 86 fileInfos, err := os.ReadDir(clusterRoot) 87 if err != nil { 88 return nil, fmt.Errorf("FindNamespaces failed to read directory %s: %s", clusterRoot, err.Error()) 89 } 90 91 for _, fileInfo := range fileInfos { 92 if fileInfo.IsDir() { 93 namespaces = append(namespaces, filepath.Base(fileInfo.Name())) 94 } 95 } 96 return namespaces, nil 97 } 98 99 // FindFileInClusterRoot will find filename in the cluster root 100 func FindFileInClusterRoot(clusterRoot string, filename string) string { 101 return fmt.Sprintf("%s/%s", clusterRoot, filename) 102 } 103 104 // FindFileInNamespace will find filename in the namespace 105 func FindFileInNamespace(clusterRoot string, namespace string, filename string) string { 106 return fmt.Sprintf("%s/%s/%s", clusterRoot, namespace, filename) 107 } 108 109 // FindPodLogFileName will find the name of the log file given a pod 110 func FindPodLogFileName(clusterRoot string, pod corev1.Pod) string { 111 return fmt.Sprintf("%s/%s/%s/logs.txt", clusterRoot, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name) 112 } 113 114 // UnmarshallFileInClusterRoot - unmarshall a file into a struct 115 func UnmarshallFileInClusterRoot(clusterRoot string, filename string, object interface{}) error { 116 clusterPath := FindFileInClusterRoot(clusterRoot, filename) 117 return unmarshallFile(clusterPath, object) 118 } 119 120 // UnmarshallFileInNamespace - unmarshall a file from a namespace into a struct 121 func UnmarshallFileInNamespace(clusterRoot string, namespace string, filename string, object interface{}) error { 122 clusterPath := FindFileInNamespace(clusterRoot, namespace, filename) 123 return unmarshallFile(clusterPath, object) 124 } 125 126 func unmarshallFile(clusterPath string, object interface{}) error { 127 // Parse the json into local struct 128 file, err := os.Open(clusterPath) 129 if os.IsNotExist(err) { 130 // The file may not exist if the component is not installed. 131 return nil 132 } 133 if err != nil { 134 return fmt.Errorf("failed to open file %s from cluster snapshot: %s", clusterPath, err.Error()) 135 } 136 defer file.Close() 137 138 fileBytes, err := io.ReadAll(file) 139 if err != nil { 140 return fmt.Errorf("Failed reading Json file %s: %s", clusterPath, err.Error()) 141 } 142 143 // Unmarshall file contents into a struct 144 err = json.Unmarshal(fileBytes, object) 145 if err != nil { 146 return fmt.Errorf("Failed to unmarshal %s: %s", clusterPath, err.Error()) 147 } 148 149 return nil 150 }