istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/util/file/file.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 file 16 17 import ( 18 "archive/tar" 19 "bytes" 20 "fmt" 21 "io" 22 "os" 23 "path/filepath" 24 "strings" 25 26 "github.com/mitchellh/go-homedir" 27 28 "istio.io/istio/pkg/test" 29 ) 30 31 // AsBytes is a simple wrapper around os.ReadFile provided for completeness. 32 func AsBytes(filename string) ([]byte, error) { 33 return os.ReadFile(filename) 34 } 35 36 // AsBytesOrFail calls AsBytes and fails the test if any errors occurred. 37 func AsBytesOrFail(t test.Failer, filename string) []byte { 38 t.Helper() 39 content, err := AsBytes(filename) 40 if err != nil { 41 t.Fatal(err) 42 } 43 return content 44 } 45 46 // MustAsBytes calls AsBytes and panics the test if any errors occurred. 47 func MustAsBytes(filename string) []byte { 48 content, err := AsBytes(filename) 49 if err != nil { 50 panic(err) 51 } 52 return content 53 } 54 55 // AsStringArray is a convenience wrapper around os.ReadFile that converts the content to a string. 56 func AsStringArray(files ...string) ([]string, error) { 57 out := make([]string, 0, len(files)) 58 for _, f := range files { 59 b, err := AsBytes(f) 60 if err != nil { 61 return nil, err 62 } 63 out = append(out, string(b)) 64 } 65 return out, nil 66 } 67 68 // AsStringArrayOrFail calls AsStringOrFail and then converts to string. 69 func AsStringArrayOrFail(t test.Failer, files ...string) []string { 70 t.Helper() 71 out, err := AsStringArray(files...) 72 if err != nil { 73 t.Fatal(err) 74 } 75 return out 76 } 77 78 // AsString is a convenience wrapper around os.ReadFile that converts the content to a string. 79 func AsString(filename string) (string, error) { 80 b, err := AsBytes(filename) 81 if err != nil { 82 return "", err 83 } 84 return string(b), nil 85 } 86 87 // AsStringOrFail calls AsBytesOrFail and then converts to string. 88 func AsStringOrFail(t test.Failer, filename string) string { 89 t.Helper() 90 return string(AsBytesOrFail(t, filename)) 91 } 92 93 // MustAsString calls MustAsBytes and then converts to string. 94 func MustAsString(filename string) string { 95 return string(MustAsBytes(filename)) 96 } 97 98 // NormalizePath expands the homedir (~) and returns an error if the file doesn't exist. 99 func NormalizePath(originalPath string) (string, error) { 100 if originalPath == "" { 101 return "", nil 102 } 103 // trim leading/trailing spaces from the path and if it uses the homedir ~, expand it. 104 var err error 105 out := strings.TrimSpace(originalPath) 106 out, err = homedir.Expand(out) 107 if err != nil { 108 return "", err 109 } 110 111 // Verify that the file exists. 112 if _, err := os.Stat(out); os.IsNotExist(err) { 113 return "", fmt.Errorf("failed normalizing file %s: %v", originalPath, err) 114 } 115 116 return out, nil 117 } 118 119 // ReadTarFile reads a tar compress file from the embedded 120 func ReadTarFile(filePath string) (string, error) { 121 b, err := os.ReadFile(filePath) 122 if err != nil { 123 return "", err 124 } 125 tr := tar.NewReader(bytes.NewBuffer(b)) 126 for { 127 hdr, err := tr.Next() 128 if err == io.EOF { 129 break // End of archive 130 } 131 if err != nil { 132 return "", err 133 } 134 if hdr.Name != strings.TrimSuffix(filepath.Base(filePath), filepath.Ext(filePath)) { 135 continue 136 } 137 contents, err := io.ReadAll(tr) 138 if err != nil { 139 return "", err 140 } 141 return string(contents), nil 142 } 143 return "", fmt.Errorf("file not found %v", filePath) 144 } 145 146 // ReadDir returns the names of all files in the given directory. This is not recursive. 147 // The base path is appended; for example, ReadDir("dir") -> ["dir/file1", "dir/folder1"] 148 func ReadDir(filePath string, extensions ...string) ([]string, error) { 149 dir, err := os.ReadDir(filePath) 150 if err != nil { 151 return nil, err 152 } 153 res := []string{} 154 for _, d := range dir { 155 matched := len(extensions) == 0 // If none are set, match anything 156 for _, ext := range extensions { 157 if filepath.Ext(d.Name()) == ext { 158 matched = true 159 break 160 } 161 } 162 if matched { 163 res = append(res, filepath.Join(filePath, d.Name())) 164 } 165 } 166 return res, nil 167 } 168 169 func ReadDirOrFail(t test.Failer, filePath string, extensions ...string) []string { 170 t.Helper() 171 res, err := ReadDir(filePath, extensions...) 172 if err != nil { 173 t.Fatal(err) 174 } 175 return res 176 } 177 178 func WriteOrFail(t test.Failer, filePath string, contents []byte) { 179 t.Helper() 180 err := os.WriteFile(filePath, contents, os.ModePerm) 181 if err != nil { 182 t.Fatal(err) 183 } 184 }