1
// Copyright 2012-2014 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
9
"github.com/juju/loggo"
10
"github.com/juju/utils"
11
"github.com/juju/utils/set"
12
"gopkg.in/juju/charm.v6-unstable"
15
var logger = loggo.GetLogger("juju.worker.uniter.charm")
17
// CharmURLPath is the path within a charm directory to which Deployers
18
// commonly write the charm URL of the latest deployed charm.
19
const CharmURLPath = ".juju-charm"
21
// Bundle allows access to a charm's files.
22
type Bundle interface {
24
// Manifest returns a set of slash-separated strings representing files,
25
// directories, and symlinks stored in the bundle.
26
Manifest() (set.Strings, error)
28
// ExpandTo unpacks the entities referenced in the manifest into the
29
// supplied directory. If it returns without error, every file referenced
30
// in the charm must be present in the directory; implementations may vary
31
// in the details of what they do with other files present.
32
ExpandTo(dir string) error
35
// BundleInfo describes a Bundle.
36
type BundleInfo interface {
38
// URL returns the charm URL identifying the bundle.
41
// ArchiveSha256 returns the hex-encoded SHA-256 digest of the bundle data.
42
ArchiveSha256() (string, error)
45
// BundleReader provides a mechanism for getting a Bundle from a BundleInfo.
46
type BundleReader interface {
48
// Read returns the bundle identified by the supplied info. The abort chan
49
// can be used to notify an implementation that it need not complete the
50
// operation, and can immediately error out if it is convenient to do so.
51
Read(bi BundleInfo, abort <-chan struct{}) (Bundle, error)
54
// Deployer is responsible for installing and upgrading charms.
55
type Deployer interface {
57
// Stage must be called to prime the Deployer to install or upgrade the
58
// bundle identified by the supplied info. The abort chan can be used to
59
// notify an implementation that it need not complete the operation, and
60
// can immediately error out if it convenient to do so. It must always
61
// be safe to restage the same bundle, or to stage a new bundle.
62
Stage(info BundleInfo, abort <-chan struct{}) error
64
// Deploy will install or upgrade the most recently staged bundle.
65
// Behaviour is undefined if Stage has not been called. Failures that
66
// can be resolved by user intervention will be signalled by returning
70
// NotifyRevert must be called when a conflicted deploy is abandoned, in
71
// preparation for a new upgrade.
74
// NotifyResolved must be called when the cause of a deploy conflict has
75
// been resolved, and a new deploy attempt will be made.
76
NotifyResolved() error
79
// ErrConflict indicates that an upgrade failed and cannot be resolved
80
// without human intervention.
81
var ErrConflict = errors.New("charm upgrade has conflicts")
83
// ReadCharmURL reads a charm identity file from the supplied path.
84
func ReadCharmURL(path string) (*charm.URL, error) {
86
if err := utils.ReadYaml(path, &surl); err != nil {
89
return charm.ParseURL(surl)
92
// WriteCharmURL writes a charm identity file into the supplied path.
93
func WriteCharmURL(path string, url *charm.URL) error {
94
return utils.WriteYaml(path, url.String())