client/local, ipn, tailcfg: document which LocalAPI client APIs are stable
The client/local package doc said its API is not necessarily stable, but that caveat was easy to miss and only a few cert methods said anything explicit either way. People have been surprised by IPN bus changes between releases. Add explicit "API maturity" notes, matching the existing wording on the cert methods, marking stable: BugReport, BugReportWithOpts, CertDomains, CheckUpdate, CurrentDERPMap, DialTCP, UserDial, DisconnectControl, GetPrefs, EditPrefs, Status, StatusWithoutPeers, SetUseExitNode, SwitchProfile, UserProfile, and the WhoIs* methods. Mark unstable: ipn.Notify, WatchIPNBus, DoLocalRequest, the Debug*, Drive*, Check*, EventBus*, and Stream* methods, SetComponentDebugLogging, TailDaemonLogs, ShutdownTailscaled, GetDNSOSConfig, GetEffectivePolicy, GetServeConfig, and GetAppConnectorRouteInfo. Also note on tailcfg.DERPMap that the type is subject to minor changes over time though its general shape is stable, document that ipn.Prefs.CorpDNS is the internal name for "tailscale set --accept-dns", and add a package doc paragraph to client/local saying that methods without an explicit API maturity note should be assumed unstable. Updates #20406 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Change-Id: I9333c58ae312e392c61d7de77987282e84ce2aeb
This commit is contained in:
committed by
Brad Fitzpatrick
parent
b14f7b7543
commit
172124da8c
@@ -50,6 +50,9 @@ type DebugPortmapOpts struct {
|
|||||||
// process.
|
// process.
|
||||||
//
|
//
|
||||||
// opts can be nil; if so, default values will be used.
|
// opts can be nil; if so, default values will be used.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) DebugPortmap(ctx context.Context, opts *DebugPortmapOpts) (io.ReadCloser, error) {
|
func (lc *Client) DebugPortmap(ctx context.Context, opts *DebugPortmapOpts) (io.ReadCloser, error) {
|
||||||
vals := make(url.Values)
|
vals := make(url.Values)
|
||||||
if opts == nil {
|
if opts == nil {
|
||||||
|
|||||||
+163
-7
@@ -2,6 +2,12 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
// Package local contains a Go client for the Tailscale LocalAPI.
|
// Package local contains a Go client for the Tailscale LocalAPI.
|
||||||
|
//
|
||||||
|
// The APIs in this package vary in maturity: some methods are considered
|
||||||
|
// stable APIs and are documented as such, while others are not necessarily
|
||||||
|
// stable and are subject to change between releases. Methods without an
|
||||||
|
// explicit "API maturity" note in their documentation should be assumed
|
||||||
|
// to be unstable.
|
||||||
package local
|
package local
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -135,6 +141,9 @@ func (lc *Client) defaultDialer(ctx context.Context, network, addr string) (net.
|
|||||||
// authenticating to the local Tailscale daemon vary by platform.
|
// authenticating to the local Tailscale daemon vary by platform.
|
||||||
//
|
//
|
||||||
// DoLocalRequest may mutate the request to add Authorization headers.
|
// DoLocalRequest may mutate the request to add Authorization headers.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) DoLocalRequest(req *http.Request) (*http.Response, error) {
|
func (lc *Client) DoLocalRequest(req *http.Request) (*http.Response, error) {
|
||||||
req.Header.Set("Tailscale-Cap", strconv.Itoa(int(tailcfg.CurrentCapabilityVersion)))
|
req.Header.Set("Tailscale-Cap", strconv.Itoa(int(tailcfg.CurrentCapabilityVersion)))
|
||||||
lc.tsClientOnce.Do(func() {
|
lc.tsClientOnce.Do(func() {
|
||||||
@@ -317,6 +326,8 @@ func decodeJSON[T any](b []byte) (ret T, err error) {
|
|||||||
// For connections proxied by tailscaled, this looks up the owner of the given
|
// For connections proxied by tailscaled, this looks up the owner of the given
|
||||||
// address as TCP first, falling back to UDP; if you want to only check a
|
// address as TCP first, falling back to UDP; if you want to only check a
|
||||||
// specific address family, use WhoIsProto.
|
// specific address family, use WhoIsProto.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) WhoIs(ctx context.Context, remoteAddr string) (*apitype.WhoIsResponse, error) {
|
func (lc *Client) WhoIs(ctx context.Context, remoteAddr string) (*apitype.WhoIsResponse, error) {
|
||||||
body, err := lc.get200(ctx, "/localapi/v0/whois?addr="+url.QueryEscape(remoteAddr))
|
body, err := lc.get200(ctx, "/localapi/v0/whois?addr="+url.QueryEscape(remoteAddr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -331,6 +342,8 @@ func (lc *Client) WhoIs(ctx context.Context, remoteAddr string) (*apitype.WhoIsR
|
|||||||
// WhoIsForService is like [Client.WhoIs] but scopes the returned CapMap to
|
// WhoIsForService is like [Client.WhoIs] but scopes the returned CapMap to
|
||||||
// capabilities that apply to the named VIP service. This enables per-service
|
// capabilities that apply to the named VIP service. This enables per-service
|
||||||
// capability resolution on hosts that advertise multiple VIP services.
|
// capability resolution on hosts that advertise multiple VIP services.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) WhoIsForService(ctx context.Context, remoteAddr string, svcName tailcfg.ServiceName) (*apitype.WhoIsResponse, error) {
|
func (lc *Client) WhoIsForService(ctx context.Context, remoteAddr string, svcName tailcfg.ServiceName) (*apitype.WhoIsResponse, error) {
|
||||||
body, err := lc.get200(ctx, "/localapi/v0/whois?addr="+url.QueryEscape(remoteAddr)+"&svc_name="+url.QueryEscape(string(svcName)))
|
body, err := lc.get200(ctx, "/localapi/v0/whois?addr="+url.QueryEscape(remoteAddr)+"&svc_name="+url.QueryEscape(string(svcName)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -346,6 +359,8 @@ func (lc *Client) WhoIsForService(ctx context.Context, remoteAddr string, svcNam
|
|||||||
// capabilities that apply to the given destination IP. The IP may be a
|
// capabilities that apply to the given destination IP. The IP may be a
|
||||||
// VIP service address, the node's own tailnet address, or any other
|
// VIP service address, the node's own tailnet address, or any other
|
||||||
// routable IP the node handles.
|
// routable IP the node handles.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) WhoIsForIP(ctx context.Context, remoteAddr string, dst netip.Addr) (*apitype.WhoIsResponse, error) {
|
func (lc *Client) WhoIsForIP(ctx context.Context, remoteAddr string, dst netip.Addr) (*apitype.WhoIsResponse, error) {
|
||||||
body, err := lc.get200(ctx, "/localapi/v0/whois?addr="+url.QueryEscape(remoteAddr)+"&dst_ip="+url.QueryEscape(dst.String()))
|
body, err := lc.get200(ctx, "/localapi/v0/whois?addr="+url.QueryEscape(remoteAddr)+"&dst_ip="+url.QueryEscape(dst.String()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -364,6 +379,8 @@ var ErrPeerNotFound = errors.New("peer not found")
|
|||||||
// WhoIsNodeKey returns the owner of the given wireguard public key.
|
// WhoIsNodeKey returns the owner of the given wireguard public key.
|
||||||
//
|
//
|
||||||
// If not found, the error is ErrPeerNotFound.
|
// If not found, the error is ErrPeerNotFound.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) WhoIsNodeKey(ctx context.Context, key key.NodePublic) (*apitype.WhoIsResponse, error) {
|
func (lc *Client) WhoIsNodeKey(ctx context.Context, key key.NodePublic) (*apitype.WhoIsResponse, error) {
|
||||||
body, err := lc.get200(ctx, "/localapi/v0/whois?addr="+url.QueryEscape(key.String()))
|
body, err := lc.get200(ctx, "/localapi/v0/whois?addr="+url.QueryEscape(key.String()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -379,6 +396,8 @@ func (lc *Client) WhoIsNodeKey(ctx context.Context, key key.NodePublic) (*apityp
|
|||||||
// IP:port, for the given protocol (tcp or udp).
|
// IP:port, for the given protocol (tcp or udp).
|
||||||
//
|
//
|
||||||
// If not found, the error is [ErrPeerNotFound].
|
// If not found, the error is [ErrPeerNotFound].
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) WhoIsProto(ctx context.Context, proto, remoteAddr string) (*apitype.WhoIsResponse, error) {
|
func (lc *Client) WhoIsProto(ctx context.Context, proto, remoteAddr string) (*apitype.WhoIsResponse, error) {
|
||||||
body, err := lc.get200(ctx, "/localapi/v0/whois?proto="+url.QueryEscape(proto)+"&addr="+url.QueryEscape(remoteAddr))
|
body, err := lc.get200(ctx, "/localapi/v0/whois?proto="+url.QueryEscape(proto)+"&addr="+url.QueryEscape(remoteAddr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -455,6 +474,9 @@ func (lc *Client) SetGauge(ctx context.Context, name string, value int) error {
|
|||||||
|
|
||||||
// TailDaemonLogs returns a stream the Tailscale daemon's logs as they arrive.
|
// TailDaemonLogs returns a stream the Tailscale daemon's logs as they arrive.
|
||||||
// Close the context to stop the stream.
|
// Close the context to stop the stream.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) TailDaemonLogs(ctx context.Context) (io.Reader, error) {
|
func (lc *Client) TailDaemonLogs(ctx context.Context) (io.Reader, error) {
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", "http://"+apitype.LocalAPIHost+"/localapi/v0/logtap", nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", "http://"+apitype.LocalAPIHost+"/localapi/v0/logtap", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -471,12 +493,18 @@ func (lc *Client) TailDaemonLogs(ctx context.Context) (io.Reader, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EventBusGraph returns a graph of active publishers and subscribers in the eventbus
|
// EventBusGraph returns a graph of active publishers and subscribers in the eventbus
|
||||||
// as a [eventbus.DebugTopics]
|
// as a [eventbus.DebugTopics].
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) EventBusGraph(ctx context.Context) ([]byte, error) {
|
func (lc *Client) EventBusGraph(ctx context.Context) ([]byte, error) {
|
||||||
return lc.get200(ctx, "/localapi/v0/debug-bus-graph")
|
return lc.get200(ctx, "/localapi/v0/debug-bus-graph")
|
||||||
}
|
}
|
||||||
|
|
||||||
// EventBusQueues returns a JSON snapshot of event bus queue depths per client.
|
// EventBusQueues returns a JSON snapshot of event bus queue depths per client.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) EventBusQueues(ctx context.Context) ([]byte, error) {
|
func (lc *Client) EventBusQueues(ctx context.Context) ([]byte, error) {
|
||||||
return lc.get200(ctx, "/localapi/v0/debug-bus-queues")
|
return lc.get200(ctx, "/localapi/v0/debug-bus-queues")
|
||||||
}
|
}
|
||||||
@@ -485,6 +513,9 @@ func (lc *Client) EventBusQueues(ctx context.Context) ([]byte, error) {
|
|||||||
// Each pair is a valid event and a nil error, or a zero event a non-nil error.
|
// Each pair is a valid event and a nil error, or a zero event a non-nil error.
|
||||||
// In case of error, the iterator ends after the pair reporting the error.
|
// In case of error, the iterator ends after the pair reporting the error.
|
||||||
// Iteration stops if ctx ends.
|
// Iteration stops if ctx ends.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) StreamBusEvents(ctx context.Context) iter.Seq2[eventbus.DebugEvent, error] {
|
func (lc *Client) StreamBusEvents(ctx context.Context) iter.Seq2[eventbus.DebugEvent, error] {
|
||||||
return func(yield func(eventbus.DebugEvent, error) bool) {
|
return func(yield func(eventbus.DebugEvent, error) bool) {
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET",
|
req, err := http.NewRequestWithContext(ctx, "GET",
|
||||||
@@ -553,6 +584,8 @@ type BugReportOpts struct {
|
|||||||
//
|
//
|
||||||
// The opts type specifies options to pass to the Tailscale daemon when
|
// The opts type specifies options to pass to the Tailscale daemon when
|
||||||
// generating this bug report.
|
// generating this bug report.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) BugReportWithOpts(ctx context.Context, opts BugReportOpts) (string, error) {
|
func (lc *Client) BugReportWithOpts(ctx context.Context, opts BugReportOpts) (string, error) {
|
||||||
qparams := make(url.Values)
|
qparams := make(url.Values)
|
||||||
if opts.Note != "" {
|
if opts.Note != "" {
|
||||||
@@ -598,12 +631,17 @@ func (lc *Client) BugReportWithOpts(ctx context.Context, opts BugReportOpts) (st
|
|||||||
//
|
//
|
||||||
// This is the same as calling [Client.BugReportWithOpts] and only specifying the Note
|
// This is the same as calling [Client.BugReportWithOpts] and only specifying the Note
|
||||||
// field.
|
// field.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) BugReport(ctx context.Context, note string) (string, error) {
|
func (lc *Client) BugReport(ctx context.Context, note string) (string, error) {
|
||||||
return lc.BugReportWithOpts(ctx, BugReportOpts{Note: note})
|
return lc.BugReportWithOpts(ctx, BugReportOpts{Note: note})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DebugAction invokes a debug action, such as "rebind" or "restun".
|
// DebugAction invokes a debug action, such as "rebind" or "restun".
|
||||||
// These are development tools and subject to change or removal over time.
|
// These are development tools.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change or removal between releases.
|
||||||
func (lc *Client) DebugAction(ctx context.Context, action string) error {
|
func (lc *Client) DebugAction(ctx context.Context, action string) error {
|
||||||
body, err := lc.send(ctx, "POST", "/localapi/v0/debug?action="+url.QueryEscape(action), 200, nil)
|
body, err := lc.send(ctx, "POST", "/localapi/v0/debug?action="+url.QueryEscape(action), 200, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -614,7 +652,10 @@ func (lc *Client) DebugAction(ctx context.Context, action string) error {
|
|||||||
|
|
||||||
// DebugActionBody invokes a debug action with a body parameter, such as
|
// DebugActionBody invokes a debug action with a body parameter, such as
|
||||||
// "debug-force-prefer-derp".
|
// "debug-force-prefer-derp".
|
||||||
// These are development tools and subject to change or removal over time.
|
// These are development tools.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change or removal between releases.
|
||||||
func (lc *Client) DebugActionBody(ctx context.Context, action string, rbody io.Reader) error {
|
func (lc *Client) DebugActionBody(ctx context.Context, action string, rbody io.Reader) error {
|
||||||
body, err := lc.send(ctx, "POST", "/localapi/v0/debug?action="+url.QueryEscape(action), 200, rbody)
|
body, err := lc.send(ctx, "POST", "/localapi/v0/debug?action="+url.QueryEscape(action), 200, rbody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -624,7 +665,10 @@ func (lc *Client) DebugActionBody(ctx context.Context, action string, rbody io.R
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DebugResultJSON invokes a debug action and returns its result as something JSON-able.
|
// DebugResultJSON invokes a debug action and returns its result as something JSON-able.
|
||||||
// These are development tools and subject to change or removal over time.
|
// These are development tools.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change or removal between releases.
|
||||||
func (lc *Client) DebugResultJSON(ctx context.Context, action string) (any, error) {
|
func (lc *Client) DebugResultJSON(ctx context.Context, action string) (any, error) {
|
||||||
body, err := lc.send(ctx, "POST", "/localapi/v0/debug?action="+url.QueryEscape(action), 200, nil)
|
body, err := lc.send(ctx, "POST", "/localapi/v0/debug?action="+url.QueryEscape(action), 200, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -642,7 +686,10 @@ func (lc *Client) DebugResultJSON(ctx context.Context, action string) (any, erro
|
|||||||
// callers of [Client.DebugResultJSON] otherwise need to do to get a typed
|
// callers of [Client.DebugResultJSON] otherwise need to do to get a typed
|
||||||
// value.
|
// value.
|
||||||
//
|
//
|
||||||
// These are development tools and subject to change or removal over time.
|
// These are development tools.
|
||||||
|
//
|
||||||
|
// API maturity: this function is not considered a stable API and is
|
||||||
|
// subject to change or removal between releases.
|
||||||
func GetDebugResultJSON[T any](ctx context.Context, lc *Client, action string) (T, error) {
|
func GetDebugResultJSON[T any](ctx context.Context, lc *Client, action string) (T, error) {
|
||||||
var v T
|
var v T
|
||||||
body, err := lc.send(ctx, "POST", "/localapi/v0/debug?action="+url.QueryEscape(action), 200, nil)
|
body, err := lc.send(ctx, "POST", "/localapi/v0/debug?action="+url.QueryEscape(action), 200, nil)
|
||||||
@@ -684,6 +731,9 @@ func (lc *Client) SetDevStoreKeyValue(ctx context.Context, key, value string) er
|
|||||||
// SetComponentDebugLogging sets component's debug logging enabled for
|
// SetComponentDebugLogging sets component's debug logging enabled for
|
||||||
// the provided duration. If the duration is in the past, the debug logging
|
// the provided duration. If the duration is in the past, the debug logging
|
||||||
// is disabled.
|
// is disabled.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) SetComponentDebugLogging(ctx context.Context, component string, d time.Duration) error {
|
func (lc *Client) SetComponentDebugLogging(ctx context.Context, component string, d time.Duration) error {
|
||||||
if !buildfeatures.HasDebug {
|
if !buildfeatures.HasDebug {
|
||||||
return feature.ErrUnavailable
|
return feature.ErrUnavailable
|
||||||
@@ -712,6 +762,8 @@ func Status(ctx context.Context) (*ipnstate.Status, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Status returns the Tailscale daemon's status.
|
// Status returns the Tailscale daemon's status.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) Status(ctx context.Context) (*ipnstate.Status, error) {
|
func (lc *Client) Status(ctx context.Context) (*ipnstate.Status, error) {
|
||||||
return lc.status(ctx, "")
|
return lc.status(ctx, "")
|
||||||
}
|
}
|
||||||
@@ -722,6 +774,8 @@ func StatusWithoutPeers(ctx context.Context) (*ipnstate.Status, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// StatusWithoutPeers returns the Tailscale daemon's status, without the peer info.
|
// StatusWithoutPeers returns the Tailscale daemon's status, without the peer info.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) StatusWithoutPeers(ctx context.Context) (*ipnstate.Status, error) {
|
func (lc *Client) StatusWithoutPeers(ctx context.Context) (*ipnstate.Status, error) {
|
||||||
return lc.status(ctx, "?peers=false")
|
return lc.status(ctx, "?peers=false")
|
||||||
}
|
}
|
||||||
@@ -826,6 +880,9 @@ func (lc *Client) PushFile(ctx context.Context, target tailcfg.StableNodeID, siz
|
|||||||
// CheckIPForwarding asks the local Tailscale daemon whether it looks like the
|
// CheckIPForwarding asks the local Tailscale daemon whether it looks like the
|
||||||
// machine is properly configured to forward IP packets as a subnet router
|
// machine is properly configured to forward IP packets as a subnet router
|
||||||
// or exit node.
|
// or exit node.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) CheckIPForwarding(ctx context.Context) error {
|
func (lc *Client) CheckIPForwarding(ctx context.Context) error {
|
||||||
if !buildfeatures.HasAdvertiseRoutes {
|
if !buildfeatures.HasAdvertiseRoutes {
|
||||||
return nil
|
return nil
|
||||||
@@ -849,6 +906,9 @@ func (lc *Client) CheckIPForwarding(ctx context.Context) error {
|
|||||||
// CheckUDPGROForwarding asks the local Tailscale daemon whether it looks like
|
// CheckUDPGROForwarding asks the local Tailscale daemon whether it looks like
|
||||||
// the machine is optimally configured to forward UDP packets as a subnet router
|
// the machine is optimally configured to forward UDP packets as a subnet router
|
||||||
// or exit node.
|
// or exit node.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) CheckUDPGROForwarding(ctx context.Context) error {
|
func (lc *Client) CheckUDPGROForwarding(ctx context.Context) error {
|
||||||
body, err := lc.get200(ctx, "/localapi/v0/check-udp-gro-forwarding")
|
body, err := lc.get200(ctx, "/localapi/v0/check-udp-gro-forwarding")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -898,6 +958,9 @@ func (lc *Client) CheckPrefs(ctx context.Context, p *ipn.Prefs) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPrefs returns the [ipn.Prefs] of the current Tailscale profile.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) GetPrefs(ctx context.Context) (*ipn.Prefs, error) {
|
func (lc *Client) GetPrefs(ctx context.Context) (*ipn.Prefs, error) {
|
||||||
body, err := lc.get200(ctx, "/localapi/v0/prefs")
|
body, err := lc.get200(ctx, "/localapi/v0/prefs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -915,6 +978,8 @@ func (lc *Client) GetPrefs(ctx context.Context) (*ipn.Prefs, error) {
|
|||||||
// or a policy restriction. An optional reason or justification for the request can be
|
// or a policy restriction. An optional reason or justification for the request can be
|
||||||
// provided as a context value using [apitype.RequestReasonKey]. If permitted by policy,
|
// provided as a context value using [apitype.RequestReasonKey]. If permitted by policy,
|
||||||
// access may be granted, and the reason will be logged for auditing purposes.
|
// access may be granted, and the reason will be logged for auditing purposes.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) EditPrefs(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn.Prefs, error) {
|
func (lc *Client) EditPrefs(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn.Prefs, error) {
|
||||||
body, err := lc.send(ctx, "PATCH", "/localapi/v0/prefs", http.StatusOK, jsonBody(mp))
|
body, err := lc.send(ctx, "PATCH", "/localapi/v0/prefs", http.StatusOK, jsonBody(mp))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -925,6 +990,9 @@ func (lc *Client) EditPrefs(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn.Pref
|
|||||||
|
|
||||||
// GetDNSOSConfig returns the system DNS configuration for the current device.
|
// GetDNSOSConfig returns the system DNS configuration for the current device.
|
||||||
// That is, it returns the DNS configuration that the system would use if Tailscale weren't being used.
|
// That is, it returns the DNS configuration that the system would use if Tailscale weren't being used.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) GetDNSOSConfig(ctx context.Context) (*apitype.DNSOSConfig, error) {
|
func (lc *Client) GetDNSOSConfig(ctx context.Context) (*apitype.DNSOSConfig, error) {
|
||||||
if !buildfeatures.HasDNS {
|
if !buildfeatures.HasDNS {
|
||||||
return nil, feature.ErrUnavailable
|
return nil, feature.ErrUnavailable
|
||||||
@@ -958,7 +1026,26 @@ func (lc *Client) QueryDNS(ctx context.Context, name string, queryType string) (
|
|||||||
return res.Bytes, res.Resolvers, nil
|
return res.Bytes, res.Resolvers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartLoginInteractive starts an interactive login.
|
// StartLoginInteractive starts an interactive login, requesting a new
|
||||||
|
// auth URL from the control plane if a login flow is not already in
|
||||||
|
// progress. If one is, the existing auth URL is re-sent.
|
||||||
|
//
|
||||||
|
// The auth URL is not returned by this method; it is delivered
|
||||||
|
// asynchronously to IPN bus watchers (see [Client.WatchIPNBus]) as an
|
||||||
|
// [ipn.Notify] with a non-empty BrowseToURL field. StartLoginInteractive
|
||||||
|
// returns as soon as the login has been requested; it does not wait for
|
||||||
|
// the login to complete.
|
||||||
|
//
|
||||||
|
// Calling StartLoginInteractive does not itself change the node's
|
||||||
|
// desired run state, but successfully completing the login does: the
|
||||||
|
// node's WantRunning pref is set to true, so a stopped node
|
||||||
|
// ("tailscale down") starts once the login finishes. If the login is
|
||||||
|
// completed as a different user or node identity than the current
|
||||||
|
// profile's, the node switches to an existing profile matching the new
|
||||||
|
// identity if one exists, or else updates the current profile to the
|
||||||
|
// new identity.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) StartLoginInteractive(ctx context.Context) error {
|
func (lc *Client) StartLoginInteractive(ctx context.Context) error {
|
||||||
_, err := lc.send(ctx, "POST", "/localapi/v0/login-interactive", http.StatusNoContent, nil)
|
_, err := lc.send(ctx, "POST", "/localapi/v0/login-interactive", http.StatusNoContent, nil)
|
||||||
return err
|
return err
|
||||||
@@ -983,6 +1070,8 @@ func (lc *Client) Logout(ctx context.Context) error {
|
|||||||
// tailscaled), a FQDN, or an IP address.
|
// tailscaled), a FQDN, or an IP address.
|
||||||
//
|
//
|
||||||
// The ctx is only used for the duration of the call, not the lifetime of the [net.Conn].
|
// The ctx is only used for the duration of the call, not the lifetime of the [net.Conn].
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) DialTCP(ctx context.Context, host string, port uint16) (net.Conn, error) {
|
func (lc *Client) DialTCP(ctx context.Context, host string, port uint16) (net.Conn, error) {
|
||||||
return lc.UserDial(ctx, "tcp", host, port)
|
return lc.UserDial(ctx, "tcp", host, port)
|
||||||
}
|
}
|
||||||
@@ -994,6 +1083,8 @@ func (lc *Client) DialTCP(ctx context.Context, host string, port uint16) (net.Co
|
|||||||
//
|
//
|
||||||
// The ctx is only used for the duration of the call, not the lifetime of the
|
// The ctx is only used for the duration of the call, not the lifetime of the
|
||||||
// [net.Conn].
|
// [net.Conn].
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) UserDial(ctx context.Context, network, host string, port uint16) (net.Conn, error) {
|
func (lc *Client) UserDial(ctx context.Context, network, host string, port uint16) (net.Conn, error) {
|
||||||
connCh := make(chan net.Conn, 1)
|
connCh := make(chan net.Conn, 1)
|
||||||
trace := httptrace.ClientTrace{
|
trace := httptrace.ClientTrace{
|
||||||
@@ -1058,6 +1149,10 @@ func (lc *Client) UserDial(ctx context.Context, network, host string, port uint1
|
|||||||
|
|
||||||
// CurrentDERPMap returns the current DERPMap that is being used by the local tailscaled.
|
// CurrentDERPMap returns the current DERPMap that is being used by the local tailscaled.
|
||||||
// It is intended to be used with netcheck to see availability of DERPs.
|
// It is intended to be used with netcheck to see availability of DERPs.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API, though the returned
|
||||||
|
// [tailcfg.DERPMap] type is subject to minor changes over time; its
|
||||||
|
// general shape is stable.
|
||||||
func (lc *Client) CurrentDERPMap(ctx context.Context) (*tailcfg.DERPMap, error) {
|
func (lc *Client) CurrentDERPMap(ctx context.Context) (*tailcfg.DERPMap, error) {
|
||||||
var derpMap tailcfg.DERPMap
|
var derpMap tailcfg.DERPMap
|
||||||
res, err := lc.send(ctx, "GET", "/localapi/v0/derpmap", 200, nil)
|
res, err := lc.send(ctx, "GET", "/localapi/v0/derpmap", 200, nil)
|
||||||
@@ -1074,6 +1169,8 @@ func (lc *Client) CurrentDERPMap(ctx context.Context) (*tailcfg.DERPMap, error)
|
|||||||
// fetch TLS certificates, equivalent to the DNS.CertDomains field of the
|
// fetch TLS certificates, equivalent to the DNS.CertDomains field of the
|
||||||
// current netmap. The returned list is sorted in ascending order, and is
|
// current netmap. The returned list is sorted in ascending order, and is
|
||||||
// empty if no netmap has been received yet.
|
// empty if no netmap has been received yet.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) CertDomains(ctx context.Context) ([]string, error) {
|
func (lc *Client) CertDomains(ctx context.Context) ([]string, error) {
|
||||||
body, err := lc.get200(ctx, "/localapi/v0/cert-domains")
|
body, err := lc.get200(ctx, "/localapi/v0/cert-domains")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1118,6 +1215,8 @@ func (lc *Client) PeerByID(ctx context.Context, id tailcfg.NodeID) (*tailcfg.Nod
|
|||||||
// referenced by a peer Node and want to resolve it to a UserProfile. Sessions
|
// referenced by a peer Node and want to resolve it to a UserProfile. Sessions
|
||||||
// opted in to [ipn.NotifyPeerChanges] / [ipn.NotifyPeerPatches] also receive
|
// opted in to [ipn.NotifyPeerChanges] / [ipn.NotifyPeerPatches] also receive
|
||||||
// UserProfiles automatically via [ipn.Notify.UserProfiles].
|
// UserProfiles automatically via [ipn.Notify.UserProfiles].
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) UserProfile(ctx context.Context, id tailcfg.UserID) (*tailcfg.UserProfile, error) {
|
func (lc *Client) UserProfile(ctx context.Context, id tailcfg.UserID) (*tailcfg.UserProfile, error) {
|
||||||
body, err := lc.get200(ctx, "/localapi/v0/user-profile?id="+strconv.FormatInt(int64(id), 10))
|
body, err := lc.get200(ctx, "/localapi/v0/user-profile?id="+strconv.FormatInt(int64(id), 10))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1162,6 +1261,8 @@ func (lc *Client) Ping(ctx context.Context, ip netip.Addr, pingtype tailcfg.Ping
|
|||||||
// DisconnectControl shuts down all connections to control, thus making control consider this node inactive. This can be
|
// DisconnectControl shuts down all connections to control, thus making control consider this node inactive. This can be
|
||||||
// run on HA subnet router or app connector replicas before shutting them down to ensure peers get told to switch over
|
// run on HA subnet router or app connector replicas before shutting them down to ensure peers get told to switch over
|
||||||
// to another replica whilst there is still some grace period for the existing connections to terminate.
|
// to another replica whilst there is still some grace period for the existing connections to terminate.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) DisconnectControl(ctx context.Context) error {
|
func (lc *Client) DisconnectControl(ctx context.Context) error {
|
||||||
_, _, err := lc.sendWithHeaders(ctx, "POST", "/localapi/v0/disconnect-control", 200, nil, nil)
|
_, _, err := lc.sendWithHeaders(ctx, "POST", "/localapi/v0/disconnect-control", 200, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1257,13 +1358,18 @@ func (lc *Client) ReloadConfig(ctx context.Context) (ok bool, err error) {
|
|||||||
|
|
||||||
// SwitchToEmptyProfile creates and switches to a new unnamed profile. The new
|
// SwitchToEmptyProfile creates and switches to a new unnamed profile. The new
|
||||||
// profile is not assigned an ID until it is persisted after a successful login.
|
// profile is not assigned an ID until it is persisted after a successful login.
|
||||||
// In order to login to the new profile, the user must call LoginInteractive.
|
// In order to login to the new profile, the user must call
|
||||||
|
// [Client.StartLoginInteractive].
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) SwitchToEmptyProfile(ctx context.Context) error {
|
func (lc *Client) SwitchToEmptyProfile(ctx context.Context) error {
|
||||||
_, err := lc.send(ctx, "PUT", "/localapi/v0/profiles/", http.StatusCreated, nil)
|
_, err := lc.send(ctx, "PUT", "/localapi/v0/profiles/", http.StatusCreated, nil)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SwitchProfile switches to the given profile.
|
// SwitchProfile switches to the given profile.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) SwitchProfile(ctx context.Context, profile ipn.ProfileID) error {
|
func (lc *Client) SwitchProfile(ctx context.Context, profile ipn.ProfileID) error {
|
||||||
_, err := lc.send(ctx, "POST", "/localapi/v0/profiles/"+url.PathEscape(string(profile)), 204, nil)
|
_, err := lc.send(ctx, "POST", "/localapi/v0/profiles/"+url.PathEscape(string(profile)), 204, nil)
|
||||||
return err
|
return err
|
||||||
@@ -1298,6 +1404,11 @@ func (lc *Client) QueryFeature(ctx context.Context, feature string) (*tailcfg.Qu
|
|||||||
return decodeJSON[*tailcfg.QueryFeatureResponse](body)
|
return decodeJSON[*tailcfg.QueryFeatureResponse](body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DebugDERPRegion reports diagnostic information about the DERP region with
|
||||||
|
// the given ID or code.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) DebugDERPRegion(ctx context.Context, regionIDOrCode string) (*ipnstate.DebugDERPRegionReport, error) {
|
func (lc *Client) DebugDERPRegion(ctx context.Context, regionIDOrCode string) (*ipnstate.DebugDERPRegionReport, error) {
|
||||||
v := url.Values{"region": {regionIDOrCode}}
|
v := url.Values{"region": {regionIDOrCode}}
|
||||||
body, err := lc.send(ctx, "POST", "/localapi/v0/debug-derp-region?"+v.Encode(), 200, nil)
|
body, err := lc.send(ctx, "POST", "/localapi/v0/debug-derp-region?"+v.Encode(), 200, nil)
|
||||||
@@ -1308,6 +1419,9 @@ func (lc *Client) DebugDERPRegion(ctx context.Context, regionIDOrCode string) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DebugPacketFilterRules returns the packet filter rules for the current device.
|
// DebugPacketFilterRules returns the packet filter rules for the current device.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) DebugPacketFilterRules(ctx context.Context) ([]tailcfg.FilterRule, error) {
|
func (lc *Client) DebugPacketFilterRules(ctx context.Context) ([]tailcfg.FilterRule, error) {
|
||||||
body, err := lc.send(ctx, "POST", "/localapi/v0/debug-packet-filter-rules", 200, nil)
|
body, err := lc.send(ctx, "POST", "/localapi/v0/debug-packet-filter-rules", 200, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1319,6 +1433,9 @@ func (lc *Client) DebugPacketFilterRules(ctx context.Context) ([]tailcfg.FilterR
|
|||||||
// DebugSetExpireIn marks the current node key to expire in d.
|
// DebugSetExpireIn marks the current node key to expire in d.
|
||||||
//
|
//
|
||||||
// This is meant primarily for debug and testing.
|
// This is meant primarily for debug and testing.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) DebugSetExpireIn(ctx context.Context, d time.Duration) error {
|
func (lc *Client) DebugSetExpireIn(ctx context.Context, d time.Duration) error {
|
||||||
v := url.Values{"expiry": {fmt.Sprint(time.Now().Add(d).Unix())}}
|
v := url.Values{"expiry": {fmt.Sprint(time.Now().Add(d).Unix())}}
|
||||||
_, err := lc.send(ctx, "POST", "/localapi/v0/set-expiry-sooner?"+v.Encode(), 200, nil)
|
_, err := lc.send(ctx, "POST", "/localapi/v0/set-expiry-sooner?"+v.Encode(), 200, nil)
|
||||||
@@ -1327,6 +1444,9 @@ func (lc *Client) DebugSetExpireIn(ctx context.Context, d time.Duration) error {
|
|||||||
|
|
||||||
// DebugPeerRelaySessions returns debug information about the current peer
|
// DebugPeerRelaySessions returns debug information about the current peer
|
||||||
// relay sessions running through this node.
|
// relay sessions running through this node.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) DebugPeerRelaySessions(ctx context.Context) (*status.ServerStatus, error) {
|
func (lc *Client) DebugPeerRelaySessions(ctx context.Context) (*status.ServerStatus, error) {
|
||||||
body, err := lc.send(ctx, "GET", "/localapi/v0/debug-peer-relay-sessions", 200, nil)
|
body, err := lc.send(ctx, "GET", "/localapi/v0/debug-peer-relay-sessions", 200, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1339,6 +1459,9 @@ func (lc *Client) DebugPeerRelaySessions(ctx context.Context) (*status.ServerSta
|
|||||||
//
|
//
|
||||||
// The provided context does not determine the lifetime of the
|
// The provided context does not determine the lifetime of the
|
||||||
// returned [io.ReadCloser].
|
// returned [io.ReadCloser].
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) StreamDebugCapture(ctx context.Context) (io.ReadCloser, error) {
|
func (lc *Client) StreamDebugCapture(ctx context.Context) (io.ReadCloser, error) {
|
||||||
req, err := http.NewRequestWithContext(ctx, "POST", "http://"+apitype.LocalAPIHost+"/localapi/v0/debug-capture", nil)
|
req, err := http.NewRequestWithContext(ctx, "POST", "http://"+apitype.LocalAPIHost+"/localapi/v0/debug-capture", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1365,6 +1488,9 @@ func (lc *Client) StreamDebugCapture(ctx context.Context) (io.ReadCloser, error)
|
|||||||
// resources.
|
// resources.
|
||||||
//
|
//
|
||||||
// A default set of ipn.Notify messages are returned but the set can be modified by mask.
|
// A default set of ipn.Notify messages are returned but the set can be modified by mask.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) WatchIPNBus(ctx context.Context, mask ipn.NotifyWatchOpt) (*IPNBusWatcher, error) {
|
func (lc *Client) WatchIPNBus(ctx context.Context, mask ipn.NotifyWatchOpt) (*IPNBusWatcher, error) {
|
||||||
m, err := mask.MarshalText()
|
m, err := mask.MarshalText()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1395,6 +1521,8 @@ func (lc *Client) WatchIPNBus(ctx context.Context, mask ipn.NotifyWatchOpt) (*IP
|
|||||||
// CheckUpdate returns a [*tailcfg.ClientVersion] indicating whether or not an update is available
|
// CheckUpdate returns a [*tailcfg.ClientVersion] indicating whether or not an update is available
|
||||||
// to be installed via the LocalAPI. In case the LocalAPI can't install updates, it returns a
|
// to be installed via the LocalAPI. In case the LocalAPI can't install updates, it returns a
|
||||||
// ClientVersion that says that we are up to date.
|
// ClientVersion that says that we are up to date.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) CheckUpdate(ctx context.Context) (*tailcfg.ClientVersion, error) {
|
func (lc *Client) CheckUpdate(ctx context.Context) (*tailcfg.ClientVersion, error) {
|
||||||
body, err := lc.get200(ctx, "/localapi/v0/update/check")
|
body, err := lc.get200(ctx, "/localapi/v0/update/check")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1411,6 +1539,8 @@ func (lc *Client) CheckUpdate(ctx context.Context) (*tailcfg.ClientVersion, erro
|
|||||||
// To turn it on, there must have been a previously used exit node.
|
// To turn it on, there must have been a previously used exit node.
|
||||||
// The most previously used one is reused.
|
// The most previously used one is reused.
|
||||||
// This is a convenience method for GUIs. To select an actual one, update the prefs.
|
// This is a convenience method for GUIs. To select an actual one, update the prefs.
|
||||||
|
//
|
||||||
|
// API maturity: this is considered a stable API.
|
||||||
func (lc *Client) SetUseExitNode(ctx context.Context, on bool) error {
|
func (lc *Client) SetUseExitNode(ctx context.Context, on bool) error {
|
||||||
_, err := lc.send(ctx, "POST", "/localapi/v0/set-use-exit-node-enabled?enabled="+strconv.FormatBool(on), http.StatusOK, nil)
|
_, err := lc.send(ctx, "POST", "/localapi/v0/set-use-exit-node-enabled?enabled="+strconv.FormatBool(on), http.StatusOK, nil)
|
||||||
return err
|
return err
|
||||||
@@ -1419,6 +1549,9 @@ func (lc *Client) SetUseExitNode(ctx context.Context, on bool) error {
|
|||||||
// DriveSetServerAddr instructs Taildrive to use the server at addr to access
|
// DriveSetServerAddr instructs Taildrive to use the server at addr to access
|
||||||
// the filesystem. This is used on platforms like Windows and MacOS to let
|
// the filesystem. This is used on platforms like Windows and MacOS to let
|
||||||
// Taildrive know to use the file server running in the GUI app.
|
// Taildrive know to use the file server running in the GUI app.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) DriveSetServerAddr(ctx context.Context, addr string) error {
|
func (lc *Client) DriveSetServerAddr(ctx context.Context, addr string) error {
|
||||||
_, err := lc.send(ctx, "PUT", "/localapi/v0/drive/fileserver-address", http.StatusCreated, strings.NewReader(addr))
|
_, err := lc.send(ctx, "PUT", "/localapi/v0/drive/fileserver-address", http.StatusCreated, strings.NewReader(addr))
|
||||||
return err
|
return err
|
||||||
@@ -1427,6 +1560,9 @@ func (lc *Client) DriveSetServerAddr(ctx context.Context, addr string) error {
|
|||||||
// DriveShareSet adds or updates the given share in the list of shares that
|
// DriveShareSet adds or updates the given share in the list of shares that
|
||||||
// Taildrive will serve to remote nodes. If a share with the same name already
|
// Taildrive will serve to remote nodes. If a share with the same name already
|
||||||
// exists, the existing share is replaced/updated.
|
// exists, the existing share is replaced/updated.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) DriveShareSet(ctx context.Context, share *drive.Share) error {
|
func (lc *Client) DriveShareSet(ctx context.Context, share *drive.Share) error {
|
||||||
_, err := lc.send(ctx, "PUT", "/localapi/v0/drive/shares", http.StatusCreated, jsonBody(share))
|
_, err := lc.send(ctx, "PUT", "/localapi/v0/drive/shares", http.StatusCreated, jsonBody(share))
|
||||||
return err
|
return err
|
||||||
@@ -1434,6 +1570,9 @@ func (lc *Client) DriveShareSet(ctx context.Context, share *drive.Share) error {
|
|||||||
|
|
||||||
// DriveShareRemove removes the share with the given name from the list of
|
// DriveShareRemove removes the share with the given name from the list of
|
||||||
// shares that Taildrive will serve to remote nodes.
|
// shares that Taildrive will serve to remote nodes.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) DriveShareRemove(ctx context.Context, name string) error {
|
func (lc *Client) DriveShareRemove(ctx context.Context, name string) error {
|
||||||
_, err := lc.send(
|
_, err := lc.send(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -1445,6 +1584,9 @@ func (lc *Client) DriveShareRemove(ctx context.Context, name string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DriveShareRename renames the share from old to new name.
|
// DriveShareRename renames the share from old to new name.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) DriveShareRename(ctx context.Context, oldName, newName string) error {
|
func (lc *Client) DriveShareRename(ctx context.Context, oldName, newName string) error {
|
||||||
_, err := lc.send(
|
_, err := lc.send(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -1457,6 +1599,9 @@ func (lc *Client) DriveShareRename(ctx context.Context, oldName, newName string)
|
|||||||
|
|
||||||
// DriveShareList returns the list of shares that drive is currently serving
|
// DriveShareList returns the list of shares that drive is currently serving
|
||||||
// to remote nodes.
|
// to remote nodes.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) DriveShareList(ctx context.Context) ([]*drive.Share, error) {
|
func (lc *Client) DriveShareList(ctx context.Context) ([]*drive.Share, error) {
|
||||||
result, err := lc.get200(ctx, "/localapi/v0/drive/shares")
|
result, err := lc.get200(ctx, "/localapi/v0/drive/shares")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1529,6 +1674,9 @@ func (lc *Client) SuggestExitNodeWithProbe(ctx context.Context) (apitype.ExitNod
|
|||||||
|
|
||||||
// CheckSOMarkInUse reports whether the socket mark option is in use. This will only
|
// CheckSOMarkInUse reports whether the socket mark option is in use. This will only
|
||||||
// be true if tailscale is running on Linux and tailscaled uses SO_MARK.
|
// be true if tailscale is running on Linux and tailscaled uses SO_MARK.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) CheckSOMarkInUse(ctx context.Context) (bool, error) {
|
func (lc *Client) CheckSOMarkInUse(ctx context.Context) (bool, error) {
|
||||||
body, err := lc.get200(ctx, "/localapi/v0/check-so-mark-in-use")
|
body, err := lc.get200(ctx, "/localapi/v0/check-so-mark-in-use")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1545,11 +1693,19 @@ func (lc *Client) CheckSOMarkInUse(ctx context.Context) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ShutdownTailscaled requests a graceful shutdown of tailscaled.
|
// ShutdownTailscaled requests a graceful shutdown of tailscaled.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) ShutdownTailscaled(ctx context.Context) error {
|
func (lc *Client) ShutdownTailscaled(ctx context.Context) error {
|
||||||
_, err := lc.send(ctx, "POST", "/localapi/v0/shutdown", 200, nil)
|
_, err := lc.send(ctx, "POST", "/localapi/v0/shutdown", 200, nil)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAppConnectorRouteInfo returns the current [appctype.RouteInfo] for this
|
||||||
|
// node's app connector.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) GetAppConnectorRouteInfo(ctx context.Context) (appctype.RouteInfo, error) {
|
func (lc *Client) GetAppConnectorRouteInfo(ctx context.Context) (appctype.RouteInfo, error) {
|
||||||
body, err := lc.get200(ctx, "/localapi/v0/appc-route-info")
|
body, err := lc.get200(ctx, "/localapi/v0/appc-route-info")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ import (
|
|||||||
// GetServeConfig return the current serve config.
|
// GetServeConfig return the current serve config.
|
||||||
//
|
//
|
||||||
// If the serve config is empty, it returns (nil, nil).
|
// If the serve config is empty, it returns (nil, nil).
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) GetServeConfig(ctx context.Context) (*ipn.ServeConfig, error) {
|
func (lc *Client) GetServeConfig(ctx context.Context) (*ipn.ServeConfig, error) {
|
||||||
body, h, err := lc.sendWithHeaders(ctx, "GET", "/localapi/v0/serve-config", 200, nil, nil)
|
body, h, err := lc.sendWithHeaders(ctx, "GET", "/localapi/v0/serve-config", 200, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// GetEffectivePolicy returns the effective policy for the specified scope.
|
// GetEffectivePolicy returns the effective policy for the specified scope.
|
||||||
|
//
|
||||||
|
// API maturity: this method is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
func (lc *Client) GetEffectivePolicy(ctx context.Context, scope setting.PolicyScope) (*setting.Snapshot, error) {
|
func (lc *Client) GetEffectivePolicy(ctx context.Context, scope setting.PolicyScope) (*setting.Snapshot, error) {
|
||||||
scopeID, err := scope.MarshalText()
|
scopeID, err := scope.MarshalText()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -294,6 +294,9 @@ func ValidateNotifyWatchOpt(mask NotifyWatchOpt) error {
|
|||||||
// In any given notification, any or all of these may be nil, meaning
|
// In any given notification, any or all of these may be nil, meaning
|
||||||
// that they have not changed.
|
// that they have not changed.
|
||||||
// They are JSON-encoded on the wire, despite the lack of struct tags.
|
// They are JSON-encoded on the wire, despite the lack of struct tags.
|
||||||
|
//
|
||||||
|
// API maturity: this type is not considered a stable API and is
|
||||||
|
// subject to change between releases.
|
||||||
type Notify struct {
|
type Notify struct {
|
||||||
_ structs.Incomparable
|
_ structs.Incomparable
|
||||||
Version string // version number of IPN backend
|
Version string // version number of IPN backend
|
||||||
|
|||||||
+2
-1
@@ -291,7 +291,8 @@ func (v PrefsView) InternalExitNodePrior() tailcfg.StableNodeID { return v.ж.In
|
|||||||
func (v PrefsView) ExitNodeAllowLANAccess() bool { return v.ж.ExitNodeAllowLANAccess }
|
func (v PrefsView) ExitNodeAllowLANAccess() bool { return v.ж.ExitNodeAllowLANAccess }
|
||||||
|
|
||||||
// CorpDNS specifies whether to install the Tailscale network's
|
// CorpDNS specifies whether to install the Tailscale network's
|
||||||
// DNS configuration, if it exists.
|
// DNS configuration, if it exists. It is the internal name for
|
||||||
|
// the "tailscale set --accept-dns=" flag.
|
||||||
func (v PrefsView) CorpDNS() bool { return v.ж.CorpDNS }
|
func (v PrefsView) CorpDNS() bool { return v.ж.CorpDNS }
|
||||||
|
|
||||||
// RunSSH bool is whether this node should run an SSH
|
// RunSSH bool is whether this node should run an SSH
|
||||||
|
|||||||
+2
-1
@@ -130,7 +130,8 @@ type Prefs struct {
|
|||||||
ExitNodeAllowLANAccess bool
|
ExitNodeAllowLANAccess bool
|
||||||
|
|
||||||
// CorpDNS specifies whether to install the Tailscale network's
|
// CorpDNS specifies whether to install the Tailscale network's
|
||||||
// DNS configuration, if it exists.
|
// DNS configuration, if it exists. It is the internal name for
|
||||||
|
// the "tailscale set --accept-dns=" flag.
|
||||||
CorpDNS bool
|
CorpDNS bool
|
||||||
|
|
||||||
// RunSSH bool is whether this node should run an SSH
|
// RunSSH bool is whether this node should run an SSH
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// DERPMap describes the set of DERP packet relay servers that are available.
|
// DERPMap describes the set of DERP packet relay servers that are available.
|
||||||
|
//
|
||||||
|
// API maturity: this type is subject to minor changes over time, though
|
||||||
|
// its general shape is stable.
|
||||||
type DERPMap struct {
|
type DERPMap struct {
|
||||||
// HomeParams, if non-nil, is a change in home parameters.
|
// HomeParams, if non-nil, is a change in home parameters.
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user