From f176503448ebbdea131aa11e327d43241d67dd17 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sun, 13 Nov 2022 13:06:53 +0100 Subject: [PATCH] Added WaitForReady() to Tailscale interface When using running `tailscale up` in the AuthKey flow process, the tailscale client immediately enters PollMap after registration - avoiding a race condition. When using the web auth (up -> go to the Control website -> CLI `register`) the client is polling checking if it has been authorized. If we immediately ask for the client IP, as done in CreateHeadscaleEnv() we might have the client in NotReady status. This method provides a way to wait for the client to be ready. Signed-off-by: Juan Font Alonso --- integration/tailscale.go | 1 + integration/tsic/tsic.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/integration/tailscale.go b/integration/tailscale.go index 01004c3f..6b51193a 100644 --- a/integration/tailscale.go +++ b/integration/tailscale.go @@ -17,6 +17,7 @@ type TailscaleClient interface { IPs() ([]netip.Addr, error) FQDN() (string, error) Status() (*ipnstate.Status, error) + WaitForReady() error WaitForPeers(expected int) error Ping(hostnameOrIP string) error } diff --git a/integration/tsic/tsic.go b/integration/tsic/tsic.go index 0f1d9c85..5f11a543 100644 --- a/integration/tsic/tsic.go +++ b/integration/tsic/tsic.go @@ -26,6 +26,7 @@ var ( errTailscalePingFailed = errors.New("ping failed") errTailscaleNotLoggedIn = errors.New("tailscale not logged in") errTailscaleWrongPeerCount = errors.New("wrong peer count") + errTailscaleNotConnected = errors.New("tailscale not connected") ) type TailscaleInContainer struct { @@ -252,6 +253,21 @@ func (t *TailscaleInContainer) FQDN() (string, error) { return status.Self.DNSName, nil } +func (t *TailscaleInContainer) WaitForReady() error { + return t.pool.Retry(func() error { + status, err := t.Status() + if err != nil { + return fmt.Errorf("failed to fetch tailscale status: %w", err) + } + + if status.CurrentTailnet != nil { + return nil + } + + return errTailscaleNotConnected + }) +} + func (t *TailscaleInContainer) WaitForPeers(expected int) error { return t.pool.Retry(func() error { status, err := t.Status()