Add tailscale versions, waiters and helpers for scenario
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
3951f39868
commit
0db608a7b7
|
@ -7,6 +7,7 @@ import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/juanfont/headscale"
|
"github.com/juanfont/headscale"
|
||||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||||
|
@ -20,12 +21,32 @@ const scenarioHashLength = 6
|
||||||
|
|
||||||
var errNoHeadscaleAvailable = errors.New("no headscale available")
|
var errNoHeadscaleAvailable = errors.New("no headscale available")
|
||||||
var errNoNamespaceAvailable = errors.New("no namespace available")
|
var errNoNamespaceAvailable = errors.New("no namespace available")
|
||||||
|
var TailscaleVersions = []string{
|
||||||
|
"head",
|
||||||
|
"unstable",
|
||||||
|
"1.32.0",
|
||||||
|
"1.30.2",
|
||||||
|
"1.28.0",
|
||||||
|
"1.26.2",
|
||||||
|
"1.24.2",
|
||||||
|
"1.22.2",
|
||||||
|
"1.20.4",
|
||||||
|
"1.18.2",
|
||||||
|
"1.16.2",
|
||||||
|
|
||||||
|
// These versions seem to fail when fetching from apt.
|
||||||
|
// "1.14.6",
|
||||||
|
// "1.12.4",
|
||||||
|
// "1.10.2",
|
||||||
|
// "1.8.7",
|
||||||
|
}
|
||||||
|
|
||||||
type Namespace struct {
|
type Namespace struct {
|
||||||
Clients map[string]*tsic.TailscaleInContainer
|
Clients map[string]*tsic.TailscaleInContainer
|
||||||
|
|
||||||
createWaitGroup sync.WaitGroup
|
createWaitGroup sync.WaitGroup
|
||||||
joinWaitGroup sync.WaitGroup
|
joinWaitGroup sync.WaitGroup
|
||||||
|
syncWaitGroup sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(kradalby): make control server configurable, test test correctness with
|
// TODO(kradalby): make control server configurable, test test correctness with
|
||||||
|
@ -52,6 +73,8 @@ func NewScenario() (*Scenario, error) {
|
||||||
return nil, fmt.Errorf("could not connect to docker: %w", err)
|
return nil, fmt.Errorf("could not connect to docker: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pool.MaxWait = 60 * time.Second
|
||||||
|
|
||||||
networkName := fmt.Sprintf("hs-%s", hash)
|
networkName := fmt.Sprintf("hs-%s", hash)
|
||||||
if overrideNetworkName := os.Getenv("HEADSCALE_TEST_NETWORK_NAME"); overrideNetworkName != "" {
|
if overrideNetworkName := os.Getenv("HEADSCALE_TEST_NETWORK_NAME"); overrideNetworkName != "" {
|
||||||
networkName = overrideNetworkName
|
networkName = overrideNetworkName
|
||||||
|
@ -162,11 +185,16 @@ func (s *Scenario) CreateNamespace(namespace string) error {
|
||||||
|
|
||||||
func (s *Scenario) CreateTailscaleNodesInNamespace(
|
func (s *Scenario) CreateTailscaleNodesInNamespace(
|
||||||
namespace string,
|
namespace string,
|
||||||
version string,
|
requestedVersion string,
|
||||||
count int,
|
count int,
|
||||||
) error {
|
) error {
|
||||||
if ns, ok := s.namespaces[namespace]; ok {
|
if ns, ok := s.namespaces[namespace]; ok {
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
|
version := requestedVersion
|
||||||
|
if requestedVersion == "all" {
|
||||||
|
version = TailscaleVersions[i%len(TailscaleVersions)]
|
||||||
|
}
|
||||||
|
|
||||||
ns.createWaitGroup.Add(1)
|
ns.createWaitGroup.Add(1)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -197,12 +225,12 @@ func (s *Scenario) RunTailscaleUp(
|
||||||
for _, client := range ns.Clients {
|
for _, client := range ns.Clients {
|
||||||
ns.joinWaitGroup.Add(1)
|
ns.joinWaitGroup.Add(1)
|
||||||
|
|
||||||
go func() {
|
go func(c *tsic.TailscaleInContainer) {
|
||||||
defer ns.joinWaitGroup.Done()
|
defer ns.joinWaitGroup.Done()
|
||||||
|
|
||||||
// TODO(kradalby): error handle this
|
// TODO(kradalby): error handle this
|
||||||
_ = client.Up(loginServer, authKey)
|
_ = c.Up(loginServer, authKey)
|
||||||
}()
|
}(client)
|
||||||
}
|
}
|
||||||
ns.joinWaitGroup.Wait()
|
ns.joinWaitGroup.Wait()
|
||||||
|
|
||||||
|
@ -212,6 +240,75 @@ func (s *Scenario) RunTailscaleUp(
|
||||||
return fmt.Errorf("failed to up tailscale node: %w", errNoNamespaceAvailable)
|
return fmt.Errorf("failed to up tailscale node: %w", errNoNamespaceAvailable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Scenario) CountTailscale() int {
|
||||||
|
count := 0
|
||||||
|
|
||||||
|
for _, ns := range s.namespaces {
|
||||||
|
count += len(ns.Clients)
|
||||||
|
}
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Scenario) WaitForTailscaleSync() error {
|
||||||
|
tsCount := s.CountTailscale()
|
||||||
|
|
||||||
|
for _, ns := range s.namespaces {
|
||||||
|
for _, client := range ns.Clients {
|
||||||
|
ns.syncWaitGroup.Add(1)
|
||||||
|
|
||||||
|
go func(c *tsic.TailscaleInContainer) {
|
||||||
|
defer ns.syncWaitGroup.Done()
|
||||||
|
|
||||||
|
// TODO(kradalby): error handle this
|
||||||
|
_ = c.WaitForPeers(tsCount)
|
||||||
|
}(client)
|
||||||
|
}
|
||||||
|
ns.syncWaitGroup.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateHeadscaleEnv is a conventient method returning a set up Headcale
|
||||||
|
// test environment with nodes of all versions, joined to the server with X
|
||||||
|
// namespaces
|
||||||
|
func (s *Scenario) CreateHeadscaleEnv(namespaces map[string]int) error {
|
||||||
|
err := s.StartHeadscale()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.Headscale().WaitForReady()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for namespaceName, clientCount := range namespaces {
|
||||||
|
err = s.CreateNamespace(namespaceName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.CreateTailscaleNodesInNamespace(namespaceName, "all", clientCount)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := s.CreatePreAuthKey(namespaceName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.RunTailscaleUp(namespaceName, s.Headscale().GetEndpoint(), key.GetKey())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Scenario) GetIPs(namespace string) ([]netip.Addr, error) {
|
func (s *Scenario) GetIPs(namespace string) ([]netip.Addr, error) {
|
||||||
var ips []netip.Addr
|
var ips []netip.Addr
|
||||||
if ns, ok := s.namespaces[namespace]; ok {
|
if ns, ok := s.namespaces[namespace]; ok {
|
||||||
|
@ -228,3 +325,16 @@ func (s *Scenario) GetIPs(namespace string) ([]netip.Addr, error) {
|
||||||
|
|
||||||
return ips, fmt.Errorf("failed to get ips: %w", errNoNamespaceAvailable)
|
return ips, fmt.Errorf("failed to get ips: %w", errNoNamespaceAvailable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Scenario) GetClients(namespace string) ([]*tsic.TailscaleInContainer, error) {
|
||||||
|
var clients []*tsic.TailscaleInContainer
|
||||||
|
if ns, ok := s.namespaces[namespace]; ok {
|
||||||
|
for _, client := range ns.Clients {
|
||||||
|
clients = append(clients, client)
|
||||||
|
}
|
||||||
|
|
||||||
|
return clients, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return clients, fmt.Errorf("failed to get clients: %w", errNoNamespaceAvailable)
|
||||||
|
}
|
||||||
|
|
|
@ -74,12 +74,9 @@ func TestHeadscale(t *testing.T) {
|
||||||
func TestCreateTailscale(t *testing.T) {
|
func TestCreateTailscale(t *testing.T) {
|
||||||
IntegrationSkip(t)
|
IntegrationSkip(t)
|
||||||
|
|
||||||
var scenario *Scenario
|
|
||||||
var err error
|
|
||||||
|
|
||||||
namespace := "only-create-containers"
|
namespace := "only-create-containers"
|
||||||
|
|
||||||
scenario, err = NewScenario()
|
scenario, err := NewScenario()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to create scenario: %s", err)
|
t.Errorf("failed to create scenario: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -89,7 +86,7 @@ func TestCreateTailscale(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("create-tailscale", func(t *testing.T) {
|
t.Run("create-tailscale", func(t *testing.T) {
|
||||||
err := scenario.CreateTailscaleNodesInNamespace(namespace, "1.32.0", 3)
|
err := scenario.CreateTailscaleNodesInNamespace(namespace, "all", 3)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to add tailscale nodes: %s", err)
|
t.Errorf("failed to add tailscale nodes: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -97,6 +94,8 @@ func TestCreateTailscale(t *testing.T) {
|
||||||
if clients := len(scenario.namespaces[namespace].Clients); clients != 3 {
|
if clients := len(scenario.namespaces[namespace].Clients); clients != 3 {
|
||||||
t.Errorf("wrong number of tailscale clients: %d != %d", clients, 3)
|
t.Errorf("wrong number of tailscale clients: %d != %d", clients, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(kradalby): Test "all" version logic
|
||||||
})
|
})
|
||||||
|
|
||||||
err = scenario.Shutdown()
|
err = scenario.Shutdown()
|
||||||
|
|
Loading…
Reference in New Issue