mirror of
https://github.com/juanfont/headscale.git
synced 2025-01-08 00:11:42 +01:00
Merge pull request #884 from kradalby/integration-v2-ping-by-hostname
This commit is contained in:
commit
ae189c03ac
@ -1,6 +1,8 @@
|
|||||||
package integration
|
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 {
|
type ControlServer interface {
|
||||||
Shutdown() error
|
Shutdown() error
|
||||||
@ -9,5 +11,5 @@ type ControlServer interface {
|
|||||||
WaitForReady() error
|
WaitForReady() error
|
||||||
CreateNamespace(namespace string) error
|
CreateNamespace(namespace string) error
|
||||||
CreateAuthKey(namespace string) (*v1.PreAuthKey, 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
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/netip"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPingAll(t *testing.T) {
|
func TestPingAllByIP(t *testing.T) {
|
||||||
IntegrationSkip(t)
|
IntegrationSkip(t)
|
||||||
|
|
||||||
scenario, err := NewScenario()
|
scenario, err := NewScenario()
|
||||||
@ -23,30 +22,14 @@ func TestPingAll(t *testing.T) {
|
|||||||
t.Errorf("failed to create headscale environment: %s", err)
|
t.Errorf("failed to create headscale environment: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var allIps []netip.Addr
|
allClients, err := scenario.ListTailscaleClients()
|
||||||
var allClients []TailscaleClient
|
|
||||||
|
|
||||||
for namespace, count := range spec {
|
|
||||||
ips, err := scenario.GetIPs(namespace)
|
|
||||||
if err != nil {
|
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 {
|
allIps, err := scenario.ListTailscaleClientsIPs()
|
||||||
t.Errorf(
|
|
||||||
"got the wrong amount of tailscale ips, %d != %d",
|
|
||||||
len(ips),
|
|
||||||
count*2,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
clients, err := scenario.GetClients(namespace)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to get tailscale clients: %s", err)
|
t.Errorf("failed to get clients: %s", err)
|
||||||
}
|
|
||||||
|
|
||||||
allIps = append(allIps, ips...)
|
|
||||||
allClients = append(allClients, clients...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = scenario.WaitForTailscaleSync()
|
err = scenario.WaitForTailscaleSync()
|
||||||
@ -58,7 +41,7 @@ func TestPingAll(t *testing.T) {
|
|||||||
|
|
||||||
for _, client := range allClients {
|
for _, client := range allClients {
|
||||||
for _, ip := range allIps {
|
for _, ip := range allIps {
|
||||||
err := client.Ping(ip)
|
err := client.Ping(ip.String())
|
||||||
if err != nil {
|
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", ip, client.Hostname(), err)
|
||||||
} else {
|
} else {
|
||||||
@ -69,8 +52,63 @@ func TestPingAll(t *testing.T) {
|
|||||||
|
|
||||||
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(allIps))
|
||||||
|
|
||||||
// err = scenario.Shutdown()
|
err = scenario.Shutdown()
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// t.Errorf("failed to tear down scenario: %s", err)
|
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
|
return &preAuthKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *HeadscaleInContainer) ListNodes(
|
func (t *HeadscaleInContainer) ListMachinesInNamespace(
|
||||||
namespace string,
|
namespace string,
|
||||||
) ([]*v1.Machine, error) {
|
) ([]*v1.Machine, error) {
|
||||||
command := []string{"headscale", "--namespace", namespace, "nodes", "list", "--output", "json"}
|
command := []string{"headscale", "--namespace", namespace, "nodes", "list", "--output", "json"}
|
||||||
|
@ -29,7 +29,7 @@ var (
|
|||||||
TailscaleVersions = []string{
|
TailscaleVersions = []string{
|
||||||
"head",
|
"head",
|
||||||
"unstable",
|
"unstable",
|
||||||
"1.32.0",
|
"1.32.1",
|
||||||
"1.30.2",
|
"1.30.2",
|
||||||
"1.28.0",
|
"1.28.0",
|
||||||
"1.26.2",
|
"1.26.2",
|
||||||
@ -138,6 +138,15 @@ func (s *Scenario) Shutdown() error {
|
|||||||
return nil
|
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
|
/// Headscale related stuff
|
||||||
// Note: These functions assume that there is a _single_ headscale instance for now
|
// 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)
|
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
|
Version() string
|
||||||
Up(loginServer, authKey string) error
|
Up(loginServer, authKey string) error
|
||||||
IPs() ([]netip.Addr, error)
|
IPs() ([]netip.Addr, error)
|
||||||
|
FQDN() (string, error)
|
||||||
Status() (*ipnstate.Status, error)
|
Status() (*ipnstate.Status, error)
|
||||||
WaitForPeers(expected int) error
|
WaitForPeers(expected int) error
|
||||||
Ping(ip netip.Addr) error
|
Ping(hostnameOrIP string) error
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ func New(
|
|||||||
return nil, err
|
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.
|
// TODO(kradalby): figure out why we need to "refresh" the network here.
|
||||||
// network, err = dockertestutil.GetFirstOrCreateNetwork(pool, network.Network.Name)
|
// network, err = dockertestutil.GetFirstOrCreateNetwork(pool, network.Network.Name)
|
||||||
@ -204,6 +204,15 @@ func (t *TailscaleInContainer) Status() (*ipnstate.Status, error) {
|
|||||||
return &status, err
|
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 {
|
func (t *TailscaleInContainer) WaitForPeers(expected int) error {
|
||||||
return t.pool.Retry(func() error {
|
return t.pool.Retry(func() error {
|
||||||
status, err := t.Status()
|
status, err := t.Status()
|
||||||
@ -220,14 +229,14 @@ func (t *TailscaleInContainer) WaitForPeers(expected int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(kradalby): Make multiping, go routine magic.
|
// 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 {
|
return t.pool.Retry(func() error {
|
||||||
command := []string{
|
command := []string{
|
||||||
"tailscale", "ping",
|
"tailscale", "ping",
|
||||||
"--timeout=1s",
|
"--timeout=1s",
|
||||||
"--c=10",
|
"--c=10",
|
||||||
"--until-direct=true",
|
"--until-direct=true",
|
||||||
ip.String(),
|
hostnameOrIP,
|
||||||
}
|
}
|
||||||
|
|
||||||
result, _, err := dockertestutil.ExecuteCommand(
|
result, _, err := dockertestutil.ExecuteCommand(
|
||||||
@ -238,8 +247,8 @@ func (t *TailscaleInContainer) Ping(ip netip.Addr) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf(
|
log.Printf(
|
||||||
"failed to run ping command from %s to %s, err: %s",
|
"failed to run ping command from %s to %s, err: %s",
|
||||||
t.hostname,
|
t.Hostname(),
|
||||||
ip.String(),
|
hostnameOrIP,
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user