github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/resource/context/context.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package context 5 6 import ( 7 "io" 8 "os" 9 "path/filepath" 10 11 "github.com/juju/errors" 12 "github.com/juju/loggo" 13 "github.com/juju/utils" 14 charmresource "gopkg.in/juju/charm.v6/resource" 15 16 "github.com/juju/juju/resource" 17 "github.com/juju/juju/resource/context/internal" 18 ) 19 20 var logger = loggo.GetLogger("juju.resource.context") 21 22 // HookContextFacade is the name of the API facade for resources in the uniter. 23 const HookContextFacade = "ResourcesHookContext" 24 25 // APIClient exposes the uniter API functionality needed for resources. 26 type APIClient interface { 27 // GetResource returns the resource info and content for the given 28 // name (and unit-implied application). 29 GetResource(resourceName string) (resource.Resource, io.ReadCloser, error) 30 } 31 32 // Content is the resources portion of a uniter hook context. 33 type Context struct { 34 apiClient APIClient 35 36 // dataDir is the path to the directory where all resources are 37 // stored for a unit. It will look something like this: 38 // 39 // /var/lib/juju/agents/unit-spam-1/resources 40 dataDir string 41 } 42 43 // NewContextAPI returns a new Content for the given API client and data dir. 44 func NewContextAPI(apiClient APIClient, dataDir string) *Context { 45 return &Context{ 46 apiClient: apiClient, 47 dataDir: dataDir, 48 } 49 } 50 51 // Flush implements hooks.Context. 52 func (c *Context) Flush() error { 53 return nil 54 } 55 56 // Download downloads the named resource and returns the path 57 // to which it was downloaded. If the resource does not exist or has 58 // not been uploaded yet then errors.NotFound is returned. 59 // 60 // Note that the downloaded file is checked for correctness. 61 func (c *Context) Download(name string) (string, error) { 62 deps := &contextDeps{ 63 APIClient: c.apiClient, 64 name: name, 65 dataDir: c.dataDir, 66 } 67 path, err := internal.ContextDownload(deps) 68 if err != nil { 69 return "", errors.Trace(err) 70 } 71 return path, nil 72 } 73 74 // contextDeps implements all the external dependencies 75 // of ContextDownload(). 76 type contextDeps struct { 77 APIClient 78 name string 79 dataDir string 80 } 81 82 func (deps *contextDeps) NewContextDirectorySpec() internal.ContextDirectorySpec { 83 return internal.NewContextDirectorySpec(deps.dataDir, deps.name, deps) 84 } 85 86 func (deps *contextDeps) OpenResource() (internal.ContextOpenedResource, error) { 87 return internal.OpenResource(deps.name, deps) 88 } 89 90 func (deps *contextDeps) Download(target internal.DownloadTarget, remote internal.ContextOpenedResource) error { 91 return internal.Download(target, remote) 92 } 93 94 func (deps *contextDeps) WriteContent(target io.Writer, content internal.Content) error { 95 return internal.WriteContent(target, content, deps) 96 } 97 98 func (deps contextDeps) CloseAndLog(closer io.Closer, label string) { 99 internal.CloseAndLog(closer, label, logger) 100 } 101 102 func (deps contextDeps) MkdirAll(dirname string) error { 103 return os.MkdirAll(dirname, 0755) 104 } 105 106 func (deps contextDeps) CreateWriter(filename string) (io.WriteCloser, error) { 107 // TODO(ericsnow) chmod 0644? 108 return os.Create(filename) 109 } 110 111 func (deps contextDeps) RemoveDir(dirname string) error { 112 return os.RemoveAll(dirname) 113 } 114 115 func (deps contextDeps) Copy(target io.Writer, source io.Reader) error { 116 _, err := io.Copy(target, source) 117 return err 118 } 119 120 func (deps contextDeps) FingerprintMatches(filename string, expected charmresource.Fingerprint) (bool, error) { 121 return FingerprintMatcher{}.FingerprintMatches(filename, expected) 122 } 123 124 func (deps contextDeps) Join(path ...string) string { 125 return filepath.Join(path...) 126 } 127 128 func (deps contextDeps) NewChecker(content internal.Content) internal.ContentChecker { 129 var sizer utils.SizeTracker 130 checksumWriter := charmresource.NewFingerprintHash() 131 return internal.NewContentChecker(content, &sizer, checksumWriter) 132 }