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