Browse Source

all: use new LocalAPI client package location

It was moved in f57fa3cbc30e.

Updates tailscale/corp#22748

Change-Id: I19f965e6bded1d4c919310aa5b864f2de0cd6220
Signed-off-by: Brad Fitzpatrick <[email protected]>
Brad Fitzpatrick 1 year ago
parent
commit
05ac21ebe4
41 changed files with 114 additions and 108 deletions
  1. 2 2
      client/systray/systray.go
  2. 1 1
      client/tailscale/apitype/apitype.go
  3. 3 2
      client/tailscale/example/servetls/servetls.go
  4. 5 5
      client/web/web.go
  5. 7 7
      client/web/web_test.go
  6. 3 3
      cmd/containerboot/metrics.go
  7. 3 3
      cmd/containerboot/serve.go
  8. 2 2
      cmd/containerboot/serve_test.go
  9. 3 3
      cmd/containerboot/services.go
  10. 4 4
      cmd/containerboot/tailscaled.go
  11. 1 1
      cmd/derper/depaware.txt
  12. 2 2
      cmd/hello/hello.go
  13. 2 2
      cmd/k8s-operator/depaware.txt
  14. 2 2
      cmd/k8s-operator/proxy.go
  15. 3 3
      cmd/natc/natc.go
  16. 3 3
      cmd/pgproxy/pgproxy.go
  17. 3 3
      cmd/proxy-to-grafana/proxy-to-grafana.go
  18. 2 2
      cmd/sniproxy/sniproxy.go
  19. 2 1
      cmd/tailscale/cli/cli.go
  20. 1 1
      cmd/tailscale/cli/serve_legacy.go
  21. 1 1
      cmd/tailscale/cli/serve_legacy_test.go
  22. 2 2
      cmd/tailscale/depaware.txt
  23. 2 2
      cmd/tailscaled/depaware.txt
  24. 2 2
      cmd/tailscaled/tailscaled.go
  25. 2 2
      cmd/tl-longchain/tl-longchain.go
  26. 6 6
      cmd/tsidp/tsidp.go
  27. 2 2
      cmd/tta/tta.go
  28. 2 1
      derp/derp_server.go
  29. 5 5
      ipn/ipnlocal/web_client.go
  30. 2 2
      ipn/ipnlocal/web_client_stub.go
  31. 10 9
      ipn/ipnserver/server_test.go
  32. 2 2
      prober/derp.go
  33. 8 7
      tsnet/tsnet.go
  34. 2 2
      tsnet/tsnet_test.go
  35. 4 3
      tstest/integration/integration_test.go
  36. 1 1
      tstest/integration/tailscaled_deps_test_darwin.go
  37. 1 1
      tstest/integration/tailscaled_deps_test_freebsd.go
  38. 1 1
      tstest/integration/tailscaled_deps_test_linux.go
  39. 1 1
      tstest/integration/tailscaled_deps_test_openbsd.go
  40. 1 1
      tstest/integration/tailscaled_deps_test_windows.go
  41. 3 3
      tstest/natlab/vnet/vnet.go

+ 2 - 2
client/systray/systray.go

@@ -26,7 +26,7 @@ import (
 	"github.com/atotto/clipboard"
 	dbus "github.com/godbus/dbus/v5"
 	"github.com/toqueteos/webbrowser"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/ipn"
 	"tailscale.com/ipn/ipnstate"
 	"tailscale.com/tailcfg"
@@ -67,7 +67,7 @@ func (menu *Menu) Run() {
 type Menu struct {
 	mu sync.Mutex // protects the entire Menu
 
-	lc          tailscale.LocalClient
+	lc          local.Client
 	status      *ipnstate.Status
 	curProfile  ipn.LoginProfile
 	allProfiles []ipn.LoginProfile

+ 1 - 1
client/tailscale/apitype/apitype.go

@@ -24,7 +24,7 @@ const LocalAPIHost = "local-tailscaled.sock"
 const RequestReasonHeader = "X-Tailscale-Reason"
 
 // RequestReasonKey is the context key used to pass the request reason
-// when making a LocalAPI request via [tailscale.LocalClient].
+// when making a LocalAPI request via [local.Client].
 // It's value is a raw string. An empty string means no reason was provided.
 //
 // See tailscale/corp#26146.

+ 3 - 2
client/tailscale/example/servetls/servetls.go

@@ -11,13 +11,14 @@ import (
 	"log"
 	"net/http"
 
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 )
 
 func main() {
+	var lc local.Client
 	s := &http.Server{
 		TLSConfig: &tls.Config{
-			GetCertificate: tailscale.GetCertificate,
+			GetCertificate: lc.GetCertificate,
 		},
 		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 			io.WriteString(w, "<h1>Hello from Tailscale!</h1> It works.")

+ 5 - 5
client/web/web.go

@@ -22,7 +22,7 @@ import (
 	"time"
 
 	"github.com/gorilla/csrf"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/client/tailscale/apitype"
 	"tailscale.com/clientupdate"
 	"tailscale.com/envknob"
@@ -50,7 +50,7 @@ type Server struct {
 	mode ServerMode
 
 	logf    logger.Logf
-	lc      *tailscale.LocalClient
+	lc      *local.Client
 	timeNow func() time.Time
 
 	// devMode indicates that the server run with frontend assets
@@ -125,9 +125,9 @@ type ServerOpts struct {
 	// PathPrefix is the URL prefix added to requests by CGI or reverse proxy.
 	PathPrefix string
 
-	// LocalClient is the tailscale.LocalClient to use for this web server.
+	// LocalClient is the local.Client to use for this web server.
 	// If nil, a new one will be created.
-	LocalClient *tailscale.LocalClient
+	LocalClient *local.Client
 
 	// TimeNow optionally provides a time function.
 	// time.Now is used as default.
@@ -166,7 +166,7 @@ func NewServer(opts ServerOpts) (s *Server, err error) {
 		return nil, fmt.Errorf("invalid Mode provided")
 	}
 	if opts.LocalClient == nil {
-		opts.LocalClient = &tailscale.LocalClient{}
+		opts.LocalClient = &local.Client{}
 	}
 	s = &Server{
 		mode:        opts.Mode,

+ 7 - 7
client/web/web_test.go

@@ -20,7 +20,7 @@ import (
 	"time"
 
 	"github.com/google/go-cmp/cmp"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/client/tailscale/apitype"
 	"tailscale.com/ipn"
 	"tailscale.com/ipn/ipnstate"
@@ -120,7 +120,7 @@ func TestServeAPI(t *testing.T) {
 
 	s := &Server{
 		mode:    ManageServerMode,
-		lc:      &tailscale.LocalClient{Dial: lal.Dial},
+		lc:      &local.Client{Dial: lal.Dial},
 		timeNow: time.Now,
 	}
 
@@ -288,7 +288,7 @@ func TestGetTailscaleBrowserSession(t *testing.T) {
 
 	s := &Server{
 		timeNow: time.Now,
-		lc:      &tailscale.LocalClient{Dial: lal.Dial},
+		lc:      &local.Client{Dial: lal.Dial},
 	}
 
 	// Add some browser sessions to cache state.
@@ -457,7 +457,7 @@ func TestAuthorizeRequest(t *testing.T) {
 
 	s := &Server{
 		mode:    ManageServerMode,
-		lc:      &tailscale.LocalClient{Dial: lal.Dial},
+		lc:      &local.Client{Dial: lal.Dial},
 		timeNow: time.Now,
 	}
 	validCookie := "ts-cookie"
@@ -572,7 +572,7 @@ func TestServeAuth(t *testing.T) {
 
 	s := &Server{
 		mode:        ManageServerMode,
-		lc:          &tailscale.LocalClient{Dial: lal.Dial},
+		lc:          &local.Client{Dial: lal.Dial},
 		timeNow:     func() time.Time { return timeNow },
 		newAuthURL:  mockNewAuthURL,
 		waitAuthURL: mockWaitAuthURL,
@@ -914,7 +914,7 @@ func TestServeAPIAuthMetricLogging(t *testing.T) {
 
 	s := &Server{
 		mode:        ManageServerMode,
-		lc:          &tailscale.LocalClient{Dial: lal.Dial},
+		lc:          &local.Client{Dial: lal.Dial},
 		timeNow:     func() time.Time { return timeNow },
 		newAuthURL:  mockNewAuthURL,
 		waitAuthURL: mockWaitAuthURL,
@@ -1126,7 +1126,7 @@ func TestRequireTailscaleIP(t *testing.T) {
 
 	s := &Server{
 		mode:    ManageServerMode,
-		lc:      &tailscale.LocalClient{Dial: lal.Dial},
+		lc:      &local.Client{Dial: lal.Dial},
 		timeNow: time.Now,
 		logf:    t.Logf,
 	}

+ 3 - 3
cmd/containerboot/metrics.go

@@ -10,7 +10,7 @@ import (
 	"io"
 	"net/http"
 
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/client/tailscale/apitype"
 )
 
@@ -18,7 +18,7 @@ import (
 // the tailscaled's LocalAPI usermetrics endpoint at /localapi/v0/usermetrics.
 type metrics struct {
 	debugEndpoint string
-	lc            *tailscale.LocalClient
+	lc            *local.Client
 }
 
 func proxy(w http.ResponseWriter, r *http.Request, url string, do func(*http.Request) (*http.Response, error)) {
@@ -68,7 +68,7 @@ func (m *metrics) handleDebug(w http.ResponseWriter, r *http.Request) {
 // In 1.78.x and 1.80.x, it also proxies debug paths to tailscaled's debug
 // endpoint if configured to ease migration for a breaking change serving user
 // metrics instead of debug metrics on the "metrics" port.
-func metricsHandlers(mux *http.ServeMux, lc *tailscale.LocalClient, debugAddrPort string) {
+func metricsHandlers(mux *http.ServeMux, lc *local.Client, debugAddrPort string) {
 	m := &metrics{
 		lc:            lc,
 		debugEndpoint: debugAddrPort,

+ 3 - 3
cmd/containerboot/serve.go

@@ -17,7 +17,7 @@ import (
 	"time"
 
 	"github.com/fsnotify/fsnotify"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/ipn"
 	"tailscale.com/kube/kubetypes"
 	"tailscale.com/types/netmap"
@@ -28,7 +28,7 @@ import (
 // applies it to lc. It exits when ctx is canceled. cdChanged is a channel that
 // is written to when the certDomain changes, causing the serve config to be
 // re-read and applied.
-func watchServeConfigChanges(ctx context.Context, path string, cdChanged <-chan bool, certDomainAtomic *atomic.Pointer[string], lc *tailscale.LocalClient, kc *kubeClient) {
+func watchServeConfigChanges(ctx context.Context, path string, cdChanged <-chan bool, certDomainAtomic *atomic.Pointer[string], lc *local.Client, kc *kubeClient) {
 	if certDomainAtomic == nil {
 		panic("certDomainAtomic must not be nil")
 	}
@@ -91,7 +91,7 @@ func certDomainFromNetmap(nm *netmap.NetworkMap) string {
 	return nm.DNS.CertDomains[0]
 }
 
-// localClient is a subset of tailscale.LocalClient that can be mocked for testing.
+// localClient is a subset of [local.Client] that can be mocked for testing.
 type localClient interface {
 	SetServeConfig(context.Context, *ipn.ServeConfig) error
 }

+ 2 - 2
cmd/containerboot/serve_test.go

@@ -12,7 +12,7 @@ import (
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/ipn"
 	"tailscale.com/kube/kubetypes"
 )
@@ -197,7 +197,7 @@ func TestReadServeConfig(t *testing.T) {
 }
 
 type fakeLocalClient struct {
-	*tailscale.LocalClient
+	*local.Client
 	setServeCalled bool
 }
 

+ 3 - 3
cmd/containerboot/services.go

@@ -21,7 +21,7 @@ import (
 	"time"
 
 	"github.com/fsnotify/fsnotify"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/ipn"
 	"tailscale.com/kube/egressservices"
 	"tailscale.com/kube/kubeclient"
@@ -50,7 +50,7 @@ type egressProxy struct {
 	kc          kubeclient.Client // never nil
 	stateSecret string            // name of the kube state Secret
 
-	tsClient *tailscale.LocalClient // never nil
+	tsClient *local.Client // never nil
 
 	netmapChan chan ipn.Notify // chan to receive netmap updates on
 
@@ -131,7 +131,7 @@ type egressProxyRunOpts struct {
 	cfgPath      string
 	nfr          linuxfw.NetfilterRunner
 	kc           kubeclient.Client
-	tsClient     *tailscale.LocalClient
+	tsClient     *local.Client
 	stateSecret  string
 	netmapChan   chan ipn.Notify
 	podIPv4      string

+ 4 - 4
cmd/containerboot/tailscaled.go

@@ -20,10 +20,10 @@ import (
 	"time"
 
 	"github.com/fsnotify/fsnotify"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 )
 
-func startTailscaled(ctx context.Context, cfg *settings) (*tailscale.LocalClient, *os.Process, error) {
+func startTailscaled(ctx context.Context, cfg *settings) (*local.Client, *os.Process, error) {
 	args := tailscaledArgs(cfg)
 	// tailscaled runs without context, since it needs to persist
 	// beyond the startup timeout in ctx.
@@ -54,7 +54,7 @@ func startTailscaled(ctx context.Context, cfg *settings) (*tailscale.LocalClient
 		break
 	}
 
-	tsClient := &tailscale.LocalClient{
+	tsClient := &local.Client{
 		Socket:        cfg.Socket,
 		UseSocketOnly: true,
 	}
@@ -170,7 +170,7 @@ func tailscaleSet(ctx context.Context, cfg *settings) error {
 	return nil
 }
 
-func watchTailscaledConfigChanges(ctx context.Context, path string, lc *tailscale.LocalClient, errCh chan<- error) {
+func watchTailscaledConfigChanges(ctx context.Context, path string, lc *local.Client, errCh chan<- error) {
 	var (
 		tickChan          <-chan time.Time
 		tailscaledCfgDir  = filepath.Dir(path)

+ 1 - 1
cmd/derper/depaware.txt

@@ -88,7 +88,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
         google.golang.org/protobuf/types/known/timestamppb           from github.com/prometheus/client_golang/prometheus+
         tailscale.com                                                from tailscale.com/version
      💣 tailscale.com/atomicfile                                     from tailscale.com/cmd/derper+
-        tailscale.com/client/local                                   from tailscale.com/client/tailscale
+        tailscale.com/client/local                                   from tailscale.com/client/tailscale+
         tailscale.com/client/tailscale                               from tailscale.com/derp
         tailscale.com/client/tailscale/apitype                       from tailscale.com/client/tailscale+
         tailscale.com/derp                                           from tailscale.com/cmd/derper+

+ 2 - 2
cmd/hello/hello.go

@@ -18,7 +18,7 @@ import (
 	"strings"
 	"time"
 
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/client/tailscale/apitype"
 )
 
@@ -31,7 +31,7 @@ var (
 //go:embed hello.tmpl.html
 var embeddedTemplate string
 
-var localClient tailscale.LocalClient
+var localClient local.Client
 
 func main() {
 	flag.Parse()

+ 2 - 2
cmd/k8s-operator/depaware.txt

@@ -780,8 +780,8 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
         tailscale.com                                                from tailscale.com/version
         tailscale.com/appc                                           from tailscale.com/ipn/ipnlocal
      💣 tailscale.com/atomicfile                                     from tailscale.com/ipn+
-        tailscale.com/client/local                                   from tailscale.com/client/tailscale
-        tailscale.com/client/tailscale                               from tailscale.com/client/web+
+        tailscale.com/client/local                                   from tailscale.com/client/tailscale+
+        tailscale.com/client/tailscale                               from tailscale.com/cmd/k8s-operator+
         tailscale.com/client/tailscale/apitype                       from tailscale.com/client/tailscale+
         tailscale.com/client/web                                     from tailscale.com/ipn/ipnlocal
         tailscale.com/clientupdate                                   from tailscale.com/client/web+

+ 2 - 2
cmd/k8s-operator/proxy.go

@@ -20,7 +20,7 @@ import (
 	"go.uber.org/zap"
 	"k8s.io/client-go/rest"
 	"k8s.io/client-go/transport"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/client/tailscale/apitype"
 	ksr "tailscale.com/k8s-operator/sessionrecording"
 	"tailscale.com/kube/kubetypes"
@@ -189,7 +189,7 @@ func runAPIServerProxy(ts *tsnet.Server, rt http.RoundTripper, log *zap.SugaredL
 // LocalAPI and then proxies them to the Kubernetes API.
 type apiserverProxy struct {
 	log *zap.SugaredLogger
-	lc  *tailscale.LocalClient
+	lc  *local.Client
 	rp  *httputil.ReverseProxy
 
 	mode        apiServerProxyMode

+ 3 - 3
cmd/natc/natc.go

@@ -29,7 +29,7 @@ import (
 	"golang.org/x/net/dns/dnsmessage"
 	"gvisor.dev/gvisor/pkg/tcpip"
 	"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/envknob"
 	"tailscale.com/hostinfo"
 	"tailscale.com/ipn"
@@ -186,9 +186,9 @@ func main() {
 type connector struct {
 	// ts is the tsnet.Server used to host the connector.
 	ts *tsnet.Server
-	// lc is the LocalClient used to interact with the tsnet.Server hosting this
+	// lc is the local.Client used to interact with the tsnet.Server hosting this
 	// connector.
-	lc *tailscale.LocalClient
+	lc *local.Client
 
 	// dnsAddr is the IPv4 address to listen on for DNS requests. It is used to
 	// prevent the app connector from assigning it to a domain.

+ 3 - 3
cmd/pgproxy/pgproxy.go

@@ -24,7 +24,7 @@ import (
 	"strings"
 	"time"
 
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/metrics"
 	"tailscale.com/tsnet"
 	"tailscale.com/tsweb"
@@ -105,7 +105,7 @@ type proxy struct {
 	upstreamHost     string // "my.database.com"
 	upstreamCertPool *x509.CertPool
 	downstreamCert   []tls.Certificate
-	client           *tailscale.LocalClient
+	client           *local.Client
 
 	activeSessions  expvar.Int
 	startedSessions expvar.Int
@@ -115,7 +115,7 @@ type proxy struct {
 // newProxy returns a proxy that forwards connections to
 // upstreamAddr. The upstream's TLS session is verified using the CA
 // cert(s) in upstreamCAPath.
-func newProxy(upstreamAddr, upstreamCAPath string, client *tailscale.LocalClient) (*proxy, error) {
+func newProxy(upstreamAddr, upstreamCAPath string, client *local.Client) (*proxy, error) {
 	bs, err := os.ReadFile(upstreamCAPath)
 	if err != nil {
 		return nil, err

+ 3 - 3
cmd/proxy-to-grafana/proxy-to-grafana.go

@@ -36,7 +36,7 @@ import (
 	"strings"
 	"time"
 
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/tailcfg"
 	"tailscale.com/tsnet"
 )
@@ -127,7 +127,7 @@ func main() {
 	log.Fatal(http.Serve(ln, proxy))
 }
 
-func modifyRequest(req *http.Request, localClient *tailscale.LocalClient) {
+func modifyRequest(req *http.Request, localClient *local.Client) {
 	// with enable_login_token set to true, we get a cookie that handles
 	// auth for paths that are not /login
 	if req.URL.Path != "/login" {
@@ -144,7 +144,7 @@ func modifyRequest(req *http.Request, localClient *tailscale.LocalClient) {
 	req.Header.Set("X-Webauth-Name", user.DisplayName)
 }
 
-func getTailscaleUser(ctx context.Context, localClient *tailscale.LocalClient, ipPort string) (*tailcfg.UserProfile, error) {
+func getTailscaleUser(ctx context.Context, localClient *local.Client, ipPort string) (*tailcfg.UserProfile, error) {
 	whois, err := localClient.WhoIs(ctx, ipPort)
 	if err != nil {
 		return nil, fmt.Errorf("failed to identify remote host: %w", err)

+ 2 - 2
cmd/sniproxy/sniproxy.go

@@ -22,7 +22,7 @@ import (
 	"strings"
 
 	"github.com/peterbourgon/ff/v3"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/hostinfo"
 	"tailscale.com/ipn"
 	"tailscale.com/tailcfg"
@@ -183,7 +183,7 @@ func run(ctx context.Context, ts *tsnet.Server, wgPort int, hostname string, pro
 type sniproxy struct {
 	srv Server
 	ts  *tsnet.Server
-	lc  *tailscale.LocalClient
+	lc  *local.Client
 }
 
 func (s *sniproxy) advertiseRoutesFromConfig(ctx context.Context, c *appctype.AppConnectorConfig) error {

+ 2 - 1
cmd/tailscale/cli/cli.go

@@ -21,6 +21,7 @@ import (
 	"github.com/mattn/go-colorable"
 	"github.com/mattn/go-isatty"
 	"github.com/peterbourgon/ff/v3/ffcli"
+	"tailscale.com/client/local"
 	"tailscale.com/client/tailscale"
 	"tailscale.com/cmd/tailscale/cli/ffcomplete"
 	"tailscale.com/envknob"
@@ -79,7 +80,7 @@ func CleanUpArgs(args []string) []string {
 	return out
 }
 
-var localClient = tailscale.LocalClient{
+var localClient = local.Client{
 	Socket: paths.DefaultTailscaledSocket(),
 }
 

+ 1 - 1
cmd/tailscale/cli/serve_legacy.go

@@ -130,7 +130,7 @@ func (e *serveEnv) newFlags(name string, setup func(fs *flag.FlagSet)) *flag.Fla
 }
 
 // localServeClient is an interface conforming to the subset of
-// tailscale.LocalClient. It includes only the methods used by the
+// local.Client. It includes only the methods used by the
 // serve command.
 //
 // The purpose of this interface is to allow tests to provide a mock.

+ 1 - 1
cmd/tailscale/cli/serve_legacy_test.go

@@ -850,7 +850,7 @@ func TestVerifyFunnelEnabled(t *testing.T) {
 	}
 }
 
-// fakeLocalServeClient is a fake tailscale.LocalClient for tests.
+// fakeLocalServeClient is a fake local.Client for tests.
 // It's not a full implementation, just enough to test the serve command.
 //
 // The fake client is stateful, and is used to test manipulating

+ 2 - 2
cmd/tailscale/depaware.txt

@@ -70,8 +70,8 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
         software.sslmate.com/src/go-pkcs12/internal/rc2              from software.sslmate.com/src/go-pkcs12
         tailscale.com                                                from tailscale.com/version
      💣 tailscale.com/atomicfile                                     from tailscale.com/cmd/tailscale/cli+
-        tailscale.com/client/local                                   from tailscale.com/client/tailscale
-        tailscale.com/client/tailscale                               from tailscale.com/client/web+
+        tailscale.com/client/local                                   from tailscale.com/client/tailscale+
+        tailscale.com/client/tailscale                               from tailscale.com/cmd/tailscale/cli+
         tailscale.com/client/tailscale/apitype                       from tailscale.com/client/tailscale+
         tailscale.com/client/web                                     from tailscale.com/cmd/tailscale/cli
         tailscale.com/clientupdate                                   from tailscale.com/client/web+

+ 2 - 2
cmd/tailscaled/depaware.txt

@@ -233,8 +233,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
         tailscale.com/appc                                           from tailscale.com/ipn/ipnlocal
      💣 tailscale.com/atomicfile                                     from tailscale.com/ipn+
   LD    tailscale.com/chirp                                          from tailscale.com/cmd/tailscaled
-        tailscale.com/client/local                                   from tailscale.com/client/tailscale
-        tailscale.com/client/tailscale                               from tailscale.com/client/web+
+        tailscale.com/client/local                                   from tailscale.com/client/tailscale+
+        tailscale.com/client/tailscale                               from tailscale.com/derp
         tailscale.com/client/tailscale/apitype                       from tailscale.com/client/tailscale+
         tailscale.com/client/web                                     from tailscale.com/ipn/ipnlocal
         tailscale.com/clientupdate                                   from tailscale.com/client/web+

+ 2 - 2
cmd/tailscaled/tailscaled.go

@@ -30,7 +30,7 @@ import (
 	"syscall"
 	"time"
 
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/cmd/tailscaled/childproc"
 	"tailscale.com/control/controlclient"
 	"tailscale.com/drive/driveimpl"
@@ -621,7 +621,7 @@ func getLocalBackend(ctx context.Context, logf logger.Logf, logID logid.PublicID
 	if root := lb.TailscaleVarRoot(); root != "" {
 		dnsfallback.SetCachePath(filepath.Join(root, "derpmap.cached.json"), logf)
 	}
-	lb.ConfigureWebClient(&tailscale.LocalClient{
+	lb.ConfigureWebClient(&local.Client{
 		Socket:        args.socketpath,
 		UseSocketOnly: args.socketpath != paths.DefaultTailscaledSocket(),
 	})

+ 2 - 2
cmd/tl-longchain/tl-longchain.go

@@ -22,7 +22,7 @@ import (
 	"log"
 	"time"
 
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/ipn/ipnstate"
 	"tailscale.com/tka"
 	"tailscale.com/types/key"
@@ -37,7 +37,7 @@ var (
 func main() {
 	flag.Parse()
 
-	lc := tailscale.LocalClient{Socket: *flagSocket}
+	lc := local.Client{Socket: *flagSocket}
 	if lc.Socket != "" {
 		lc.UseSocketOnly = true
 	}

+ 6 - 6
cmd/tsidp/tsidp.go

@@ -35,7 +35,7 @@ import (
 
 	"gopkg.in/square/go-jose.v2"
 	"gopkg.in/square/go-jose.v2/jwt"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/client/tailscale/apitype"
 	"tailscale.com/envknob"
 	"tailscale.com/ipn"
@@ -75,7 +75,7 @@ func main() {
 	}
 
 	var (
-		lc          *tailscale.LocalClient
+		lc          *local.Client
 		st          *ipnstate.Status
 		err         error
 		watcherChan chan error
@@ -84,7 +84,7 @@ func main() {
 		lns []net.Listener
 	)
 	if *flagUseLocalTailscaled {
-		lc = &tailscale.LocalClient{}
+		lc = &local.Client{}
 		st, err = lc.StatusWithoutPeers(ctx)
 		if err != nil {
 			log.Fatalf("getting status: %v", err)
@@ -212,7 +212,7 @@ func main() {
 // serveOnLocalTailscaled starts a serve session using an already-running
 // tailscaled instead of starting a fresh tsnet server, making something
 // listening on clientDNSName:dstPort accessible over serve/funnel.
-func serveOnLocalTailscaled(ctx context.Context, lc *tailscale.LocalClient, st *ipnstate.Status, dstPort uint16, shouldFunnel bool) (cleanup func(), watcherChan chan error, err error) {
+func serveOnLocalTailscaled(ctx context.Context, lc *local.Client, st *ipnstate.Status, dstPort uint16, shouldFunnel bool) (cleanup func(), watcherChan chan error, err error) {
 	// In order to support funneling out in local tailscaled mode, we need
 	// to add a serve config to forward the listeners we bound above and
 	// allow those forwarders to be funneled out.
@@ -275,7 +275,7 @@ func serveOnLocalTailscaled(ctx context.Context, lc *tailscale.LocalClient, st *
 }
 
 type idpServer struct {
-	lc          *tailscale.LocalClient
+	lc          *local.Client
 	loopbackURL string
 	serverURL   string // "https://foo.bar.ts.net"
 	funnel      bool
@@ -328,7 +328,7 @@ type authRequest struct {
 // allowRelyingParty validates that a relying party identified either by a
 // known remoteAddr or a valid client ID/secret pair is allowed to proceed
 // with the authorization flow associated with this authRequest.
-func (ar *authRequest) allowRelyingParty(r *http.Request, lc *tailscale.LocalClient) error {
+func (ar *authRequest) allowRelyingParty(r *http.Request, lc *local.Client) error {
 	if ar.localRP {
 		ra, err := netip.ParseAddrPort(r.RemoteAddr)
 		if err != nil {

+ 2 - 2
cmd/tta/tta.go

@@ -30,7 +30,7 @@ import (
 	"time"
 
 	"tailscale.com/atomicfile"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/hostinfo"
 	"tailscale.com/util/mak"
 	"tailscale.com/util/must"
@@ -64,7 +64,7 @@ func serveCmd(w http.ResponseWriter, cmd string, args ...string) {
 }
 
 type localClientRoundTripper struct {
-	lc tailscale.LocalClient
+	lc local.Client
 }
 
 func (rt *localClientRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {

+ 2 - 1
derp/derp_server.go

@@ -36,6 +36,7 @@ import (
 
 	"go4.org/mem"
 	"golang.org/x/sync/errgroup"
+	"tailscale.com/client/local"
 	"tailscale.com/client/tailscale"
 	"tailscale.com/disco"
 	"tailscale.com/envknob"
@@ -1319,7 +1320,7 @@ func (c *sclient) requestMeshUpdate() {
 	}
 }
 
-var localClient tailscale.LocalClient
+var localClient local.Client
 
 // isMeshPeer reports whether the client is a trusted mesh peer
 // node in the DERP region.

+ 5 - 5
ipn/ipnlocal/web_client.go

@@ -17,7 +17,7 @@ import (
 	"sync"
 	"time"
 
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/client/web"
 	"tailscale.com/logtail/backoff"
 	"tailscale.com/net/netutil"
@@ -36,16 +36,16 @@ type webClient struct {
 
 	server *web.Server // or nil, initialized lazily
 
-	// lc optionally specifies a LocalClient to use to connect
+	// lc optionally specifies a local.Client to use to connect
 	// to the localapi for this tailscaled instance.
 	// If nil, a default is used.
-	lc *tailscale.LocalClient
+	lc *local.Client
 }
 
 // ConfigureWebClient configures b.web prior to use.
-// Specifially, it sets b.web.lc to the provided LocalClient.
+// Specifially, it sets b.web.lc to the provided local.Client.
 // If provided as nil, b.web.lc is cleared out.
-func (b *LocalBackend) ConfigureWebClient(lc *tailscale.LocalClient) {
+func (b *LocalBackend) ConfigureWebClient(lc *local.Client) {
 	b.webClient.mu.Lock()
 	defer b.webClient.mu.Unlock()
 	b.webClient.lc = lc

+ 2 - 2
ipn/ipnlocal/web_client_stub.go

@@ -9,14 +9,14 @@ import (
 	"errors"
 	"net"
 
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 )
 
 const webClientPort = 5252
 
 type webClient struct{}
 
-func (b *LocalBackend) ConfigureWebClient(lc *tailscale.LocalClient) {}
+func (b *LocalBackend) ConfigureWebClient(lc *local.Client) {}
 
 func (b *LocalBackend) webClientGetOrInit() error {
 	return errors.New("not implemented")

+ 10 - 9
ipn/ipnserver/server_test.go

@@ -17,6 +17,7 @@ import (
 	"sync/atomic"
 	"testing"
 
+	"tailscale.com/client/local"
 	"tailscale.com/client/tailscale"
 	"tailscale.com/client/tailscale/apitype"
 	"tailscale.com/control/controlclient"
@@ -330,7 +331,7 @@ func newTestIPNServer(tb testing.TB, lb *ipnlocal.LocalBackend, enableLogging bo
 
 type testIPNClient struct {
 	tb testing.TB
-	*tailscale.LocalClient
+	*local.Client
 	User *ipnauth.TestActor
 }
 
@@ -338,7 +339,7 @@ func (c *testIPNClient) WatchIPNBus(ctx context.Context, mask ipn.NotifyWatchOpt
 	c.tb.Helper()
 	ctx, cancelWatcher := context.WithCancel(ctx)
 	c.tb.Cleanup(cancelWatcher)
-	watcher, err := c.LocalClient.WatchIPNBus(ctx, mask)
+	watcher, err := c.Client.WatchIPNBus(ctx, mask)
 	if err != nil {
 		c.tb.Fatalf("WatchIPNBus(%q): %v", c.User.Name, err)
 	}
@@ -359,7 +360,7 @@ type testIPNServer struct {
 	tb testing.TB
 	*Server
 	clientID  atomic.Int64
-	getClient func(*ipnauth.TestActor) *tailscale.LocalClient
+	getClient func(*ipnauth.TestActor) *local.Client
 
 	actorsMu sync.Mutex
 	actors   map[string]*ipnauth.TestActor
@@ -369,9 +370,9 @@ func (s *testIPNServer) getClientAs(name string) *testIPNClient {
 	clientID := fmt.Sprintf("Client-%d", 1+s.clientID.Add(1))
 	user := s.makeTestUser(name, clientID)
 	return &testIPNClient{
-		tb:          s.tb,
-		LocalClient: s.getClient(user),
-		User:        user,
+		tb:     s.tb,
+		Client: s.getClient(user),
+		User:   user,
 	}
 }
 
@@ -427,7 +428,7 @@ func (s *testIPNServer) checkCurrentUser(want *ipnauth.TestActor) {
 
 // startTestIPNServer starts a [httptest.Server] that hosts the specified IPN server for the
 // duration of the test, using the specified base context for incoming requests.
-// It returns a function that creates a [tailscale.LocalClient] as a given [ipnauth.TestActor].
+// It returns a function that creates a [local.Client] as a given [ipnauth.TestActor].
 func startTestIPNServer(tb testing.TB, baseContext context.Context, server *Server) *testIPNServer {
 	tb.Helper()
 	ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -448,8 +449,8 @@ func startTestIPNServer(tb testing.TB, baseContext context.Context, server *Serv
 	return &testIPNServer{
 		tb:     tb,
 		Server: server,
-		getClient: func(actor *ipnauth.TestActor) *tailscale.LocalClient {
-			return &tailscale.LocalClient{Transport: newTestRoundTripper(ts, actor)}
+		getClient: func(actor *ipnauth.TestActor) *local.Client {
+			return &local.Client{Transport: newTestRoundTripper(ts, actor)}
 		},
 	}
 }

+ 2 - 2
prober/derp.go

@@ -30,7 +30,7 @@ import (
 	"github.com/tailscale/wireguard-go/device"
 	"github.com/tailscale/wireguard-go/tun"
 	"go4.org/netipx"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/derp"
 	"tailscale.com/derp/derphttp"
 	"tailscale.com/net/netmon"
@@ -534,7 +534,7 @@ func (d *derpProber) getNodePair(n1, n2 string) (ret1, ret2 *tailcfg.DERPNode, _
 	return ret1, ret2, nil
 }
 
-var tsLocalClient tailscale.LocalClient
+var tsLocalClient local.Client
 
 // updateMap refreshes the locally-cached DERP map.
 func (d *derpProber) updateMap(ctx context.Context) error {

+ 8 - 7
tsnet/tsnet.go

@@ -26,6 +26,7 @@ import (
 	"sync"
 	"time"
 
+	"tailscale.com/client/local"
 	"tailscale.com/client/tailscale"
 	"tailscale.com/control/controlclient"
 	"tailscale.com/envknob"
@@ -135,11 +136,11 @@ type Server struct {
 	hostname         string
 	shutdownCtx      context.Context
 	shutdownCancel   context.CancelFunc
-	proxyCred        string                 // SOCKS5 proxy auth for loopbackListener
-	localAPICred     string                 // basic auth password for loopbackListener
-	loopbackListener net.Listener           // optional loopback for localapi and proxies
-	localAPIListener net.Listener           // in-memory, used by localClient
-	localClient      *tailscale.LocalClient // in-memory
+	proxyCred        string        // SOCKS5 proxy auth for loopbackListener
+	localAPICred     string        // basic auth password for loopbackListener
+	loopbackListener net.Listener  // optional loopback for localapi and proxies
+	localAPIListener net.Listener  // in-memory, used by localClient
+	localClient      *local.Client // in-memory
 	localAPIServer   *http.Server
 	logbuffer        *filch.Filch
 	logtail          *logtail.Logger
@@ -222,7 +223,7 @@ func (s *Server) HTTPClient() *http.Client {
 //
 // It will start the server if it has not been started yet. If the server's
 // already been started successfully, it doesn't return an error.
-func (s *Server) LocalClient() (*tailscale.LocalClient, error) {
+func (s *Server) LocalClient() (*local.Client, error) {
 	if err := s.Start(); err != nil {
 		return nil, err
 	}
@@ -676,7 +677,7 @@ func (s *Server) start() (reterr error) {
 	// nettest.Listen provides a in-memory pipe based implementation for net.Conn.
 	lal := memnet.Listen("local-tailscaled.sock:80")
 	s.localAPIListener = lal
-	s.localClient = &tailscale.LocalClient{Dial: lal.Dial}
+	s.localClient = &local.Client{Dial: lal.Dial}
 	s.localAPIServer = &http.Server{Handler: lah}
 	s.lb.ConfigureWebClient(s.localClient)
 	go func() {

+ 2 - 2
tsnet/tsnet_test.go

@@ -36,7 +36,7 @@ import (
 	dto "github.com/prometheus/client_model/go"
 	"github.com/prometheus/common/expfmt"
 	"golang.org/x/net/proxy"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/cmd/testwrapper/flakytest"
 	"tailscale.com/ipn"
 	"tailscale.com/ipn/store/mem"
@@ -1273,7 +1273,7 @@ func waitForCondition(t *testing.T, msg string, waitTime time.Duration, f func()
 }
 
 // mustDirect ensures there is a direct connection between LocalClient 1 and 2
-func mustDirect(t *testing.T, logf logger.Logf, lc1, lc2 *tailscale.LocalClient) {
+func mustDirect(t *testing.T, logf logger.Logf, lc1, lc2 *local.Client) {
 	t.Helper()
 	lastLog := time.Now().Add(-time.Minute)
 	// See https://github.com/tailscale/tailscale/issues/654

+ 4 - 3
tstest/integration/integration_test.go

@@ -32,6 +32,7 @@ import (
 
 	"github.com/miekg/dns"
 	"go4.org/mem"
+	"tailscale.com/client/local"
 	"tailscale.com/client/tailscale"
 	"tailscale.com/clientupdate"
 	"tailscale.com/cmd/testwrapper/flakytest"
@@ -755,11 +756,11 @@ func TestClientSideJailing(t *testing.T) {
 	defer ln.Close()
 	port := uint16(ln.Addr().(*net.TCPAddr).Port)
 
-	lc1 := &tailscale.LocalClient{
+	lc1 := &local.Client{
 		Socket:        n1.sockFile,
 		UseSocketOnly: true,
 	}
-	lc2 := &tailscale.LocalClient{
+	lc2 := &local.Client{
 		Socket:        n2.sockFile,
 		UseSocketOnly: true,
 	}
@@ -789,7 +790,7 @@ func TestClientSideJailing(t *testing.T) {
 		},
 	}
 
-	testDial := func(t *testing.T, lc *tailscale.LocalClient, ip netip.Addr, port uint16, shouldFail bool) {
+	testDial := func(t *testing.T, lc *local.Client, ip netip.Addr, port uint16, shouldFail bool) {
 		t.Helper()
 		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
 		defer cancel()

+ 1 - 1
tstest/integration/tailscaled_deps_test_darwin.go

@@ -11,7 +11,7 @@ import (
 	// transitive deps when we run "go install tailscaled" in a child
 	// process and can cache a prior success when a dependency changes.
 	_ "tailscale.com/chirp"
-	_ "tailscale.com/client/tailscale"
+	_ "tailscale.com/client/local"
 	_ "tailscale.com/cmd/tailscaled/childproc"
 	_ "tailscale.com/control/controlclient"
 	_ "tailscale.com/derp/derphttp"

+ 1 - 1
tstest/integration/tailscaled_deps_test_freebsd.go

@@ -11,7 +11,7 @@ import (
 	// transitive deps when we run "go install tailscaled" in a child
 	// process and can cache a prior success when a dependency changes.
 	_ "tailscale.com/chirp"
-	_ "tailscale.com/client/tailscale"
+	_ "tailscale.com/client/local"
 	_ "tailscale.com/cmd/tailscaled/childproc"
 	_ "tailscale.com/control/controlclient"
 	_ "tailscale.com/derp/derphttp"

+ 1 - 1
tstest/integration/tailscaled_deps_test_linux.go

@@ -11,7 +11,7 @@ import (
 	// transitive deps when we run "go install tailscaled" in a child
 	// process and can cache a prior success when a dependency changes.
 	_ "tailscale.com/chirp"
-	_ "tailscale.com/client/tailscale"
+	_ "tailscale.com/client/local"
 	_ "tailscale.com/cmd/tailscaled/childproc"
 	_ "tailscale.com/control/controlclient"
 	_ "tailscale.com/derp/derphttp"

+ 1 - 1
tstest/integration/tailscaled_deps_test_openbsd.go

@@ -11,7 +11,7 @@ import (
 	// transitive deps when we run "go install tailscaled" in a child
 	// process and can cache a prior success when a dependency changes.
 	_ "tailscale.com/chirp"
-	_ "tailscale.com/client/tailscale"
+	_ "tailscale.com/client/local"
 	_ "tailscale.com/cmd/tailscaled/childproc"
 	_ "tailscale.com/control/controlclient"
 	_ "tailscale.com/derp/derphttp"

+ 1 - 1
tstest/integration/tailscaled_deps_test_windows.go

@@ -18,7 +18,7 @@ import (
 	_ "golang.org/x/sys/windows/svc/mgr"
 	_ "golang.zx2c4.com/wintun"
 	_ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
-	_ "tailscale.com/client/tailscale"
+	_ "tailscale.com/client/local"
 	_ "tailscale.com/cmd/tailscaled/childproc"
 	_ "tailscale.com/control/controlclient"
 	_ "tailscale.com/derp/derphttp"

+ 3 - 3
tstest/natlab/vnet/vnet.go

@@ -50,7 +50,7 @@ import (
 	"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
 	"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
 	"gvisor.dev/gvisor/pkg/waiter"
-	"tailscale.com/client/tailscale"
+	"tailscale.com/client/local"
 	"tailscale.com/derp"
 	"tailscale.com/derp/derphttp"
 	"tailscale.com/net/netutil"
@@ -2123,7 +2123,7 @@ func (s *Server) takeAgentConnOne(n *node) (_ *agentConn, ok bool) {
 }
 
 type NodeAgentClient struct {
-	*tailscale.LocalClient
+	*local.Client
 	HTTPClient *http.Client
 }
 
@@ -2148,7 +2148,7 @@ func (s *Server) NodeAgentDialer(n *Node) DialFunc {
 func (s *Server) NodeAgentClient(n *Node) *NodeAgentClient {
 	d := s.NodeAgentDialer(n)
 	return &NodeAgentClient{
-		LocalClient: &tailscale.LocalClient{
+		Client: &local.Client{
 			UseSocketOnly: true,
 			OmitAuth:      true,
 			Dial:          d,