github.com/Datadog/cnab-go@v0.3.3-beta1.0.20191007143216-bba4b7e723d0/bundle/loader/loader.go (about) 1 package loader 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net/http" 7 "net/url" 8 "os" 9 10 "github.com/deislabs/cnab-go/bundle" 11 ) 12 13 // BundleLoader provides an interface for loading a bundle 14 type BundleLoader interface { 15 // Load a bundle from a local file 16 Load(source string) (*bundle.Bundle, error) 17 // Load a bundle from raw data 18 LoadData(data []byte) (*bundle.Bundle, error) 19 } 20 21 // Loader loads a bundle manifest (bundle.json) 22 type Loader struct{} 23 24 // New creates a loader for bundle files. 25 //TODO: remove if unnecessary 26 func New() BundleLoader { 27 return &Loader{} 28 } 29 30 func NewLoader() *Loader { 31 return &Loader{} 32 } 33 34 // Load loads the given bundle. 35 func (l *Loader) Load(filename string) (*bundle.Bundle, error) { 36 b := &bundle.Bundle{} 37 data, err := loadData(filename) 38 if err != nil { 39 return b, err 40 } 41 return l.LoadData(data) 42 } 43 44 // LoadData loads a Bundle from the given data. 45 // 46 // This loads a JSON bundle file into a *bundle.Bundle. 47 func (l *Loader) LoadData(data []byte) (*bundle.Bundle, error) { 48 return bundle.Unmarshal(data) 49 } 50 51 // loadData is a utility method that loads a file either off of the FS (if it exists) or via a remote HTTP GET. 52 // 53 // If bundleFile exists on disk, this will return that file. Otherwise, it will attempt to parse the 54 // file name as a URL and request it as an HTTP GET request. 55 func loadData(bundleFile string) ([]byte, error) { 56 if isLocalReference(bundleFile) { 57 return ioutil.ReadFile(bundleFile) 58 } 59 60 if u, err := url.ParseRequestURI(bundleFile); err != nil { 61 // The error emitted by ParseRequestURI is icky. 62 return []byte{}, fmt.Errorf("bundle %q not found", bundleFile) 63 } else if u.Scheme == "file" { 64 // What do we do if someone passes a `file:///` URL in? Is `file` inferred 65 // if no protocol is specified? 66 return []byte{}, fmt.Errorf("bundle %q not found", bundleFile) 67 } 68 69 response, err := http.Get(bundleFile) 70 if err != nil { 71 return []byte{}, fmt.Errorf("cannot download bundle file: %v", err) 72 } 73 defer response.Body.Close() 74 75 return ioutil.ReadAll(response.Body) 76 } 77 78 func isLocalReference(file string) bool { 79 _, err := os.Stat(file) 80 return err == nil 81 }