Skip to content

Commit

Permalink
Merge pull request #884 from kradalby/integration-v2-ping-by-hostname
Browse files Browse the repository at this point in the history
  • Loading branch information
kradalby authored Oct 23, 2022
2 parents ecce82d + 7155b22 commit ae189c0
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 39 deletions.
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

0 comments on commit ae189c0

Please sign in to comment.