github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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  }