mirror of
https://github.com/juanfont/headscale.git
synced 2024-11-10 17:12:33 +08:00
Merge pull request #884 from kradalby/integration-v2-ping-by-hostname
This commit is contained in:
commit
ae189c03ac
6 changed files with 157 additions and 40 deletions
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
@ -23,30 +22,14 @@ func TestPingAll(t *testing.T) {
|
|||
t.Errorf("failed to create headscale environment: %s", err)
|
||||
}
|
||||
|
||||
var allIps []netip.Addr
|
||||
var allClients []TailscaleClient
|
||||
|
||||
for namespace, count := range spec {
|
||||
ips, err := scenario.GetIPs(namespace)
|
||||
allClients, err := scenario.ListTailscaleClients()
|
||||
if err != nil {
|
||||
t.Errorf("failed to get tailscale ips: %s", err)
|
||||
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,
|
||||
)
|
||||
}
|
||||
|
||||
clients, err := scenario.GetClients(namespace)
|
||||
allIps, err := scenario.ListTailscaleClientsIPs()
|
||||
if err != nil {
|
||||
t.Errorf("failed to get tailscale clients: %s", err)
|
||||
}
|
||||
|
||||
allIps = append(allIps, ips...)
|
||||
allClients = append(allClients, clients...)
|
||||
t.Errorf("failed to get clients: %s", err)
|
||||
}
|
||||
|
||||
err = scenario.WaitForTailscaleSync()
|
||||
|
@ -58,7 +41,7 @@ func TestPingAll(t *testing.T) {
|
|||
|
||||
for _, client := range allClients {
|
||||
for _, ip := range allIps {
|
||||
err := client.Ping(ip)
|
||||
err := client.Ping(ip.String())
|
||||
if err != nil {
|
||||
t.Errorf("failed to ping %s from %s: %s", ip, client.Hostname(), err)
|
||||
} else {
|
||||
|
@ -69,8 +52,63 @@ func TestPingAll(t *testing.T) {
|
|||
|
||||
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)
|
||||
// }
|
||||
err = scenario.Shutdown()
|
||||
if err != nil {
|
||||
t.Errorf("failed to tear down scenario: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPingAllByHostname(t *testing.T) {
|
||||
IntegrationSkip(t)
|
||||
|
||||
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 _, hostname := range allHostnames {
|
||||
err := client.Ping(hostname)
|
||||
if err != nil {
|
||||
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(allClients))
|
||||
|
||||
err = scenario.Shutdown()
|
||||
if err != nil {
|
||||
t.Errorf("failed to tear down scenario: %s", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"}
|
||||
|
|
|
@ -29,7 +29,7 @@ var (
|
|||
TailscaleVersions = []string{
|
||||
"head",
|
||||
"unstable",
|
||||
"1.32.0",
|
||||
"1.32.1",
|
||||
"1.30.2",
|
||||
"1.28.0",
|
||||
"1.26.2",
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue