mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-01 09:32:08 +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:
@@ -218,52 +218,76 @@ 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())
|
||||
for id, up := range b.netMap.UserProfiles {
|
||||
sb.AddUser(id, up)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
for _, p := range b.netMap.Peers {
|
||||
var lastSeen time.Time
|
||||
if p.LastSeen != nil {
|
||||
lastSeen = *p.LastSeen
|
||||
}
|
||||
for _, p := range b.netMap.Peers {
|
||||
var lastSeen time.Time
|
||||
if p.LastSeen != nil {
|
||||
lastSeen = *p.LastSeen
|
||||
var tailAddr string
|
||||
for _, addr := range p.Addresses {
|
||||
// The peer struct currently only allows a single
|
||||
// Tailscale IP address. For compatibility with the
|
||||
// old display, make sure it's the IPv4 address.
|
||||
if addr.IP.Is4() && addr.IsSingleIP() && tsaddr.IsTailscaleIP(addr.IP) {
|
||||
tailAddr = addr.IP.String()
|
||||
break
|
||||
}
|
||||
var tailAddr string
|
||||
for _, addr := range p.Addresses {
|
||||
// The peer struct currently only allows a single
|
||||
// Tailscale IP address. For compatibility with the
|
||||
// old display, make sure it's the IPv4 address.
|
||||
if addr.IP.Is4() && addr.IsSingleIP() && tsaddr.IsTailscaleIP(addr.IP) {
|
||||
tailAddr = addr.IP.String()
|
||||
break
|
||||
}
|
||||
}
|
||||
sb.AddPeer(key.Public(p.Key), &ipnstate.PeerStatus{
|
||||
InNetworkMap: true,
|
||||
UserID: p.User,
|
||||
TailAddr: tailAddr,
|
||||
HostName: p.Hostinfo.Hostname,
|
||||
DNSName: p.Name,
|
||||
OS: p.Hostinfo.OS,
|
||||
KeepAlive: p.KeepAlive,
|
||||
Created: p.Created,
|
||||
LastSeen: lastSeen,
|
||||
ShareeNode: p.Hostinfo.ShareeNode,
|
||||
ExitNode: p.StableID != "" && p.StableID == b.prefs.ExitNodeID,
|
||||
})
|
||||
}
|
||||
sb.AddPeer(key.Public(p.Key), &ipnstate.PeerStatus{
|
||||
InNetworkMap: true,
|
||||
UserID: p.User,
|
||||
TailAddr: tailAddr,
|
||||
HostName: p.Hostinfo.Hostname,
|
||||
DNSName: p.Name,
|
||||
OS: p.Hostinfo.OS,
|
||||
KeepAlive: p.KeepAlive,
|
||||
Created: p.Created,
|
||||
LastSeen: lastSeen,
|
||||
ShareeNode: p.Hostinfo.ShareeNode,
|
||||
ExitNode: p.StableID != "" && p.StableID == b.prefs.ExitNodeID,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,14 @@ import (
|
||||
|
||||
// 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 @@ import (
|
||||
"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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user