control/controlclient,tailcfg: propagate registration errors to the frontend

Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
Maisem Ali 2021-10-26 10:19:35 -07:00 committed by Maisem Ali
parent 139a6c4c9c
commit 81cabf48ec
8 changed files with 18 additions and 13 deletions

View File

@ -281,7 +281,6 @@ func (c *Auto) authRoutine() {
report := func(err error, msg string) { report := func(err error, msg string) {
c.logf("[v1] %s: %v", msg, err) c.logf("[v1] %s: %v", msg, err)
err = fmt.Errorf("%s: %v", msg, err)
// don't send status updates for context errors, // don't send status updates for context errors,
// since context cancelation is always on purpose. // since context cancelation is always on purpose.
if ctx.Err() == nil { if ctx.Err() == nil {
@ -431,7 +430,7 @@ func (c *Auto) mapRoutine() {
report := func(err error, msg string) { report := func(err error, msg string) {
c.logf("[v1] %s: %v", msg, err) c.logf("[v1] %s: %v", msg, err)
err = fmt.Errorf("%s: %v", msg, err) err = fmt.Errorf("%s: %w", msg, err)
// don't send status updates for context errors, // don't send status updates for context errors,
// since context cancelation is always on purpose. // since context cancelation is always on purpose.
if ctx.Err() == nil { if ctx.Err() == nil {
@ -599,9 +598,7 @@ func (c *Auto) sendStatus(who string, err error, url string, nm *netmap.NetworkM
NetMap: nm, NetMap: nm,
Hostinfo: hi, Hostinfo: hi,
State: state, State: state,
} Err: err,
if err != nil {
new.Err = err.Error()
} }
if statusFunc != nil { if statusFunc != nil {
statusFunc(new) statusFunc(new)

View File

@ -435,6 +435,9 @@ func (c *Direct) doLogin(ctx context.Context, opt loginOpt) (mustRegen bool, new
c.logf("RegisterReq: got response; nodeKeyExpired=%v, machineAuthorized=%v; authURL=%v", c.logf("RegisterReq: got response; nodeKeyExpired=%v, machineAuthorized=%v; authURL=%v",
resp.NodeKeyExpired, resp.MachineAuthorized, resp.AuthURL != "") resp.NodeKeyExpired, resp.MachineAuthorized, resp.AuthURL != "")
if resp.Error != "" {
return false, "", errors.New(resp.Error)
}
if resp.NodeKeyExpired { if resp.NodeKeyExpired {
if regen { if regen {
return true, "", fmt.Errorf("weird: regen=true but server says NodeKeyExpired: %v", request.NodeKey) return true, "", fmt.Errorf("weird: regen=true but server says NodeKeyExpired: %v", request.NodeKey)

View File

@ -67,7 +67,7 @@ type Status struct {
_ structs.Incomparable _ structs.Incomparable
LoginFinished *empty.Message // nonempty when login finishes LoginFinished *empty.Message // nonempty when login finishes
LogoutFinished *empty.Message // nonempty when logout finishes LogoutFinished *empty.Message // nonempty when logout finishes
Err string Err error
URL string // interactive URL to visit to finish logging in URL string // interactive URL to visit to finish logging in
NetMap *netmap.NetworkMap // server-pushed configuration NetMap *netmap.NetworkMap // server-pushed configuration

View File

@ -448,12 +448,14 @@ func (b *LocalBackend) SetDecompressor(fn func() (controlclient.Decompressor, er
// Among other things, this is where we update the netmap, packet filters, DNS and DERP maps. // Among other things, this is where we update the netmap, packet filters, DNS and DERP maps.
func (b *LocalBackend) setClientStatus(st controlclient.Status) { func (b *LocalBackend) setClientStatus(st controlclient.Status) {
// The following do not depend on any data for which we need to lock b. // The following do not depend on any data for which we need to lock b.
if st.Err != "" { if st.Err != nil {
// TODO(crawshaw): display in the UI. // TODO(crawshaw): display in the UI.
if st.Err == "EOF" { if errors.Is(st.Err, io.EOF) {
b.logf("[v1] Received error: EOF") b.logf("[v1] Received error: EOF")
} else { } else {
b.logf("Received error: %v", st.Err) b.logf("Received error: %v", st.Err)
e := st.Err.Error()
b.send(ipn.Notify{ErrMessage: &e})
} }
return return
} }

View File

@ -137,9 +137,7 @@ func (cc *mockControl) send(err error, url string, loginFinished bool, nm *netma
URL: url, URL: url,
NetMap: nm, NetMap: nm,
Persist: &cc.persist, Persist: &cc.persist,
} Err: err,
if err != nil {
s.Err = err.Error()
} }
if loginFinished { if loginFinished {
s.LoginFinished = &empty.Message{} s.LoginFinished = &empty.Message{}

View File

@ -679,6 +679,10 @@ type RegisterResponse struct {
NodeKeyExpired bool // if true, the NodeKey needs to be replaced NodeKeyExpired bool // if true, the NodeKey needs to be replaced
MachineAuthorized bool // TODO(crawshaw): move to using MachineStatus MachineAuthorized bool // TODO(crawshaw): move to using MachineStatus
AuthURL string // if set, authorization pending AuthURL string // if set, authorization pending
// Error indiciates that authorization failed. If this is non-empty,
// other status fields should be ignored.
Error string
} }
// EndpointType distinguishes different sources of MapRequest.Endpoint values. // EndpointType distinguishes different sources of MapRequest.Endpoint values.

View File

@ -243,6 +243,7 @@ func (src *RegisterResponse) Clone() *RegisterResponse {
NodeKeyExpired bool NodeKeyExpired bool
MachineAuthorized bool MachineAuthorized bool
AuthURL string AuthURL string
Error string
}{}) }{})
// Clone makes a deep copy of DERPRegion. // Clone makes a deep copy of DERPRegion.

View File

@ -696,8 +696,8 @@ func (n *testNode) MustUp(extraArgs ...string) {
} }
args = append(args, extraArgs...) args = append(args, extraArgs...)
t.Logf("Running %v ...", args) t.Logf("Running %v ...", args)
if err := n.Tailscale(args...).Run(); err != nil { if b, err := n.Tailscale(args...).CombinedOutput(); err != nil {
t.Fatalf("up: %v", err) t.Fatalf("up: %v, %v", string(b), err)
} }
} }