mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-16 18:08:40 +00:00
cmd/tailscale/cli: make exit-node list not random
The output was changing randomly per run, due to range over a map. Then some misc style tweaks I noticed while debugging. Fixes #11629 Change-Id: I67aef0e68566994e5744d4828002f6eb70810ee1 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
6e334e64a1
commit
ac2522092d
@ -70,7 +70,6 @@ func runExitNodeList(ctx context.Context, args []string) error {
|
|||||||
// We only show exit nodes under the exit-node subcommand.
|
// We only show exit nodes under the exit-node subcommand.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
peers = append(peers, ps)
|
peers = append(peers, ps)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +89,6 @@ func runExitNodeList(ctx context.Context, args []string) error {
|
|||||||
for _, country := range filteredPeers.Countries {
|
for _, country := range filteredPeers.Countries {
|
||||||
for _, city := range country.Cities {
|
for _, city := range country.Cities {
|
||||||
for _, peer := range city.Peers {
|
for _, peer := range city.Peers {
|
||||||
|
|
||||||
fmt.Fprintf(w, "\n %s\t%s\t%s\t%s\t%s\t", peer.TailscaleIPs[0], strings.Trim(peer.DNSName, "."), country.Name, city.Name, peerStatus(peer))
|
fmt.Fprintf(w, "\n %s\t%s\t%s\t%s\t%s\t", peer.TailscaleIPs[0], strings.Trim(peer.DNSName, "."), country.Name, city.Name, peerStatus(peer))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,46 +135,51 @@ type filteredCity struct {
|
|||||||
|
|
||||||
const noLocationData = "-"
|
const noLocationData = "-"
|
||||||
|
|
||||||
|
var noLocation = &tailcfg.Location{
|
||||||
|
Country: noLocationData,
|
||||||
|
CountryCode: noLocationData,
|
||||||
|
City: noLocationData,
|
||||||
|
CityCode: noLocationData,
|
||||||
|
}
|
||||||
|
|
||||||
// filterFormatAndSortExitNodes filters and sorts exit nodes into
|
// filterFormatAndSortExitNodes filters and sorts exit nodes into
|
||||||
// alphabetical order, by country, city and then by priority if
|
// alphabetical order, by country, city and then by priority if
|
||||||
// present.
|
// present.
|
||||||
// If an exit node has location data, and the country has more than
|
// If an exit node has location data, and the country has more than
|
||||||
// once city, an `Any` city is added to the country that contains the
|
// one city, an `Any` city is added to the country that contains the
|
||||||
// highest priority exit node within that country.
|
// highest priority exit node within that country.
|
||||||
// For exit nodes without location data, their country fields are
|
// For exit nodes without location data, their country fields are
|
||||||
// defined as '-' to indicate that the data is not available.
|
// defined as '-' to indicate that the data is not available.
|
||||||
func filterFormatAndSortExitNodes(peers []*ipnstate.PeerStatus, filterBy string) filteredExitNodes {
|
func filterFormatAndSortExitNodes(peers []*ipnstate.PeerStatus, filterBy string) filteredExitNodes {
|
||||||
|
// first get peers into some fixed order, as code below doesn't break ties
|
||||||
|
// and our input comes from a random range-over-map.
|
||||||
|
slices.SortFunc(peers, func(a, b *ipnstate.PeerStatus) int {
|
||||||
|
return strings.Compare(a.DNSName, b.DNSName)
|
||||||
|
})
|
||||||
|
|
||||||
countries := make(map[string]*filteredCountry)
|
countries := make(map[string]*filteredCountry)
|
||||||
cities := make(map[string]*filteredCity)
|
cities := make(map[string]*filteredCity)
|
||||||
for _, ps := range peers {
|
for _, ps := range peers {
|
||||||
if ps.Location == nil {
|
loc := cmp.Or(ps.Location, noLocation)
|
||||||
ps.Location = &tailcfg.Location{
|
|
||||||
Country: noLocationData,
|
|
||||||
CountryCode: noLocationData,
|
|
||||||
City: noLocationData,
|
|
||||||
CityCode: noLocationData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if filterBy != "" && ps.Location.Country != filterBy {
|
if filterBy != "" && loc.Country != filterBy {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
co, coOK := countries[ps.Location.CountryCode]
|
co, ok := countries[loc.CountryCode]
|
||||||
if !coOK {
|
if !ok {
|
||||||
co = &filteredCountry{
|
co = &filteredCountry{
|
||||||
Name: ps.Location.Country,
|
Name: loc.Country,
|
||||||
}
|
}
|
||||||
countries[ps.Location.CountryCode] = co
|
countries[loc.CountryCode] = co
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ci, ciOK := cities[ps.Location.CityCode]
|
ci, ok := cities[loc.CityCode]
|
||||||
if !ciOK {
|
if !ok {
|
||||||
ci = &filteredCity{
|
ci = &filteredCity{
|
||||||
Name: ps.Location.City,
|
Name: loc.City,
|
||||||
}
|
}
|
||||||
cities[ps.Location.CityCode] = ci
|
cities[loc.CityCode] = ci
|
||||||
co.Cities = append(co.Cities, ci)
|
co.Cities = append(co.Cities, ci)
|
||||||
}
|
}
|
||||||
ci.Peers = append(ci.Peers, ps)
|
ci.Peers = append(ci.Peers, ps)
|
||||||
@ -193,10 +196,10 @@ func filterFormatAndSortExitNodes(peers []*ipnstate.PeerStatus, filterBy string)
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var countryANYPeer []*ipnstate.PeerStatus
|
var countryAnyPeer []*ipnstate.PeerStatus
|
||||||
for _, city := range country.Cities {
|
for _, city := range country.Cities {
|
||||||
sortPeersByPriority(city.Peers)
|
sortPeersByPriority(city.Peers)
|
||||||
countryANYPeer = append(countryANYPeer, city.Peers...)
|
countryAnyPeer = append(countryAnyPeer, city.Peers...)
|
||||||
var reducedCityPeers []*ipnstate.PeerStatus
|
var reducedCityPeers []*ipnstate.PeerStatus
|
||||||
for i, peer := range city.Peers {
|
for i, peer := range city.Peers {
|
||||||
if i == 0 || peer.ExitNode {
|
if i == 0 || peer.ExitNode {
|
||||||
@ -208,7 +211,7 @@ func filterFormatAndSortExitNodes(peers []*ipnstate.PeerStatus, filterBy string)
|
|||||||
city.Peers = reducedCityPeers
|
city.Peers = reducedCityPeers
|
||||||
}
|
}
|
||||||
sortByCityName(country.Cities)
|
sortByCityName(country.Cities)
|
||||||
sortPeersByPriority(countryANYPeer)
|
sortPeersByPriority(countryAnyPeer)
|
||||||
|
|
||||||
if len(country.Cities) > 1 {
|
if len(country.Cities) > 1 {
|
||||||
// For countries with more than one city, we want to return the
|
// For countries with more than one city, we want to return the
|
||||||
@ -216,7 +219,7 @@ func filterFormatAndSortExitNodes(peers []*ipnstate.PeerStatus, filterBy string)
|
|||||||
country.Cities = append([]*filteredCity{
|
country.Cities = append([]*filteredCity{
|
||||||
{
|
{
|
||||||
Name: "Any",
|
Name: "Any",
|
||||||
Peers: []*ipnstate.PeerStatus{countryANYPeer[0]},
|
Peers: []*ipnstate.PeerStatus{countryAnyPeer[0]},
|
||||||
},
|
},
|
||||||
}, country.Cities...)
|
}, country.Cities...)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user