github.com/google/cloudprober@v0.11.3/common/file/file.go (about) 1 // Copyright 2020 The Cloudprober 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 /* 16 Package file implements utilities to read files from various backends. 17 */ 18 package file 19 20 import ( 21 "context" 22 "errors" 23 "fmt" 24 "io/ioutil" 25 "net/http" 26 "os" 27 "strings" 28 "time" 29 30 "golang.org/x/oauth2/google" 31 ) 32 33 type readFunc func(path string) ([]byte, error) 34 type modTimeFunc func(path string) (time.Time, error) 35 36 var prefixToReadfunc = map[string]readFunc{ 37 "gs://": readFileFromGCS, 38 } 39 40 var prefixToModTimeFunc = map[string]modTimeFunc{ 41 "gs://": modTimeGCS, 42 } 43 44 func readFileFromGCS(objectPath string) ([]byte, error) { 45 hc, err := google.DefaultClient(context.Background()) 46 if err != nil { 47 return nil, err 48 } 49 50 objURL := "https://storage.googleapis.com/" + objectPath 51 res, err := hc.Get(objURL) 52 53 if err != nil { 54 return nil, err 55 } 56 57 if res.StatusCode != http.StatusOK { 58 return nil, fmt.Errorf("got error while retrieving GCS object, http status: %s, status code: %d", res.Status, res.StatusCode) 59 } 60 61 defer res.Body.Close() 62 return ioutil.ReadAll(res.Body) 63 } 64 65 func modTimeGCS(objectPath string) (time.Time, error) { 66 return time.Time{}, errors.New("mod-time is not implemented for GCS files yet") 67 } 68 69 // ReadFile returns file contents as a slice of bytes. It's similar to ioutil's 70 // ReadFile, but includes support for files on non-disk locations. For example, 71 // files with paths starting with gs:// are assumed to be on GCS, and are read 72 // from GCS. 73 func ReadFile(fname string) ([]byte, error) { 74 for prefix, f := range prefixToReadfunc { 75 if strings.HasPrefix(fname, prefix) { 76 return f(fname[len(prefix):]) 77 } 78 } 79 return ioutil.ReadFile(fname) 80 } 81 82 // ModTime returns file's modified timestamp. 83 func ModTime(fname string) (time.Time, error) { 84 for prefix, f := range prefixToModTimeFunc { 85 if strings.HasPrefix(fname, prefix) { 86 return f(fname[len(prefix):]) 87 } 88 } 89 90 statInfo, err := os.Stat(fname) 91 if err != nil { 92 return time.Time{}, err 93 } 94 return statInfo.ModTime(), nil 95 }