Browse Source

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

Signed-off-by: Maisem Ali <[email protected]>
Maisem Ali 4 years ago
parent
commit
81cabf48ec

+ 2 - 5
control/controlclient/auto.go

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

+ 3 - 0
control/controlclient/direct.go

@@ -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",
 		resp.NodeKeyExpired, resp.MachineAuthorized, resp.AuthURL != "")
 
+	if resp.Error != "" {
+		return false, "", errors.New(resp.Error)
+	}
 	if resp.NodeKeyExpired {
 		if regen {
 			return true, "", fmt.Errorf("weird: regen=true but server says NodeKeyExpired: %v", request.NodeKey)

+ 1 - 1
control/controlclient/status.go

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

+ 4 - 2
ipn/ipnlocal/local.go

@@ -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.
 func (b *LocalBackend) setClientStatus(st controlclient.Status) {
 	// 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.
-		if st.Err == "EOF" {
+		if errors.Is(st.Err, io.EOF) {
 			b.logf("[v1] Received error: EOF")
 		} else {
 			b.logf("Received error: %v", st.Err)
+			e := st.Err.Error()
+			b.send(ipn.Notify{ErrMessage: &e})
 		}
 		return
 	}

+ 1 - 3
ipn/ipnlocal/state_test.go

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

+ 4 - 0
tailcfg/tailcfg.go

@@ -679,6 +679,10 @@ type RegisterResponse struct {
 	NodeKeyExpired    bool   // if true, the NodeKey needs to be replaced
 	MachineAuthorized bool   // TODO(crawshaw): move to using MachineStatus
 	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.

+ 1 - 0
tailcfg/tailcfg_clone.go

@@ -243,6 +243,7 @@ var _RegisterResponseCloneNeedsRegeneration = RegisterResponse(struct {
 	NodeKeyExpired    bool
 	MachineAuthorized bool
 	AuthURL           string
+	Error             string
 }{})
 
 // Clone makes a deep copy of DERPRegion.

+ 2 - 2
tstest/integration/integration_test.go

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