github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/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/charm" 11 "github.com/juju/loggo" 12 "github.com/juju/utils" 13 "github.com/juju/utils/set" 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 // Archive URL returns the location of the bundle data. 43 ArchiveURL() (*url.URL, utils.SSLHostnameVerification, error) 44 45 // ArchiveSha256 returns the hex-encoded SHA-256 digest of the bundle data. 46 ArchiveSha256() (string, error) 47 } 48 49 // BundleReader provides a mechanism for getting a Bundle from a BundleInfo. 50 type BundleReader interface { 51 52 // Read returns the bundle identified by the supplied info. The abort chan 53 // can be used to notify an implementation that it need not complete the 54 // operation, and can immediately error out if it is convenient to do so. 55 Read(bi BundleInfo, abort <-chan struct{}) (Bundle, error) 56 } 57 58 // Deployer is responsible for installing and upgrading charms. 59 type Deployer interface { 60 61 // Stage must be called to prime the Deployer to install or upgrade the 62 // bundle identified by the supplied info. The abort chan can be used to 63 // notify an implementation that it need not complete the operation, and 64 // can immediately error out if it convenient to do so. It must always 65 // be safe to restage the same bundle, or to stage a new bundle. 66 Stage(info BundleInfo, abort <-chan struct{}) error 67 68 // Deploy will install or upgrade the most recently staged bundle. 69 // Behaviour is undefined if Stage has not been called. Failures that 70 // can be resolved by user intervention will be signalled by returning 71 // ErrConflict. 72 Deploy() error 73 74 // NotifyRevert must be called when a conflicted deploy is abandoned, in 75 // preparation for a new upgrade. 76 NotifyRevert() error 77 78 // NotifyResolved must be called when the cause of a deploy conflict has 79 // been resolved, and a new deploy attempt will be made. 80 NotifyResolved() error 81 } 82 83 // ErrConflict indicates that an upgrade failed and cannot be resolved 84 // without human intervention. 85 var ErrConflict = errors.New("charm upgrade has conflicts") 86 87 // ReadCharmURL reads a charm identity file from the supplied path. 88 func ReadCharmURL(path string) (*charm.URL, error) { 89 surl := "" 90 if err := utils.ReadYaml(path, &surl); err != nil { 91 return nil, err 92 } 93 return charm.ParseURL(surl) 94 } 95 96 // WriteCharmURL writes a charm identity file into the supplied path. 97 func WriteCharmURL(path string, url *charm.URL) error { 98 return utils.WriteYaml(path, url.String()) 99 }