~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/resource/context/context.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
        "io/ioutil"
 
9
        "os"
 
10
        "path/filepath"
 
11
 
 
12
        "github.com/juju/errors"
 
13
        "github.com/juju/loggo"
 
14
        "github.com/juju/utils"
 
15
        charmresource "gopkg.in/juju/charm.v6-unstable/resource"
 
16
 
 
17
        "github.com/juju/juju/resource"
 
18
        "github.com/juju/juju/resource/context/internal"
 
19
)
 
20
 
 
21
var logger = loggo.GetLogger("juju.resource.context")
 
22
 
 
23
// HookContextFacade is the name of the API facade for resources in the uniter.
 
24
const HookContextFacade = "ResourcesHookContext"
 
25
 
 
26
// APIClient exposes the uniter API functionality needed for resources.
 
27
type APIClient interface {
 
28
        // GetResource returns the resource info and content for the given
 
29
        // name (and unit-implied application).
 
30
        GetResource(resourceName string) (resource.Resource, io.ReadCloser, error)
 
31
}
 
32
 
 
33
// Content is the resources portion of a uniter hook context.
 
34
type Context struct {
 
35
        apiClient APIClient
 
36
 
 
37
        // dataDir is the path to the directory where all resources are
 
38
        // stored for a unit. It will look something like this:
 
39
        //
 
40
        //   /var/lib/juju/agents/unit-spam-1/resources
 
41
        dataDir string
 
42
}
 
43
 
 
44
// NewContextAPI returns a new Content for the given API client and data dir.
 
45
func NewContextAPI(apiClient APIClient, dataDir string) *Context {
 
46
        return &Context{
 
47
                apiClient: apiClient,
 
48
                dataDir:   dataDir,
 
49
        }
 
50
}
 
51
 
 
52
// Flush implements jujuc.Context.
 
53
func (c *Context) Flush() error {
 
54
        return nil
 
55
}
 
56
 
 
57
// Download downloads the named resource and returns the path
 
58
// to which it was downloaded. If the resource does not exist or has
 
59
// not been uploaded yet then errors.NotFound is returned.
 
60
//
 
61
// Note that the downloaded file is checked for correctness.
 
62
func (c *Context) Download(name string) (string, error) {
 
63
        deps := &contextDeps{
 
64
                APIClient: c.apiClient,
 
65
                name:      name,
 
66
                dataDir:   c.dataDir,
 
67
        }
 
68
        path, err := internal.ContextDownload(deps)
 
69
        if err != nil {
 
70
                return "", errors.Trace(err)
 
71
        }
 
72
        return path, nil
 
73
}
 
74
 
 
75
// contextDeps implements all the external dependencies
 
76
// of ContextDownload().
 
77
type contextDeps struct {
 
78
        APIClient
 
79
        name    string
 
80
        dataDir string
 
81
}
 
82
 
 
83
func (deps *contextDeps) NewContextDirectorySpec() internal.ContextDirectorySpec {
 
84
        return internal.NewContextDirectorySpec(deps.dataDir, deps.name, deps)
 
85
}
 
86
 
 
87
func (deps *contextDeps) OpenResource() (internal.ContextOpenedResource, error) {
 
88
        return internal.OpenResource(deps.name, deps)
 
89
}
 
90
 
 
91
func (deps *contextDeps) Download(target internal.DownloadTarget, remote internal.ContextOpenedResource) error {
 
92
        return internal.DownloadIndirect(target, remote, deps)
 
93
}
 
94
 
 
95
func (deps *contextDeps) DownloadDirect(target internal.DownloadTarget, remote internal.ContentSource) error {
 
96
        return internal.Download(target, remote)
 
97
}
 
98
 
 
99
func (deps *contextDeps) ReplaceDirectory(tgt, src string) error {
 
100
        return internal.ReplaceDirectory(tgt, src, deps)
 
101
}
 
102
 
 
103
func (deps *contextDeps) NewTempDirSpec() (internal.DownloadTempTarget, error) {
 
104
        spec, err := internal.NewTempDirectorySpec(deps.name, deps)
 
105
        if err != nil {
 
106
                return nil, errors.Trace(err)
 
107
        }
 
108
        dir := &internal.ContextDownloadDirectory{
 
109
                spec,
 
110
        }
 
111
        return dir, nil
 
112
}
 
113
 
 
114
func (deps *contextDeps) WriteContent(target io.Writer, content internal.Content) error {
 
115
        return internal.WriteContent(target, content, deps)
 
116
}
 
117
 
 
118
func (deps contextDeps) CloseAndLog(closer io.Closer, label string) {
 
119
        internal.CloseAndLog(closer, label, logger)
 
120
}
 
121
 
 
122
func (deps contextDeps) MkdirAll(dirname string) error {
 
123
        return os.MkdirAll(dirname, 0755)
 
124
}
 
125
 
 
126
func (deps contextDeps) CreateWriter(filename string) (io.WriteCloser, error) {
 
127
        // TODO(ericsnow) chmod 0644?
 
128
        return os.Create(filename)
 
129
}
 
130
 
 
131
func (deps contextDeps) NewTempDir() (string, error) {
 
132
        return ioutil.TempDir("", "juju-resource-")
 
133
}
 
134
 
 
135
func (deps contextDeps) RemoveDir(dirname string) error {
 
136
        return os.RemoveAll(dirname)
 
137
}
 
138
 
 
139
func (deps contextDeps) Move(target, source string) error {
 
140
        // Note that we follow the io.Copy() argument arder here
 
141
        // (os.Rename does not).
 
142
        return os.Rename(source, target)
 
143
}
 
144
 
 
145
func (deps contextDeps) Copy(target io.Writer, source io.Reader) error {
 
146
        _, err := io.Copy(target, source)
 
147
        return err
 
148
}
 
149
 
 
150
func (deps contextDeps) FingerprintMatches(filename string, expected charmresource.Fingerprint) (bool, error) {
 
151
        return FingerprintMatcher{}.FingerprintMatches(filename, expected)
 
152
}
 
153
 
 
154
func (deps contextDeps) Join(path ...string) string {
 
155
        return filepath.Join(path...)
 
156
}
 
157
 
 
158
func (deps contextDeps) NewChecker(content internal.Content) internal.ContentChecker {
 
159
        var sizer utils.SizeTracker
 
160
        checksumWriter := charmresource.NewFingerprintHash()
 
161
        return internal.NewContentChecker(content, &sizer, checksumWriter)
 
162
}