Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration test v2, hostname ping test #884

Merged
merged 8 commits into from
Oct 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions integration/control.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package integration

import v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
import (
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
)

type ControlServer interface {
Shutdown() error
Expand All @@ -9,5 +11,5 @@ type ControlServer interface {
WaitForReady() error
CreateNamespace(namespace string) error
CreateAuthKey(namespace string) (*v1.PreAuthKey, error)
ListNodes(namespace string) ([]*v1.Machine, error)
ListMachinesInNamespace(namespace string) ([]*v1.Machine, error)
}
96 changes: 67 additions & 29 deletions integration/general_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package integration

import (
"net/netip"
"testing"
)

func TestPingAll(t *testing.T) {
func TestPingAllByIP(t *testing.T) {
IntegrationSkip(t)

scenario, err := NewScenario()
Expand All @@ -23,54 +22,93 @@ func TestPingAll(t *testing.T) {
t.Errorf("failed to create headscale environment: %s", err)
}

var allIps []netip.Addr
var allClients []TailscaleClient
allClients, err := scenario.ListTailscaleClients()
if err != nil {
t.Errorf("failed to get clients: %s", err)
}

for namespace, count := range spec {
ips, err := scenario.GetIPs(namespace)
if err != nil {
t.Errorf("failed to get tailscale ips: %s", err)
}
allIps, err := scenario.ListTailscaleClientsIPs()
if err != nil {
t.Errorf("failed to get clients: %s", err)
}

if len(ips) != count*2 {
t.Errorf(
"got the wrong amount of tailscale ips, %d != %d",
len(ips),
count*2,
)
}
err = scenario.WaitForTailscaleSync()
if err != nil {
t.Errorf("failed wait for tailscale clients to be in sync: %s", err)
}

clients, err := scenario.GetClients(namespace)
if err != nil {
t.Errorf("failed to get tailscale clients: %s", err)
success := 0

for _, client := range allClients {
for _, ip := range allIps {
err := client.Ping(ip.String())
if err != nil {
t.Errorf("failed to ping %s from %s: %s", ip, client.Hostname(), err)
} else {
success++
}
}
}

t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))

err = scenario.Shutdown()
if err != nil {
t.Errorf("failed to tear down scenario: %s", err)
}
}

func TestPingAllByHostname(t *testing.T) {
IntegrationSkip(t)

allIps = append(allIps, ips...)
allClients = append(allClients, clients...)
scenario, err := NewScenario()
if err != nil {
t.Errorf("failed to create scenario: %s", err)
}

spec := map[string]int{
// Omit 1.16.2 (-1) because it does not have the FQDN field
"namespace3": len(TailscaleVersions) - 1,
"namespace4": len(TailscaleVersions) - 1,
}

err = scenario.CreateHeadscaleEnv(spec)
if err != nil {
t.Errorf("failed to create headscale environment: %s", err)
}

allClients, err := scenario.ListTailscaleClients()
if err != nil {
t.Errorf("failed to get clients: %s", err)
}

err = scenario.WaitForTailscaleSync()
if err != nil {
t.Errorf("failed wait for tailscale clients to be in sync: %s", err)
}

allHostnames, err := scenario.ListTailscaleClientsFQDNs()
if err != nil {
t.Errorf("failed to get FQDNs: %s", err)
}

success := 0

for _, client := range allClients {
for _, ip := range allIps {
err := client.Ping(ip)
for _, hostname := range allHostnames {
err := client.Ping(hostname)
if err != nil {
t.Errorf("failed to ping %s from %s: %s", ip, client.Hostname(), err)
t.Errorf("failed to ping %s from %s: %s", hostname, client.Hostname(), err)
} else {
success++
}
}
}

t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allClients))

// err = scenario.Shutdown()
// if err != nil {
// t.Errorf("failed to tear down scenario: %s", err)
// }
err = scenario.Shutdown()
if err != nil {
t.Errorf("failed to tear down scenario: %s", err)
}
}
2 changes: 1 addition & 1 deletion integration/hsic/hsic.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func (t *HeadscaleInContainer) CreateAuthKey(
return &preAuthKey, nil
}

func (t *HeadscaleInContainer) ListNodes(
func (t *HeadscaleInContainer) ListMachinesInNamespace(
namespace string,
) ([]*v1.Machine, error) {
command := []string{"headscale", "--namespace", namespace, "nodes", "list", "--output", "json"}
Expand Down
69 changes: 68 additions & 1 deletion integration/scenario.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ var (
TailscaleVersions = []string{
"head",
"unstable",
"1.32.0",
"1.32.1",
"1.30.2",
"1.28.0",
"1.26.2",
Expand Down Expand Up @@ -138,6 +138,15 @@ func (s *Scenario) Shutdown() error {
return nil
}

func (s *Scenario) Namespaces() []string {
namespaces := make([]string, 0)
for namespace := range s.namespaces {
namespaces = append(namespaces, namespace)
}

return namespaces
}

/// Headscale related stuff
// Note: These functions assume that there is a _single_ headscale instance for now

Expand Down Expand Up @@ -345,3 +354,61 @@ func (s *Scenario) GetClients(namespace string) ([]TailscaleClient, error) {

return clients, fmt.Errorf("failed to get clients: %w", errNoNamespaceAvailable)
}

func (s *Scenario) ListTailscaleClients(namespaces ...string) ([]TailscaleClient, error) {
var allClients []TailscaleClient

if len(namespaces) == 0 {
namespaces = s.Namespaces()
}

for _, namespace := range namespaces {
clients, err := s.GetClients(namespace)
if err != nil {
return nil, err
}

allClients = append(allClients, clients...)
}

return allClients, nil
}

func (s *Scenario) ListTailscaleClientsIPs(namespaces ...string) ([]netip.Addr, error) {
var allIps []netip.Addr

if len(namespaces) == 0 {
namespaces = s.Namespaces()
}

for _, namespace := range namespaces {
ips, err := s.GetIPs(namespace)
if err != nil {
return nil, err
}

allIps = append(allIps, ips...)
}

return allIps, nil
}

func (s *Scenario) ListTailscaleClientsFQDNs(namespaces ...string) ([]string, error) {
allFQDNs := make([]string, 0)

clients, err := s.ListTailscaleClients(namespaces...)
if err != nil {
return nil, err
}

for _, client := range clients {
fqdn, err := client.FQDN()
if err != nil {
return nil, err
}

allFQDNs = append(allFQDNs, fqdn)
}

return allFQDNs, nil
}
3 changes: 2 additions & 1 deletion integration/tailscale.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ type TailscaleClient interface {
Version() string
Up(loginServer, authKey string) error
IPs() ([]netip.Addr, error)
FQDN() (string, error)
Status() (*ipnstate.Status, error)
WaitForPeers(expected int) error
Ping(ip netip.Addr) error
Ping(hostnameOrIP string) error
}
19 changes: 14 additions & 5 deletions integration/tsic/tsic.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func New(
return nil, err
}

hostname := fmt.Sprintf("ts-%s-%s", version, hash)
hostname := fmt.Sprintf("ts-%s-%s", strings.ReplaceAll(version, ".", "-"), hash)

// TODO(kradalby): figure out why we need to "refresh" the network here.
// network, err = dockertestutil.GetFirstOrCreateNetwork(pool, network.Network.Name)
Expand Down Expand Up @@ -204,6 +204,15 @@ func (t *TailscaleInContainer) Status() (*ipnstate.Status, error) {
return &status, err
}

func (t *TailscaleInContainer) FQDN() (string, error) {
status, err := t.Status()
if err != nil {
return "", fmt.Errorf("failed to get FQDN: %w", err)
}

return status.Self.DNSName, nil
}

func (t *TailscaleInContainer) WaitForPeers(expected int) error {
return t.pool.Retry(func() error {
status, err := t.Status()
Expand All @@ -220,14 +229,14 @@ func (t *TailscaleInContainer) WaitForPeers(expected int) error {
}

// TODO(kradalby): Make multiping, go routine magic.
func (t *TailscaleInContainer) Ping(ip netip.Addr) error {
func (t *TailscaleInContainer) Ping(hostnameOrIP string) error {
return t.pool.Retry(func() error {
command := []string{
"tailscale", "ping",
"--timeout=1s",
"--c=10",
"--until-direct=true",
ip.String(),
hostnameOrIP,
}

result, _, err := dockertestutil.ExecuteCommand(
Expand All @@ -238,8 +247,8 @@ func (t *TailscaleInContainer) Ping(ip netip.Addr) error {
if err != nil {
log.Printf(
"failed to run ping command from %s to %s, err: %s",
t.hostname,
ip.String(),
t.Hostname(),
hostnameOrIP,
err,
)

Expand Down