mirror of
https://github.com/tailscale/tailscale.git
synced 2026-04-03 06:02:30 -04:00
cmd/tailscale: add service list command
This commit is contained in:
@@ -1422,3 +1422,13 @@ func (lc *Client) GetAppConnectorRouteInfo(ctx context.Context) (appctype.RouteI
|
||||
}
|
||||
return decodeJSON[appctype.RouteInfo](body)
|
||||
}
|
||||
|
||||
// GetServices returns the list of VIP services visible to this node,
|
||||
// including their names, IP addresses, and ports.
|
||||
func (lc *Client) GetServices(ctx context.Context) ([]*tailcfg.ServiceDetail, error) {
|
||||
body, err := lc.get200(ctx, "/localapi/v0/services")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return decodeJSON[[]*tailcfg.ServiceDetail](body)
|
||||
}
|
||||
|
||||
@@ -269,6 +269,7 @@ func newRootCmd() *ffcli.Command {
|
||||
nilOrCall(maybeNetlockCmd),
|
||||
licensesCmd,
|
||||
exitNodeCmd(),
|
||||
servicesCmd(),
|
||||
nilOrCall(maybeUpdateCmd),
|
||||
whoisCmd,
|
||||
debugCmd(),
|
||||
|
||||
68
cmd/tailscale/cli/services.go
Normal file
68
cmd/tailscale/cli/services.go
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/peterbourgon/ff/v3/ffcli"
|
||||
)
|
||||
|
||||
func servicesCmd() *ffcli.Command {
|
||||
return &ffcli.Command{
|
||||
Name: "service",
|
||||
ShortUsage: "tailscale service <subcommand>",
|
||||
ShortHelp: "Manage and view VIP services on your tailnet",
|
||||
Subcommands: []*ffcli.Command{
|
||||
{
|
||||
Name: "list",
|
||||
ShortUsage: "tailscale service list",
|
||||
ShortHelp: "List VIP services visible to this node",
|
||||
Exec: runServicesList,
|
||||
},
|
||||
},
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
return flag.ErrHelp
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func runServicesList(ctx context.Context, args []string) error {
|
||||
if len(args) > 0 {
|
||||
return errors.New("unexpected non-flag arguments to 'tailscale service list'")
|
||||
}
|
||||
services, err := localClient.GetServices(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(services) == 0 {
|
||||
return errors.New("no services found")
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(Stdout, 10, 5, 5, ' ', 0)
|
||||
defer w.Flush()
|
||||
fmt.Fprintf(w, "\n %s\t%s\t%s\t", "SERVICE", "ADDRS", "PORTS")
|
||||
for _, svc := range services {
|
||||
addrs := make([]string, len(svc.Addrs))
|
||||
for i, a := range svc.Addrs {
|
||||
addrs[i] = a.String()
|
||||
}
|
||||
ports := make([]string, len(svc.Ports))
|
||||
for i, p := range svc.Ports {
|
||||
ports[i] = p.String()
|
||||
}
|
||||
fmt.Fprintf(w, "\n %s\t%s\t%s\t",
|
||||
svc.Name,
|
||||
strings.Join(addrs, ", "),
|
||||
strings.Join(ports, ", "),
|
||||
)
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user