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  }