mirror of
https://github.com/tailscale/tailscale.git
synced 2024-12-01 14:05:39 +00:00
cmd/tailscale, ipn/localapi: get daemon version from localapi status
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
d0dffe33c0
commit
439d70dce2
@ -103,7 +103,16 @@ func Goroutines(ctx context.Context) ([]byte, error) {
|
||||
|
||||
// Status returns the Tailscale daemon's status.
|
||||
func Status(ctx context.Context) (*ipnstate.Status, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", "http://local-tailscaled.sock/localapi/v0/status", nil)
|
||||
return status(ctx, "")
|
||||
}
|
||||
|
||||
// StatusWithPeers returns the Tailscale daemon's status, without the peer info.
|
||||
func StatusWithoutPeers(ctx context.Context) (*ipnstate.Status, error) {
|
||||
return status(ctx, "?peers=false")
|
||||
}
|
||||
|
||||
func status(ctx context.Context, queryString string) (*ipnstate.Status, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", "http://local-tailscaled.sock/localapi/v0/status"+queryString, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
"log"
|
||||
|
||||
"github.com/peterbourgon/ff/v2/ffcli"
|
||||
"tailscale.com/ipn"
|
||||
"tailscale.com/client/tailscale"
|
||||
"tailscale.com/version"
|
||||
)
|
||||
|
||||
@ -42,29 +42,10 @@ func runVersion(ctx context.Context, args []string) error {
|
||||
|
||||
fmt.Printf("Client: %s\n", version.String())
|
||||
|
||||
c, bc, ctx, cancel := connect(ctx)
|
||||
defer cancel()
|
||||
|
||||
bc.AllowVersionSkew = true
|
||||
|
||||
done := make(chan struct{})
|
||||
|
||||
bc.SetNotifyCallback(func(n ipn.Notify) {
|
||||
if n.ErrMessage != nil {
|
||||
log.Fatal(*n.ErrMessage)
|
||||
st, err := tailscale.StatusWithoutPeers(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n.Engine != nil {
|
||||
fmt.Printf("Daemon: %s\n", n.Version)
|
||||
close(done)
|
||||
}
|
||||
})
|
||||
go pump(ctx, bc, c)
|
||||
|
||||
bc.RequestEngineStatus()
|
||||
select {
|
||||
case <-done:
|
||||
fmt.Printf("Daemon: %s\n", st.Version)
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
|
@ -218,20 +218,45 @@ func (b *LocalBackend) Status() *ipnstate.Status {
|
||||
return sb.Status()
|
||||
}
|
||||
|
||||
// StatusWithoutPeers is like Status but omits any details
|
||||
// of peers.
|
||||
func (b *LocalBackend) StatusWithoutPeers() *ipnstate.Status {
|
||||
sb := new(ipnstate.StatusBuilder)
|
||||
b.updateStatus(sb, nil)
|
||||
return sb.Status()
|
||||
}
|
||||
|
||||
// UpdateStatus implements ipnstate.StatusUpdater.
|
||||
func (b *LocalBackend) UpdateStatus(sb *ipnstate.StatusBuilder) {
|
||||
b.e.UpdateStatus(sb)
|
||||
b.updateStatus(sb, b.populatePeerStatusLocked)
|
||||
}
|
||||
|
||||
// updateStatus populates sb with status.
|
||||
//
|
||||
// extraLocked, if non-nil, is called while b.mu is still held.
|
||||
func (b *LocalBackend) updateStatus(sb *ipnstate.StatusBuilder, extraLocked func(*ipnstate.StatusBuilder)) {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
|
||||
sb.SetVersion(version.Long)
|
||||
sb.SetBackendState(b.state.String())
|
||||
sb.SetAuthURL(b.authURL)
|
||||
|
||||
// TODO: hostinfo, and its networkinfo
|
||||
// TODO: EngineStatus copy (and deprecate it?)
|
||||
|
||||
if b.netMap != nil {
|
||||
sb.SetMagicDNSSuffix(b.netMap.MagicDNSSuffix())
|
||||
}
|
||||
|
||||
if extraLocked != nil {
|
||||
extraLocked(sb)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *LocalBackend) populatePeerStatusLocked(sb *ipnstate.StatusBuilder) {
|
||||
if b.netMap == nil {
|
||||
return
|
||||
}
|
||||
for id, up := range b.netMap.UserProfiles {
|
||||
sb.AddUser(id, up)
|
||||
}
|
||||
@ -265,7 +290,6 @@ func (b *LocalBackend) UpdateStatus(sb *ipnstate.StatusBuilder) {
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WhoIs reports the node and user who owns the node with the given IP:port.
|
||||
// If the IP address is a Tailscale IP, the provided port may be 0.
|
||||
|
@ -26,7 +26,14 @@
|
||||
|
||||
// Status represents the entire state of the IPN network.
|
||||
type Status struct {
|
||||
// Version is the daemon's long version (see version.Long).
|
||||
Version string
|
||||
|
||||
// BackendState is an ipn.State string value:
|
||||
// "NoState", "NeedsLogin", "NeedsMachineAuth", "Stopped",
|
||||
// "Starting", "Running".
|
||||
BackendState string
|
||||
|
||||
AuthURL string // current URL provided by control to authorize client
|
||||
TailscaleIPs []netaddr.IP // Tailscale IP(s) assigned to this node
|
||||
Self *PeerStatus
|
||||
@ -105,6 +112,12 @@ type StatusBuilder struct {
|
||||
st Status
|
||||
}
|
||||
|
||||
func (sb *StatusBuilder) SetVersion(v string) {
|
||||
sb.mu.Lock()
|
||||
defer sb.mu.Unlock()
|
||||
sb.st.Version = v
|
||||
}
|
||||
|
||||
func (sb *StatusBuilder) SetBackendState(v string) {
|
||||
sb.mu.Lock()
|
||||
defer sb.mu.Unlock()
|
||||
|
@ -10,9 +10,11 @@
|
||||
"io"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
||||
"inet.af/netaddr"
|
||||
"tailscale.com/ipn/ipnlocal"
|
||||
"tailscale.com/ipn/ipnstate"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
@ -118,7 +120,24 @@ func (h *Handler) serveStatus(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var st *ipnstate.Status
|
||||
if defBool(r.FormValue("peers"), true) {
|
||||
st = h.b.Status()
|
||||
} else {
|
||||
st = h.b.StatusWithoutPeers()
|
||||
}
|
||||
e := json.NewEncoder(w)
|
||||
e.SetIndent("", "\t")
|
||||
e.Encode(h.b.Status())
|
||||
e.Encode(st)
|
||||
}
|
||||
|
||||
func defBool(a string, def bool) bool {
|
||||
if a == "" {
|
||||
return def
|
||||
}
|
||||
v, err := strconv.ParseBool(a)
|
||||
if err != nil {
|
||||
return def
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user