github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/apiaddressupdater/apiaddressupdater.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package apiaddressupdater 5 6 import ( 7 "fmt" 8 9 "github.com/juju/errors" 10 "github.com/juju/loggo" 11 12 "github.com/juju/juju/network" 13 "github.com/juju/juju/watcher" 14 "github.com/juju/juju/worker" 15 ) 16 17 var logger = loggo.GetLogger("juju.worker.apiaddressupdater") 18 19 // APIAddressUpdater is responsible for propagating API addresses. 20 // 21 // In practice, APIAddressUpdater is used by a machine agent to watch 22 // API addresses in state and write the changes to the agent's config file. 23 type APIAddressUpdater struct { 24 addresser APIAddresser 25 setter APIAddressSetter 26 } 27 28 // APIAddresser is an interface that is provided to NewAPIAddressUpdater 29 // which can be used to watch for API address changes. 30 type APIAddresser interface { 31 APIHostPorts() ([][]network.HostPort, error) 32 WatchAPIHostPorts() (watcher.NotifyWatcher, error) 33 } 34 35 // APIAddressSetter is an interface that is provided to NewAPIAddressUpdater 36 // whose SetAPIHostPorts method will be invoked whenever address changes occur. 37 type APIAddressSetter interface { 38 SetAPIHostPorts(servers [][]network.HostPort) error 39 } 40 41 // NewAPIAddressUpdater returns a worker.Worker that watches for changes to 42 // API addresses and then sets them on the APIAddressSetter. 43 // TODO(fwereade): this should have a config struct, and some validation. 44 func NewAPIAddressUpdater(addresser APIAddresser, setter APIAddressSetter) (worker.Worker, error) { 45 handler := &APIAddressUpdater{ 46 addresser: addresser, 47 setter: setter, 48 } 49 w, err := watcher.NewNotifyWorker(watcher.NotifyConfig{ 50 Handler: handler, 51 }) 52 if err != nil { 53 return nil, errors.Trace(err) 54 } 55 return w, nil 56 } 57 58 // SetUp is part of the watcher.NotifyHandler interface. 59 func (c *APIAddressUpdater) SetUp() (watcher.NotifyWatcher, error) { 60 return c.addresser.WatchAPIHostPorts() 61 } 62 63 // Handle is part of the watcher.NotifyHandler interface. 64 func (c *APIAddressUpdater) Handle(_ <-chan struct{}) error { 65 addresses, err := c.addresser.APIHostPorts() 66 if err != nil { 67 return fmt.Errorf("error getting addresses: %v", err) 68 } 69 70 // Filter out any LXC or LXD bridge addresses. See LP bug #1416928. and 71 // bug #1567683 72 hpsToSet := make([][]network.HostPort, 0, len(addresses)) 73 for _, hostPorts := range addresses { 74 // Strip ports, filter, then add ports again. 75 filtered := network.FilterBridgeAddresses(network.HostsWithoutPort(hostPorts)) 76 hps := make([]network.HostPort, 0, len(filtered)) 77 for _, hostPort := range hostPorts { 78 for _, addr := range filtered { 79 if addr.Value == hostPort.Address.Value { 80 hps = append(hps, hostPort) 81 } 82 } 83 } 84 if len(hps) > 0 { 85 hpsToSet = append(hpsToSet, hps) 86 } 87 } 88 logger.Debugf("updating API hostPorts to %+v", hpsToSet) 89 if err := c.setter.SetAPIHostPorts(hpsToSet); err != nil { 90 return fmt.Errorf("error setting addresses: %v", err) 91 } 92 return nil 93 } 94 95 // TearDown is part of the watcher.NotifyHandler interface. 96 func (c *APIAddressUpdater) TearDown() error { 97 return nil 98 }