cmd/tailscale/main: use localapi for login and add tests. (#157)

pull/170/head
kari-ts 9 months ago committed by GitHub
parent e90f39a58c
commit 98fe1e86e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -7,8 +7,6 @@ import (
"net" "net"
"net/http" "net/http"
"sync" "sync"
"tailscale.com/ipn/localapi"
) )
// Response represents the result of processing an http.Request. // Response represents the result of processing an http.Request.
@ -53,10 +51,10 @@ func (r *Response) Flush() {
} }
type LocalAPIClient struct { type LocalAPIClient struct {
h *localapi.Handler h http.Handler
} }
func New(h *localapi.Handler) *LocalAPIClient { func New(h http.Handler) *LocalAPIClient {
return &LocalAPIClient{h: h} return &LocalAPIClient{h: h}
} }

@ -0,0 +1,73 @@
package localapiclient
import (
"context"
"io"
"net/http"
"testing"
"time"
)
var ctx = context.Background()
type BadStatusHandler struct{}
func (b *BadStatusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadRequest)
}
func TestBadStatus(t *testing.T) {
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(2*time.Second))
client := New(&BadStatusHandler{})
defer cancel()
_, err := client.Call(ctx, "POST", "test", nil)
if err.Error() != "request failed with status code 400" {
t.Error("Expected bad status error, but got", err)
}
}
type TimeoutHandler struct{}
var successfulResponse = "successful response!"
func (b *TimeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
time.Sleep(6 * time.Second)
w.Write([]byte(successfulResponse))
}
func TestTimeout(t *testing.T) {
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(2*time.Second))
client := New(&TimeoutHandler{})
defer cancel()
_, err := client.Call(ctx, "GET", "test", nil)
if err.Error() != "timeout for test" {
t.Error("Expected timeout error, but got", err)
}
}
type SuccessfulHandler struct{}
func (b *SuccessfulHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(successfulResponse))
}
func TestSuccess(t *testing.T) {
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(2*time.Second))
client := New(&SuccessfulHandler{})
defer cancel()
w, err := client.Call(ctx, "GET", "test", nil)
if err != nil {
t.Error("Expected no error, but got", err)
}
report, err := io.ReadAll(w.Body())
if string(report) != successfulResponse {
t.Error("Expected successful report, but got", report)
}
}

@ -61,6 +61,7 @@ type App struct {
logIDPublicAtomic atomic.Pointer[logid.PublicID] logIDPublicAtomic atomic.Pointer[logid.PublicID]
localAPIClient *localapiclient.LocalAPIClient localAPIClient *localapiclient.LocalAPIClient
backend *ipnlocal.LocalBackend
// netStates receives the most recent network state. // netStates receives the most recent network state.
netStates chan BackendState netStates chan BackendState
@ -294,6 +295,7 @@ func (a *App) runBackend(ctx context.Context) error {
return err return err
} }
a.logIDPublicAtomic.Store(&b.logIDPublic) a.logIDPublicAtomic.Store(&b.logIDPublic)
a.backend = b.backend
defer b.CloseTUNs() defer b.CloseTUNs()
h := localapi.NewHandler(b.backend, log.Printf, b.sys.NetMon.Get(), *a.logIDPublicAtomic.Load()) h := localapi.NewHandler(b.backend, log.Printf, b.sys.NetMon.Get(), *a.logIDPublicAtomic.Load())
@ -459,8 +461,9 @@ func (a *App) runBackend(ctx context.Context) error {
state.Prefs.ExitNodeAllowLANAccess = bool(e) state.Prefs.ExitNodeAllowLANAccess = bool(e)
go b.backend.SetPrefs(state.Prefs) go b.backend.SetPrefs(state.Prefs)
case WebAuthEvent: case WebAuthEvent:
log.Printf("KARI WEBAUTHEVENT")
if !signingIn { if !signingIn {
go b.backend.StartLoginInteractive() go a.login(ctx)
signingIn = true signingIn = true
} }
case SetLoginServerEvent: case SetLoginServerEvent:
@ -591,6 +594,18 @@ func (a *App) getBugReportID(ctx context.Context, bugReportChan chan<- string, f
bugReportChan <- string(logBytes) bugReportChan <- string(logBytes)
} }
func (a *App) login(ctx context.Context) {
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(2*time.Second))
defer cancel()
r, err := a.localAPIClient.Call(ctx, "POST", "login-interactive", nil)
defer r.Body().Close()
if err != nil {
log.Printf("login: %s", err)
a.backend.StartLoginInteractive()
}
}
func (a *App) processWaitingFiles(b *ipnlocal.LocalBackend) error { func (a *App) processWaitingFiles(b *ipnlocal.LocalBackend) error {
files, err := b.WaitingFiles() files, err := b.WaitingFiles()
if err != nil { if err != nil {

@ -98,4 +98,4 @@ require (
gvisor.dev/gvisor v0.0.0-20240119233241-c9c1d4f9b186 // indirect gvisor.dev/gvisor v0.0.0-20240119233241-c9c1d4f9b186 // indirect
inet.af/peercred v0.0.0-20210906144145-0893ea02156a // indirect inet.af/peercred v0.0.0-20210906144145-0893ea02156a // indirect
nhooyr.io/websocket v1.8.10 // indirect nhooyr.io/websocket v1.8.10 // indirect
) )
Loading…
Cancel
Save