mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-10-31 16:11:03 +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 | ||||
| 
 | ||||
| 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 | ||||
| 	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) | ||||
| 		} | ||||
| 
 | ||||
| 		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) | ||||
| 		if err != nil { | ||||
| 			t.Errorf("failed to get tailscale clients: %s", err) | ||||
| 		} | ||||
| 
 | ||||
| 		allIps = append(allIps, ips...) | ||||
| 		allClients = append(allClients, clients...) | ||||
| 	allIps, err := scenario.ListTailscaleClientsIPs() | ||||
| 	if err != nil { | ||||
| 		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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user