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  }