...

Source file src/github.com/redhat-developer/odo/tests/helper/helper_filesystem.go

Documentation: github.com/redhat-developer/odo/tests/helper

     1  package helper
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"runtime"
     8  	"strings"
     9  	"time"
    10  
    11  	dfutil "github.com/devfile/library/v2/pkg/util"
    12  	. "github.com/onsi/ginkgo/v2"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  // CreateNewContext create new empty temporary directory
    17  func CreateNewContext() string {
    18  	directory, err := os.MkdirTemp("", "")
    19  	Expect(err).NotTo(HaveOccurred())
    20  	fmt.Fprintf(GinkgoWriter, "Created dir: %s\n", directory)
    21  	return directory
    22  }
    23  
    24  // DeleteDir deletes the specified path; due to Windows behaviour (for example https://github.com/redhat-developer/odo/issues/3371)
    25  // where Windows temporarily holds a lock on files and folders, we keep trying to delete until the operation passes (or it expires)
    26  func DeleteDir(dir string) {
    27  	attempts := 0
    28  
    29  	errorReportedAtLeastOnce := false
    30  
    31  	err := RunWithExponentialBackoff(func() error {
    32  		attempts++
    33  
    34  		fmt.Fprintf(GinkgoWriter, "Deleting dir: %s\n", dir)
    35  		err := os.RemoveAll(dir)
    36  		if err == nil {
    37  			return nil
    38  		}
    39  
    40  		errorReportedAtLeastOnce = true
    41  		fmt.Fprintf(GinkgoWriter, "Unable to delete %s on attempt #%d, trying again...\n", dir, attempts)
    42  
    43  		return err
    44  	}, 16, 2*time.Minute)
    45  	Expect(err).NotTo(HaveOccurred())
    46  
    47  	if errorReportedAtLeastOnce {
    48  		fmt.Fprintf(GinkgoWriter, "Successfully deleted %s after #%d attempts\n", dir, attempts)
    49  	}
    50  }
    51  
    52  // RunWithExponentialBackoff keeps trying to run 'fxn' until it no longer returns an error; if the function never succeeded,
    53  // then the most recent error is returned.
    54  func RunWithExponentialBackoff(fxn func() error, maxDelayInSeconds int, expireDuration time.Duration) error {
    55  	expireTime := time.Now().Add(expireDuration)
    56  	delayInSeconds := 1
    57  
    58  	var err error
    59  
    60  	for {
    61  
    62  		err = fxn()
    63  
    64  		if err == nil || time.Now().After(expireTime) {
    65  			break
    66  		}
    67  
    68  		delayInSeconds *= 2 // exponential backoff
    69  		if delayInSeconds > maxDelayInSeconds {
    70  			delayInSeconds = maxDelayInSeconds
    71  		}
    72  		time.Sleep(time.Duration(delayInSeconds) * time.Second)
    73  
    74  	}
    75  	return err
    76  
    77  }
    78  
    79  // DeleteFile deletes file
    80  func DeleteFile(filepath string) {
    81  	fmt.Fprintf(GinkgoWriter, "Deleting file: %s\n", filepath)
    82  	err := os.Remove(filepath)
    83  	Expect(err).NotTo(HaveOccurred())
    84  }
    85  
    86  // Chdir change current working dir
    87  func Chdir(dir string) {
    88  	fmt.Fprintf(GinkgoWriter, "Setting current dir to: %s\n", dir)
    89  	err := os.Chdir(dir)
    90  	Expect(err).ShouldNot(HaveOccurred())
    91  }
    92  
    93  // MakeDir creates a new dir
    94  func MakeDir(dir string) {
    95  	err := os.MkdirAll(dir, 0750)
    96  	Expect(err).ShouldNot(HaveOccurred())
    97  }
    98  
    99  // Getwd returns current working dir
   100  func Getwd() string {
   101  	dir, err := os.Getwd()
   102  	Expect(err).NotTo(HaveOccurred())
   103  	fmt.Fprintf(GinkgoWriter, "Current working dir: %s\n", dir)
   104  	return dir
   105  }
   106  
   107  // CopyExample copies an example from tests/examples/<binaryOrSource>/<componentName>/<exampleName> into targetDir
   108  func CopyExample(exampleName string, targetDir string) {
   109  	// filename of this file
   110  	_, filename, _, _ := runtime.Caller(0)
   111  	// path to the examples directory
   112  	examplesDir := filepath.Join(filepath.Dir(filename), "..", "examples")
   113  
   114  	src := filepath.Join(examplesDir, exampleName)
   115  	info, err := os.Stat(src)
   116  	Expect(err).NotTo(HaveOccurred())
   117  
   118  	err = copyDir(src, targetDir, info)
   119  	Expect(err).NotTo(HaveOccurred())
   120  }
   121  
   122  func CopyManifestFile(fileName, targetDst string) {
   123  	// filename of this file
   124  	_, filename, _, _ := runtime.Caller(0)
   125  	// path to the examples directory
   126  	manifestsDir := filepath.Join(filepath.Dir(filename), "..", "examples", "manifests")
   127  
   128  	src := filepath.Join(manifestsDir, fileName)
   129  	info, err := os.Stat(src)
   130  	Expect(err).NotTo(HaveOccurred())
   131  
   132  	err = dfutil.CopyFile(src, targetDst, info)
   133  	Expect(err).NotTo(HaveOccurred())
   134  
   135  }
   136  
   137  func GetExamplePath(args ...string) string {
   138  	_, filename, _, _ := runtime.Caller(0)
   139  	path := append([]string{filepath.Dir(filename), "..", "examples"}, args...)
   140  	return filepath.Join(path...)
   141  }
   142  
   143  // CopyExampleDevFile copies an example devfile from tests/examples/source/devfiles/<componentName>/devfile.yaml into targetDst.
   144  // If newName is not empty, it will replace the component name in the target Devfile.
   145  // The Devfile updaters allow to perform operations against the target Devfile, like removing the component name (via DevfileMetadataNameRemover).
   146  func CopyExampleDevFile(devfilePath, targetDst string, newName string, updaters ...DevfileUpdater) {
   147  	// filename of this file
   148  	_, filename, _, _ := runtime.Caller(0)
   149  	// path to the examples directory
   150  	examplesDir := filepath.Join(filepath.Dir(filename), "..", "examples")
   151  
   152  	src := filepath.Join(examplesDir, devfilePath)
   153  	info, err := os.Stat(src)
   154  	Expect(err).NotTo(HaveOccurred())
   155  
   156  	err = dfutil.CopyFile(src, targetDst, info)
   157  	Expect(err).NotTo(HaveOccurred())
   158  
   159  	var devfileUpdaters []DevfileUpdater
   160  	if newName != "" {
   161  		devfileUpdaters = append(devfileUpdaters, DevfileMetadataNameSetter(newName))
   162  	}
   163  	devfileUpdaters = append(devfileUpdaters, updaters...)
   164  	UpdateDevfileContent(targetDst, devfileUpdaters)
   165  }
   166  
   167  // FileShouldContainSubstring check if file contains subString
   168  func FileShouldContainSubstring(file string, subString string) {
   169  	data, err := os.ReadFile(file)
   170  	Expect(err).NotTo(HaveOccurred())
   171  	Expect(string(data)).To(ContainSubstring(subString))
   172  }
   173  
   174  // FileShouldNotContainSubstring check if file does not contain subString
   175  func FileShouldNotContainSubstring(file string, subString string) {
   176  	data, err := os.ReadFile(file)
   177  	Expect(err).NotTo(HaveOccurred())
   178  	Expect(string(data)).NotTo(ContainSubstring(subString))
   179  }
   180  
   181  // ReplaceString replaces oldString with newString in text file
   182  func ReplaceString(filename string, oldString string, newString string) {
   183  	fmt.Fprintf(GinkgoWriter, "Replacing \"%s\" with \"%s\" in %s\n", oldString, newString, filename)
   184  
   185  	f, err := os.ReadFile(filename)
   186  	Expect(err).NotTo(HaveOccurred())
   187  
   188  	newContent := strings.ReplaceAll(string(f), oldString, newString)
   189  
   190  	err = os.WriteFile(filename, []byte(newContent), 0600)
   191  	Expect(err).NotTo(HaveOccurred())
   192  }
   193  
   194  // ReplaceStrings replaces oldStrings with newStrings in text file
   195  // two arrays must be of same length, else will fail
   196  func ReplaceStrings(filename string, oldStrings []string, newStrings []string) {
   197  	fmt.Fprintf(GinkgoWriter, "Replacing \"%v\" with \"%v\" in %s\n", oldStrings, newStrings, filename)
   198  
   199  	contentByte, err := os.ReadFile(filename)
   200  	Expect(err).NotTo(HaveOccurred())
   201  
   202  	newContent := string(contentByte)
   203  	for i := range oldStrings {
   204  		newContent = strings.ReplaceAll(newContent, oldStrings[i], newStrings[i])
   205  	}
   206  
   207  	err = os.WriteFile(filename, []byte(newContent), 0600)
   208  	Expect(err).NotTo(HaveOccurred())
   209  }
   210  
   211  // copyDir copy one directory to the other
   212  // this function is called recursively info should start as os.Stat(src)
   213  func copyDir(src string, dst string, info os.FileInfo) error {
   214  
   215  	if info.IsDir() {
   216  		entries, err := os.ReadDir(src)
   217  		if err != nil {
   218  			return err
   219  		}
   220  		for _, entry := range entries {
   221  			file, err := entry.Info()
   222  			if err != nil {
   223  				return err
   224  			}
   225  			dsrt := filepath.Join(src, file.Name())
   226  			ddst := filepath.Join(dst, file.Name())
   227  			if err := copyDir(dsrt, ddst, file); err != nil {
   228  				return err
   229  			}
   230  		}
   231  		return nil
   232  	}
   233  
   234  	if err := os.MkdirAll(filepath.Dir(dst), os.ModePerm); err != nil {
   235  		return err
   236  	}
   237  
   238  	return dfutil.CopyFile(src, dst, info)
   239  }
   240  
   241  // CreateFileWithContent creates a file at the given path and writes the given content
   242  // path is the path to the required file
   243  // fileContent is the content to be written to the given file
   244  func CreateFileWithContent(path string, fileContent string) error {
   245  	return CreateFileWithContentAndPerm(path, fileContent, 0600)
   246  }
   247  
   248  // CreateFileWithContentAndPerm creates a file at the given path using the given file permissions, and writes the given content.
   249  // path is the path to the required file
   250  // fileContent is the content to be written to the given file
   251  func CreateFileWithContentAndPerm(path string, fileContent string, perm os.FileMode) error {
   252  	// create and open file if not exists
   253  	var file, err = os.OpenFile(path, os.O_RDWR|os.O_CREATE, perm)
   254  	if err != nil {
   255  		return err
   256  	}
   257  	defer file.Close() // #nosec G307
   258  	// write to file
   259  	_, err = file.WriteString(fileContent)
   260  	if err != nil {
   261  		return err
   262  	}
   263  	return nil
   264  }
   265  
   266  // ListFilesInDir lists all the files in the directory
   267  // directoryName is the name of the directory
   268  func ListFilesInDir(directoryName string) []string {
   269  	var filesInDirectory []string
   270  	entries, err := os.ReadDir(directoryName)
   271  	Expect(err).ShouldNot(HaveOccurred())
   272  	for _, entry := range entries {
   273  		file, err := entry.Info()
   274  		Expect(err).ShouldNot(HaveOccurred())
   275  		filesInDirectory = append(filesInDirectory, file.Name())
   276  	}
   277  	return filesInDirectory
   278  }
   279  
   280  // VerifyFileExists receives a path to a file, and returns whether or not
   281  // it points to an existing file
   282  func VerifyFileExists(filename string) bool {
   283  	info, err := os.Stat(filename)
   284  	if os.IsNotExist(err) {
   285  		return false
   286  	}
   287  	return !info.IsDir()
   288  }
   289  
   290  // ReadFile reads the file from the filePath
   291  func ReadFile(filePath string) (string, error) {
   292  	data, err := os.ReadFile(filePath)
   293  	if err != nil {
   294  		return "", err
   295  	}
   296  	return string(data), nil
   297  }
   298  
   299  // CreateSimpleFile creates a simple file
   300  // return the file path with random string
   301  func CreateSimpleFile(context, filePrefix, fileExtension string) (string, string) {
   302  
   303  	FilePath := filepath.Join(context, filePrefix+RandString(10)+fileExtension)
   304  	content := []byte(RandString(10))
   305  	err := os.WriteFile(FilePath, content, 0600)
   306  	Expect(err).NotTo(HaveOccurred())
   307  
   308  	return FilePath, string(content)
   309  }
   310  
   311  func AppendToFile(filepath string, s string) error {
   312  	f, err := os.OpenFile(filepath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
   313  	if err != nil {
   314  		return err
   315  	}
   316  	defer f.Close() // #nosec G307
   317  	if _, err := f.WriteString(s); err != nil {
   318  		return err
   319  	}
   320  	return nil
   321  }
   322  
   323  func CreateInvalidDevfile(dir string) {
   324  	devfilePath := filepath.Join(dir, "devfile.yaml")
   325  	err := CreateFileWithContent(devfilePath, "invalid")
   326  	Expect(err).ToNot(HaveOccurred())
   327  }
   328  
   329  func DeleteInvalidDevfile(dir string) {
   330  	devfilePath := filepath.Join(dir, "devfile.yaml")
   331  	err := os.Remove(devfilePath)
   332  	Expect(err).ToNot(HaveOccurred())
   333  }
   334  

View as plain text