github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/caasbroker/broker.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package caasbroker 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/loggo" 9 "gopkg.in/juju/worker.v1/catacomb" 10 11 "github.com/juju/juju/caas" 12 "github.com/juju/juju/environs" 13 "github.com/juju/juju/environs/config" 14 ) 15 16 var logger = loggo.GetLogger("juju.worker.caas") 17 18 // ConfigAPI exposes a model configuration and a watch constructor 19 // that allows clients to be informed of changes to the configuration. 20 type ConfigAPI interface { 21 CloudSpec() (environs.CloudSpec, error) 22 ModelConfig() (*config.Config, error) 23 } 24 25 // Config describes the dependencies of a Tracker. 26 // 27 // It's arguable that it should be called TrackerConfig, because of the heavy 28 // use of model config in this package. 29 type Config struct { 30 ConfigAPI ConfigAPI 31 NewContainerBrokerFunc caas.NewContainerBrokerFunc 32 } 33 34 // Validate returns an error if the config cannot be used to start a Tracker. 35 func (config Config) Validate() error { 36 if config.ConfigAPI == nil { 37 return errors.NotValidf("nil ConfigAPI") 38 } 39 if config.NewContainerBrokerFunc == nil { 40 return errors.NotValidf("nil NewContainerBrokerFunc") 41 } 42 return nil 43 } 44 45 // Tracker loads a caas broker, makes it available to clients, and updates 46 // the broker in response to config changes until it is killed. 47 type Tracker struct { 48 config Config 49 catacomb catacomb.Catacomb 50 broker caas.Broker 51 } 52 53 // NewTracker returns a new Tracker, or an error if anything goes wrong. 54 // If a tracker is returned, its Broker() method is immediately usable. 55 // 56 // The caller is responsible for Kill()ing the returned Tracker and Wait()ing 57 // for any errors it might return. 58 func NewTracker(config Config) (*Tracker, error) { 59 if err := config.Validate(); err != nil { 60 return nil, errors.Trace(err) 61 } 62 cloudSpec, err := config.ConfigAPI.CloudSpec() 63 if err != nil { 64 return nil, errors.Annotate(err, "cannot get cloud information") 65 } 66 cfg, err := config.ConfigAPI.ModelConfig() 67 if err != nil { 68 return nil, errors.Trace(err) 69 } 70 broker, err := config.NewContainerBrokerFunc(environs.OpenParams{ 71 Cloud: cloudSpec, 72 Config: cfg, 73 }) 74 if err != nil { 75 return nil, errors.Annotate(err, "cannot create caas broker") 76 } 77 78 t := &Tracker{ 79 config: config, 80 broker: broker, 81 } 82 err = catacomb.Invoke(catacomb.Plan{ 83 Site: &t.catacomb, 84 Work: t.loop, 85 }) 86 if err != nil { 87 return nil, errors.Trace(err) 88 } 89 return t, nil 90 } 91 92 // Broker returns the encapsulated Broker. It will continue to be updated in 93 // the background for as long as the Tracker continues to run. 94 func (t *Tracker) Broker() caas.Broker { 95 return t.broker 96 } 97 98 func (t *Tracker) loop() error { 99 // TODO(caas) - watch for config and credential changes 100 for { 101 logger.Debugf("waiting for config and credential notifications") 102 select { 103 case <-t.catacomb.Dying(): 104 return t.catacomb.ErrDying() 105 } 106 } 107 } 108 109 // Kill is part of the worker.Worker interface. 110 func (t *Tracker) Kill() { 111 t.catacomb.Kill(nil) 112 } 113 114 // Wait is part of the worker.Worker interface. 115 func (t *Tracker) Wait() error { 116 return t.catacomb.Wait() 117 }