Code change:
return &serverList[0], nil } <del> func findAddrs(netblob interface{}) []string { // Run-time types for the win :( ret := []string{} list, ok := netblob.([]interface{}) if !ok { return ret } for _, item := range list { props, ok := item.(map[string]interface{}) if !ok { continue } tmp, ok := props["addr"] </del> <ins> func getAddressesByName(client *gophercloud.ServiceClient, name string) ([]api.NodeAddress, error) { srv, err := getServerByName(client, name) if err != nil { return nil, err } addrs := []api.NodeAddress{} for network, netblob := range srv.Addresses { list, ok := netblob.([]interface{}) </ins> if !ok { continue } <del> addr, ok := tmp.(string) if !ok { continue </del> <ins> for _, item := range list { var addressType api.NodeAddressType props, ok := item.(map[string]interface{}) if !ok { continue } extIPType, ok := props["OS-EXT-IPS:type"] if (ok && extIPType == "floating") || (!ok && network == "public") { addressType = api.NodeExternalIP } else { addressType = api.NodeInternalIP } tmp, ok := props["addr"] if !ok { continue } addr, ok := tmp.(string) if !ok { continue } api.AddToNodeAddresses(&addrs, api.NodeAddress{ Type:    addressType, Address: addr, }, ) </ins> } <del> ret = append(ret, addr) </del> } <del> return ret </del> <ins> // AccessIPs are usually duplicates of "public" addresses. if srv.AccessIPv4 != "" { api.AddToNodeAddresses(&addrs, api.NodeAddress{ Type:    api.NodeExternalIP, Address: srv.AccessIPv4, }, ) } if srv.AccessIPv6 != "" { api.AddToNodeAddresses(&addrs, api.NodeAddress{ Type:    api.NodeExternalIP, Address: srv.AccessIPv6, }, ) } return addrs, nil </ins> } <del> func getAddressByName(api *gophercloud.ServiceClient, name string) (string, error) { srv, err := getServerByName(api, name) </del> <ins> func getAddressByName(client *gophercloud.ServiceClient, name string) (string, error) { addrs, err := getAddressesByName(client, name) </ins> if err != nil { return "", err <ins> } else if len(addrs) == 0 { return "", ErrNoAddressFound </ins> } <del> var s string if s == "" { if tmp := findAddrs(srv.Addresses["private"]); len(tmp) >= 1 { s = tmp[0] } } if s == "" { if tmp := findAddrs(srv.Addresses["public"]); len(tmp) >= 1 { s = tmp[0] </del> <ins> for _, addr := range addrs { if addr.Type == api.NodeInternalIP { return addr.Address, nil </ins> } } <del> if s == "" { s = srv.AccessIPv4 } if s == "" { s = srv.AccessIPv6 } if s == "" { return "", ErrNoAddressFound } return s, nil </del> <ins> return addrs[0].Address, nil </ins> } // Implementation of Instances.CurrentNodeName

Related discussion:
text: From we can find that, hardcode "private" and "public", seems only support that network with such name. , it fetch the first ip. usually, it can include both v6 and v4 ip. what's the meaning to just fetch the first one ? is it v4 or v6 ?
ping and
Yes. Zoom out a level or two in the code, and you'll see we're trying to either a) setup an openstack loadbalancer to point to the minion node (a single address) using , or b) report to kubernetes all the addresses we know about the node and whether they are "internal" or "external" in . All we have at the starting point is the server name (from kubernetes), and we need to make up the rest of this information somehow. (I agree (a) should reuse the NodeAddresses() function from (b), but the latter is a newer function and the code hasn't yet been refactored in that way. This doesn't really change the substance of this discussion.) Re (1): The logic as currently implemented is: Assume any network named "private" is "internal" Assume any network named "public" is "external" Assume the AccessIPs (IPv4 and IPv6) are "external" Any other network addresses are ignored. I implemented the first two ("private" and "public") following the Rackspace public cloud precedent, and on the basis that users in other OpenStack clouds can use these names if they want to encourage an address other than the Access addresses. For the (a) use case, we just take the first address we find in order of the above; for (b) we report that full list. I preferred "private" to "public" since (again, at least on Rackspace public cloud), the traffic on "private" network is sometimes cheaper/free. I agree this isn't great, and please suggest something better if you have a use case in mind. Perhaps we should pull a list of network names that should be considered "internal" and "external" from the provider config? Perhaps I could assume that provider networks are public and non-provider networks are internal? I don't want to add too much configuration here if there's a good algorithm that will Just Work.