cmd/tailscale/cli: exit node filter should display all exit node options (#12699)

This change expands the `exit-node list -filter` command to display all
location based exit nodes for the filtered country. This allows users
to switch to alternative servers when our recommended exit node is not
working as intended.

This change also makes the country filter matching case insensitive,
e.g. both USA and usa will work.

Updates #12698

Signed-off-by: Charlotte Brandhorst-Satzkorn <charlotte@tailscale.com>
This commit is contained in:
Charlotte Brandhorst-Satzkorn 2024-07-03 11:48:20 -07:00 committed by GitHub
parent 59936e6d4a
commit 42f01afe26
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 4 deletions

View File

@ -137,6 +137,7 @@ func runExitNodeList(ctx context.Context, args []string) error {
} }
fmt.Fprintln(w) fmt.Fprintln(w)
fmt.Fprintln(w) fmt.Fprintln(w)
fmt.Fprintln(w, "# To view the complete list of exit nodes for a country, use `tailscale exit-node list --filter=` followed by the country name.")
fmt.Fprintln(w, "# To use an exit node, use `tailscale set --exit-node=` followed by the hostname or IP.") fmt.Fprintln(w, "# To use an exit node, use `tailscale set --exit-node=` followed by the hostname or IP.")
if hasAnyExitNodeSuggestions(peers) { if hasAnyExitNodeSuggestions(peers) {
fmt.Fprintln(w, "# To have Tailscale suggest an exit node, use `tailscale exit-node suggest`.") fmt.Fprintln(w, "# To have Tailscale suggest an exit node, use `tailscale exit-node suggest`.")
@ -231,7 +232,7 @@ func filterFormatAndSortExitNodes(peers []*ipnstate.PeerStatus, filterBy string)
for _, ps := range peers { for _, ps := range peers {
loc := cmp.Or(ps.Location, noLocation) loc := cmp.Or(ps.Location, noLocation)
if filterBy != "" && loc.Country != filterBy { if filterBy != "" && !strings.EqualFold(loc.Country, filterBy) {
continue continue
} }
@ -271,9 +272,14 @@ func filterFormatAndSortExitNodes(peers []*ipnstate.PeerStatus, filterBy string)
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 filterBy != "" {
// We only return the highest priority peer and any peer that // If the peers are being filtered, we return all peers to the user.
reducedCityPeers = append(reducedCityPeers, city.Peers...)
break
}
// If the peers are not being filtered, we only return the highest priority peer and any peer that
// is currently the active exit node. // is currently the active exit node.
if i == 0 || peer.ExitNode {
reducedCityPeers = append(reducedCityPeers, peer) reducedCityPeers = append(reducedCityPeers, peer)
} }
} }

View File

@ -219,7 +219,7 @@ func TestFilterFormatAndSortExitNodes(t *testing.T) {
{ {
Name: "Rainier", Name: "Rainier",
Peers: []*ipnstate.PeerStatus{ Peers: []*ipnstate.PeerStatus{
ps[2], ps[2], ps[3],
}, },
}, },
}, },