github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/resource/context/internal/download.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package internal 5 6 // TODO(ericsnow) Move this file elsewhere? 7 // (e.g. top-level resource pkg, charm/resource) 8 9 import ( 10 "io" 11 12 "github.com/juju/errors" 13 ) 14 15 // Download downloads the resource from the provied source to the target. 16 func Download(target DownloadTarget, remote ContentSource) error { 17 resDir, err := target.Initialize() 18 if err != nil { 19 return errors.Trace(err) 20 } 21 22 if err := resDir.Write(remote); err != nil { 23 return errors.Trace(err) 24 } 25 26 return nil 27 } 28 29 // DownloadIndirect downloads the resource from the source into a temp 30 // directory. Then the target is replaced by the temp directory. 31 func DownloadIndirect(target DownloadTarget, remote ContentSource, deps DownloadIndirectDeps) error { 32 tempDirSpec, err := deps.NewTempDirSpec() 33 defer deps.CloseAndLog(tempDirSpec, "resource temp dir") 34 if err != nil { 35 return errors.Trace(err) 36 } 37 38 if err := deps.DownloadDirect(tempDirSpec, remote); err != nil { 39 return errors.Trace(err) 40 } 41 42 resDir, err := target.Initialize() 43 if err != nil { 44 return errors.Trace(err) 45 } 46 47 oldDir := tempDirSpec.Resolve() 48 newDir := resDir.Resolve() 49 if err := deps.ReplaceDirectory(newDir, oldDir); err != nil { 50 return errors.Annotate(err, "could not replace existing resource directory") 51 } 52 53 return nil 54 } 55 56 // DownloadIndirectDeps exposes the external functionality needed 57 // by DownloadIndirect. 58 type DownloadIndirectDeps interface { 59 // NewTempDirSpec returns a directory spec for the resource under a temporary datadir. 60 NewTempDirSpec() (DownloadTempTarget, error) 61 62 // CloseAndLog closes the closer and logs any error. 63 CloseAndLog(io.Closer, string) 64 65 // DownloadDirect downloads the source into the target. 66 DownloadDirect(DownloadTarget, ContentSource) error 67 68 // ReplaceDirectory moves the source directory path to the target 69 // path. If the target path already exists then it is replaced atomically. 70 ReplaceDirectory(tgt, src string) error 71 } 72 73 // DownloadTarget exposes the functionality of a directory spec 74 // needed by Download(). 75 type DownloadTarget interface { 76 // Initialize prepares the target directory and returns it. 77 Initialize() (DownloadDirectory, error) 78 } 79 80 // DownloadDirectory exposes the functionality of a resource directory 81 // needed by Download(). 82 type DownloadDirectory interface { 83 Resolver 84 85 // Write writes all the relevant files for the provided source 86 // to the directory. 87 Write(ContentSource) error 88 } 89 90 // DownloadTempTarget represents a temporary download directory. 91 type DownloadTempTarget interface { 92 DownloadTarget 93 Resolver 94 io.Closer 95 } 96 97 // Resolver exposes the functionality of DirectorySpec needed 98 // by DownloadIndirect. 99 type Resolver interface { 100 // Resolve returns the fully resolved path for the provided path items. 101 Resolve(...string) string 102 }