Skip to content

Commit

Permalink
Add sync errorgroup handling in integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kev-the-dev committed May 11, 2023
1 parent 252342a commit 3047fe4
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 89 deletions.
2 changes: 1 addition & 1 deletion integration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Tests are located in files ending with `_test.go` and the framework are located

## Running integration tests locally

The easiest way to run tests locally is to use `[act](INSERT LINK)`, a local GitHub Actions runner:
The easiest way to run tests locally is to use `[act](https://github.com/nektos/act)`, a local GitHub Actions runner:

```
act pull_request -W .github/workflows/test-integration-v2-TestPingAllByIP.yaml
Expand Down
31 changes: 14 additions & 17 deletions integration/auth_oidc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ func TestOIDCExpireNodesBasedOnTokenExpiry(t *testing.T) {
t.Logf("%d successful pings out of %d (before expiry)", success, len(allClients)*len(allIps))

// await all nodes being logged out after OIDC token expiry
scenario.WaitForTailscaleLogout()
if err = scenario.WaitForTailscaleLogout(); err != nil {
t.Errorf("failed to logout tailscale nodes: %s", err)
}

err = scenario.Shutdown()
if err != nil {
Expand Down Expand Up @@ -310,15 +312,11 @@ func (s *AuthOIDCScenario) runTailscaleUp(
log.Printf("running tailscale up for user %s", userStr)
if user, ok := s.users[userStr]; ok {
for _, client := range user.Clients {
user.joinWaitGroup.Add(1)

go func(c TailscaleClient) {
defer user.joinWaitGroup.Done()

// TODO(juanfont): error handle this
c := client
user.joinWaitGroup.Go(func() error {
loginURL, err := c.UpWithLoginURL(loginServer)
if err != nil {
log.Printf("failed to run tailscale up: %s", err)
return fmt.Errorf("failed to run tailscale up: %w", err)
}

loginURL.Host = fmt.Sprintf("%s:8080", headscale.GetIP())
Expand All @@ -335,22 +333,19 @@ func (s *AuthOIDCScenario) runTailscaleUp(
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, loginURL.String(), nil)
resp, err := httpClient.Do(req)
if err != nil {
log.Printf("%s failed to get login url %s: %s", c.Hostname(), loginURL, err)

return
return fmt.Errorf("%s failed to get login url %s: %w", c.Hostname(), loginURL, err)
}

defer resp.Body.Close()

_, err = io.ReadAll(resp.Body)
if err != nil {
log.Printf("%s failed to read response body: %s", c.Hostname(), err)

return
return fmt.Errorf("%s failed to read response body: %w", c.Hostname(), err)
}

log.Printf("Finished request for %s to join tailnet", c.Hostname())
}(client)

return nil
})

err = client.WaitForReady()
if err != nil {
Expand All @@ -360,7 +355,9 @@ func (s *AuthOIDCScenario) runTailscaleUp(
log.Printf("client %s is ready", client.Hostname())
}

user.joinWaitGroup.Wait()
if err := user.joinWaitGroup.Wait(); err != nil {
return fmt.Errorf("failed to bring up tailscale nodes: %w", err)
}

for _, client := range user.Clients {
err := client.WaitForReady()
Expand Down
24 changes: 13 additions & 11 deletions integration/auth_web_flow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
}
}

scenario.WaitForTailscaleLogout()
if err = scenario.WaitForTailscaleLogout(); err != nil {
t.Errorf("failed to logout tailscale nodes: %s", err)
}

t.Logf("all clients logged out")

Expand Down Expand Up @@ -250,29 +252,29 @@ func (s *AuthWebFlowScenario) runTailscaleUp(
log.Printf("running tailscale up for user %s", userStr)
if user, ok := s.users[userStr]; ok {
for _, client := range user.Clients {
user.joinWaitGroup.Add(1)

go func(c TailscaleClient) {
defer user.joinWaitGroup.Done()

// TODO(juanfont): error handle this
c := client
user.joinWaitGroup.Go(func() error {
loginURL, err := c.UpWithLoginURL(loginServer)
if err != nil {
log.Printf("failed to run tailscale up: %s", err)
return fmt.Errorf("failed to run tailscale up: %w", err)
}

err = s.runHeadscaleRegister(userStr, loginURL)
if err != nil {
log.Printf("failed to register client: %s", err)
return fmt.Errorf("failed to register client: %w", err)
}
}(client)

return nil
})

err := client.WaitForReady()
if err != nil {
log.Printf("error waiting for client %s to be ready: %s", client.Hostname(), err)
}
}
user.joinWaitGroup.Wait()
if err := user.joinWaitGroup.Wait(); err != nil {
return fmt.Errorf("failed to up tailscale nodes: %w", err)
}

for _, client := range user.Clients {
err := client.WaitForReady()
Expand Down
21 changes: 7 additions & 14 deletions integration/embedded_derp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package integration

import (
"fmt"
"log"
"net/url"
"testing"

Expand Down Expand Up @@ -186,39 +185,33 @@ func (s *EmbeddedDERPServerScenario) CreateTailscaleIsolatedNodesInUser(

cert := hsServer.GetCert()

user.createWaitGroup.Add(1)

opts = append(opts,
tsic.WithHeadscaleTLS(cert),
)

go func() {
defer user.createWaitGroup.Done()

// TODO(kradalby): error handle this
user.createWaitGroup.Go(func() error {
tsClient, err := tsic.New(
s.pool,
version,
network,
opts...,
)
if err != nil {
// return fmt.Errorf("failed to add tailscale node: %w", err)
log.Printf("failed to create tailscale node: %s", err)
return fmt.Errorf("failed to create tailscale node: %w", err)
}

err = tsClient.WaitForReady()
if err != nil {
// return fmt.Errorf("failed to add tailscale node: %w", err)
log.Printf("failed to wait for tailscaled: %s", err)
return fmt.Errorf("failed to wait for tailscaled: %w", err)
}

user.Clients[tsClient.Hostname()] = tsClient
}()

return nil
})
}
user.createWaitGroup.Wait()

return nil
return user.createWaitGroup.Wait()
}

return fmt.Errorf("failed to add tailscale node: %w", errNoUserAvailable)
Expand Down
8 changes: 6 additions & 2 deletions integration/general_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ func TestAuthKeyLogoutAndRelogin(t *testing.T) {
}
}

scenario.WaitForTailscaleLogout()
if err = scenario.WaitForTailscaleLogout(); err != nil {
t.Errorf("failed to logout tailscale nodes: %s", err)
}

t.Logf("all clients logged out")

Expand Down Expand Up @@ -261,7 +263,9 @@ func TestEphemeral(t *testing.T) {
}
}

scenario.WaitForTailscaleLogout()
if err = scenario.WaitForTailscaleLogout(); err != nil {
t.Errorf("failed to logout tailscale nodes: %s", err)
}

t.Logf("all clients logged out")

Expand Down
79 changes: 35 additions & 44 deletions integration/scenario.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/juanfont/headscale/integration/tsic"
"github.com/ory/dockertest/v3"
"github.com/puzpuzpuz/xsync/v2"
"golang.org/x/sync/errgroup"
)

const (
Expand Down Expand Up @@ -79,9 +80,9 @@ var (
type User struct {
Clients map[string]TailscaleClient

createWaitGroup sync.WaitGroup
joinWaitGroup sync.WaitGroup
syncWaitGroup sync.WaitGroup
createWaitGroup errgroup.Group
joinWaitGroup errgroup.Group
syncWaitGroup errgroup.Group
}

// Scenario is a representation of an environment with one ControlServer and
Expand Down Expand Up @@ -286,40 +287,34 @@ func (s *Scenario) CreateTailscaleNodesInUser(
cert := headscale.GetCert()
hostname := headscale.GetHostname()

user.createWaitGroup.Add(1)

opts = append(opts,
tsic.WithHeadscaleTLS(cert),
tsic.WithHeadscaleName(hostname),
)

go func() {
defer user.createWaitGroup.Done()

// TODO(kradalby): error handle this
user.createWaitGroup.Go(func() error {
tsClient, err := tsic.New(
s.pool,
version,
s.network,
opts...,
)
if err != nil {
// return fmt.Errorf("failed to add tailscale node: %w", err)
log.Printf("failed to create tailscale node: %s", err)
return fmt.Errorf("failed to add tailscale node: %w", err)
}

err = tsClient.WaitForReady()
if err != nil {
// return fmt.Errorf("failed to add tailscale node: %w", err)
log.Printf("failed to wait for tailscaled: %s", err)
return fmt.Errorf("failed to add tailscale node: %w", err)
}

user.Clients[tsClient.Hostname()] = tsClient
}()

return nil
})
}
user.createWaitGroup.Wait()

return nil
return user.createWaitGroup.Wait()
}

return fmt.Errorf("failed to add tailscale node: %w", errNoUserAvailable)
Expand All @@ -332,22 +327,20 @@ func (s *Scenario) RunTailscaleUp(
) error {
if user, ok := s.users[userStr]; ok {
for _, client := range user.Clients {
user.joinWaitGroup.Add(1)

go func(c TailscaleClient) {
defer user.joinWaitGroup.Done()

// TODO(kradalby): error handle this
_ = c.Up(loginServer, authKey)
}(client)
c := client
user.joinWaitGroup.Go(func() error {
return c.Up(loginServer, authKey)
})

err := client.WaitForReady()
if err != nil {
log.Printf("error waiting for client %s to be ready: %s", client.Hostname(), err)
}
}

user.joinWaitGroup.Wait()
if err := user.joinWaitGroup.Wait(); err != nil {
return fmt.Errorf("failed to up tailscale nodes: %w", err)
}

for _, client := range user.Clients {
err := client.WaitForReady()
Expand Down Expand Up @@ -383,16 +376,14 @@ func (s *Scenario) WaitForTailscaleSync() error {

for _, user := range s.users {
for _, client := range user.Clients {
user.syncWaitGroup.Add(1)

go func(c TailscaleClient) {
defer user.syncWaitGroup.Done()

// TODO(kradalby): error handle this
_ = c.WaitForPeers(tsCount)
}(client)
c := client
user.syncWaitGroup.Go(func() error {
return c.WaitForPeers(tsCount)
})
}
if err := user.syncWaitGroup.Wait(); err != nil {
return err
}
user.syncWaitGroup.Wait()
}

return nil
Expand Down Expand Up @@ -555,18 +546,18 @@ func (s *Scenario) ListTailscaleClientsFQDNs(users ...string) ([]string, error)

// WaitForTailscaleLogout blocks execution until all TailscaleClients have
// logged out of the ControlServer.
func (s *Scenario) WaitForTailscaleLogout() {
func (s *Scenario) WaitForTailscaleLogout() error {
for _, user := range s.users {
for _, client := range user.Clients {
user.syncWaitGroup.Add(1)

go func(c TailscaleClient) {
defer user.syncWaitGroup.Done()

// TODO(kradalby): error handle this
_ = c.WaitForLogout()
}(client)
c := client
user.syncWaitGroup.Go(func() error {
return c.WaitForLogout()
})
}
if err := user.syncWaitGroup.Wait(); err != nil {
return err
}
user.syncWaitGroup.Wait()
}

return nil
}

0 comments on commit 3047fe4

Please sign in to comment.