func (c *configInternal) SetAPIHostPorts(servers [][]network.HostPort) { if c.apiDetails == nil { return } var addrs []string for _, serverHostPorts := range servers { // Try the preferred approach first. serverHP, ok := network.SelectHostPortBySpace(serverHostPorts, network.DefaultSpace) if ok { addrs = append(addrs, serverHP.NetAddr()) } else { // Fallback to the legacy approach. hps := network.SelectInternalHostPorts(serverHostPorts, false) addrs = append(addrs, hps...) } } c.apiDetails.addresses = addrs logger.Infof("API server address details %q written to agent config as %q", servers, addrs) }
// SetAPIHostPorts sets the addresses of the API server instances. // Each server is represented by one element in the top level slice. func (st *State) SetAPIHostPorts(netHostsPorts [][]network.HostPort) error { // Filter any addresses not on the default space, if possible. // All API servers need to be accessible there. var hpsToSet [][]network.HostPort for _, hps := range netHostsPorts { defaultSpaceHP, ok := network.SelectHostPortBySpace(hps, network.DefaultSpace) if !ok { logger.Warningf("cannot determine API addresses in space %q to use as API endpoints; using all addresses", network.DefaultSpace) hpsToSet = netHostsPorts break } hpsToSet = append(hpsToSet, []network.HostPort{defaultSpaceHP}) } doc := apiHostPortsDoc{ APIHostPorts: fromNetworkHostsPorts(hpsToSet), } buildTxn := func(attempt int) ([]txn.Op, error) { existing, err := st.APIHostPorts() if err != nil { return nil, err } op := txn.Op{ C: controllersC, Id: apiHostPortsKey, Assert: bson.D{{ "apihostports", fromNetworkHostsPorts(existing), }}, } if !hostsPortsEqual(netHostsPorts, existing) { op.Update = bson.D{{ "$set", bson.D{{"apihostports", doc.APIHostPorts}}, }} } return []txn.Op{op}, nil } if err := st.run(buildTxn); err != nil { return errors.Annotate(err, "cannot set API addresses") } logger.Debugf("setting API hostPorts: %v", hpsToSet) return nil }
// 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 bridge addresses. See LP bug #1416928. hpsToSet := make([][]network.HostPort, 0, len(addresses)) for _, hostPorts := range addresses { // First try to keep only addresses in the default space where all API servers are on. defaultSpaceHP, ok := network.SelectHostPortBySpace(hostPorts, network.DefaultSpace) if ok { hpsToSet = append(hpsToSet, []network.HostPort{defaultSpaceHP}) continue } else { // As a fallback, use the old behavior. logger.Warningf("cannot determine API addresses by space %q (using all as fallback)", network.DefaultSpace) } // Strip ports, filter, then add ports again. filtered := network.FilterLXCAddresses(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 }