Handle errors in integration test setups

Thanks @kev-the-dev

Closes #1460

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
Kristoffer Dalby 2023-08-29 08:33:33 +02:00 committed by Kristoffer Dalby
parent 63caf9a222
commit b4a4d0f760
55 changed files with 829 additions and 1118 deletions

View file

@ -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 (
@ -33,30 +34,33 @@ var (
tailscaleVersions2021 = []string{
"head",
"unstable",
"1.40.0",
"1.38.4",
"1.36.2",
"1.34.2",
"1.32.3",
"1.30.2",
"1.48",
"1.46",
"1.44",
"1.42",
"1.40",
"1.38",
"1.36",
"1.34",
"1.32",
"1.30",
}
tailscaleVersions2019 = []string{
"1.28.0",
"1.26.2",
"1.24.2",
"1.22.2",
"1.20.4",
"1.28",
"1.26",
"1.24",
"1.22",
"1.20",
"1.18",
}
// tailscaleVersionsUnavailable = []string{
// // These versions seem to fail when fetching from apt.
// "1.18.2",
// "1.16.2",
// "1.14.6",
// "1.12.4",
// "1.10.2",
// "1.8.7",
// "1.14.6",
// "1.12.4",
// "1.10.2",
// "1.8.7",
// }.
// TailscaleVersions represents a list of Tailscale versions the suite
@ -79,9 +83,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
@ -148,7 +152,7 @@ func NewScenario() (*Scenario, error) {
// and networks associated with it.
// In addition, it will save the logs of the ControlServer to `/tmp/control` in the
// environment running the tests.
func (s *Scenario) Shutdown() error {
func (s *Scenario) Shutdown() {
s.controlServers.Range(func(_ string, control ControlServer) bool {
err := control.Shutdown()
if err != nil {
@ -166,21 +170,19 @@ func (s *Scenario) Shutdown() error {
log.Printf("removing client %s in user %s", client.Hostname(), userName)
err := client.Shutdown()
if err != nil {
return fmt.Errorf("failed to tear down client: %w", err)
log.Printf("failed to tear down client: %s", err)
}
}
}
if err := s.pool.RemoveNetwork(s.network); err != nil {
return fmt.Errorf("failed to remove network: %w", err)
log.Printf("failed to remove network: %s", err)
}
// TODO(kradalby): This seem redundant to the previous call
// if err := s.network.Close(); err != nil {
// return fmt.Errorf("failed to tear down network: %w", err)
// }
return nil
}
// Users returns the name of all users associated with the Scenario.
@ -213,7 +215,7 @@ func (s *Scenario) Headscale(opts ...hsic.Option) (ControlServer, error) {
return nil, fmt.Errorf("failed to create headscale container: %w", err)
}
err = headscale.WaitForReady()
err = headscale.WaitForRunning()
if err != nil {
return nil, fmt.Errorf("failed reach headscale container: %w", err)
}
@ -286,17 +288,12 @@ 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,
@ -304,20 +301,30 @@ func (s *Scenario) CreateTailscaleNodesInUser(
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 (%s) node: %w",
tsClient.Hostname(),
err,
)
}
err = tsClient.WaitForReady()
err = tsClient.WaitForNeedsLogin()
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 (%s) to need login: %w",
tsClient.Hostname(),
err,
)
}
user.Clients[tsClient.Hostname()] = tsClient
}()
return nil
})
}
if err := user.createWaitGroup.Wait(); err != nil {
return err
}
user.createWaitGroup.Wait()
return nil
}
@ -332,29 +339,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)
err := client.WaitForReady()
if err != nil {
log.Printf("error waiting for client %s to be ready: %s", client.Hostname(), err)
}
c := client
user.joinWaitGroup.Go(func() error {
return c.Login(loginServer, authKey)
})
}
user.joinWaitGroup.Wait()
if err := user.joinWaitGroup.Wait(); err != nil {
return err
}
for _, client := range user.Clients {
err := client.WaitForReady()
err := client.WaitForRunning()
if err != nil {
log.Printf("client %s was not ready: %s", client.Hostname(), err)
return fmt.Errorf("failed to up tailscale node: %w", err)
return fmt.Errorf("%s failed to up tailscale node: %w", client.Hostname(), err)
}
}
@ -381,18 +379,22 @@ func (s *Scenario) CountTailscale() int {
func (s *Scenario) WaitForTailscaleSync() error {
tsCount := s.CountTailscale()
return s.WaitForTailscaleSyncWithPeerCount(tsCount - 1)
}
// WaitForTailscaleSyncWithPeerCount blocks execution until all the TailscaleClient reports
// to have all other TailscaleClients present in their netmap.NetworkMap.
func (s *Scenario) WaitForTailscaleSyncWithPeerCount(peerCount int) 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(peerCount)
})
}
if err := user.syncWaitGroup.Wait(); err != nil {
return err
}
user.syncWaitGroup.Wait()
}
return nil
@ -555,18 +557,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
}