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