1
0
mirror of https://github.com/juanfont/headscale.git synced 2026-02-07 20:04:00 +01:00

fix: ensure Docker API version compatibility and improve app connector tests

- Set DOCKER_API_VERSION to 1.44 if not already defined to maintain compatibility with newer Docker daemons.
- Update app connector tests to use netip.Prefix for route definitions and improve validation checks for netmap and capability maps.
- Refactor assertions in tests for better clarity and consistency.

This enhances the reliability of integration tests and ensures proper interaction with Docker APIs.
This commit is contained in:
matanbaruch 2026-02-11 06:48:37 +02:00
parent 542f1fabb8
commit fd840fabb1
2 changed files with 37 additions and 36 deletions

View File

@ -256,6 +256,18 @@ func createGoTestContainer(ctx context.Context, cli *client.Client, config *RunC
// Set GOCACHE to a known location (used by both bind mount and volume cases)
env = append(env, "GOCACHE=/cache/go-build")
// Ensure Docker API version compatibility with newer Docker daemons (29.x+).
// dockertest's go-dockerclient uses old API versions (e.g., 1.25) in URLs which
// newer Docker daemons reject (minimum 1.44). Setting DOCKER_API_VERSION makes
// the client use a compatible version, and DOCKER_MACHINE_NAME triggers the
// NewClientFromEnv() code path in dockertest which respects DOCKER_API_VERSION.
if os.Getenv("DOCKER_API_VERSION") == "" {
env = append(env, "DOCKER_API_VERSION=1.44")
} else {
env = append(env, "DOCKER_API_VERSION="+os.Getenv("DOCKER_API_VERSION"))
}
env = append(env, "DOCKER_MACHINE_NAME=integration")
containerConfig := &container.Config{
Image: "golang:" + config.GoVersion,
Cmd: goTestCmd,

View File

@ -2,6 +2,7 @@ package integration
import (
"encoding/json"
"net/netip"
"testing"
"time"
@ -43,7 +44,7 @@ func TestAppConnectorBasic(t *testing.T) {
Name: "VPN Apps",
Connectors: []string{"tag:connector"},
Domains: []string{"vpn.example.com"},
Routes: []string{"10.0.0.0/8"},
Routes: []netip.Prefix{netip.MustParsePrefix("10.0.0.0/8")},
},
},
}
@ -111,50 +112,42 @@ func TestAppConnectorBasic(t *testing.T) {
// Wait for the app connector capability to be propagated
t.Log("Waiting for app connector capability to be propagated")
assert.EventuallyWithT(t, func(c *assert.CollectT) {
netmap, err := connectorNode.Netmap()
nm, err := connectorNode.Netmap()
assert.NoError(c, err)
if netmap == nil || netmap.SelfNode == nil {
assert.Fail(c, "Netmap or SelfNode is nil")
if nm == nil || !nm.SelfNode.Valid() {
assert.Fail(c, "Netmap or SelfNode is invalid")
return
}
// Check for the app-connectors capability in CapMap
capMap := netmap.SelfNode.CapMap
if capMap == nil {
capMap := nm.SelfNode.CapMap()
if capMap.IsNil() {
assert.Fail(c, "CapMap is nil")
return
}
appConnectorCap := tailcfg.NodeCapability("tailscale.com/app-connectors")
attrs, hasCapability := capMap[appConnectorCap]
attrs, hasCapability := capMap.GetOk(appConnectorCap)
assert.True(c, hasCapability, "Node should have app-connectors capability")
if hasCapability {
// Verify we have the expected number of app connector configs
assert.Len(c, attrs, 2, "Should have 2 app connector configs")
assert.Equal(c, 2, attrs.Len(), "Should have 2 app connector configs")
// Verify the content of the configs
var configs []policyv2.AppConnectorAttr
for _, attr := range attrs {
var cfg policyv2.AppConnectorAttr
err := json.Unmarshal([]byte(attr), &cfg)
assert.NoError(c, err)
configs = append(configs, cfg)
}
// Check that we have the expected domains
var allDomains []string
for _, cfg := range configs {
for i := range attrs.Len() {
var cfg policyv2.AppConnectorAttr
err := json.Unmarshal([]byte(attrs.At(i)), &cfg)
assert.NoError(c, err)
allDomains = append(allDomains, cfg.Domains...)
}
assert.Contains(c, allDomains, "internal.example.com")
assert.Contains(c, allDomains, "*.corp.example.com")
assert.Contains(c, allDomains, "vpn.example.com")
}
}, 60*time.Second, 1*time.Second, "App connector capability should be propagated")
t.Log("TestAppConnectorBasic PASSED: App connector configuration propagated correctly")
}
// TestAppConnectorNonMatchingTag tests that nodes without matching tags
@ -250,16 +243,14 @@ func TestAppConnectorNonMatchingTag(t *testing.T) {
// Use a shorter timeout since we're checking for absence
time.Sleep(5 * time.Second)
netmap, err := otherNode.Netmap()
nm, err := otherNode.Netmap()
require.NoError(t, err)
if netmap != nil && netmap.SelfNode != nil && netmap.SelfNode.CapMap != nil {
if nm != nil && nm.SelfNode.Valid() && !nm.SelfNode.CapMap().IsNil() {
appConnectorCap := tailcfg.NodeCapability("tailscale.com/app-connectors")
_, hasCapability := netmap.SelfNode.CapMap[appConnectorCap]
_, hasCapability := nm.SelfNode.CapMap().GetOk(appConnectorCap)
assert.False(t, hasCapability, "Node with non-matching tag should NOT have app-connectors capability")
}
t.Log("TestAppConnectorNonMatchingTag PASSED: Non-matching tag correctly excluded")
}
// TestAppConnectorWildcardConnector tests that a wildcard (*) connector
@ -322,34 +313,32 @@ func TestAppConnectorWildcardConnector(t *testing.T) {
// Wait for the app connector capability to be propagated
assert.EventuallyWithT(t, func(c *assert.CollectT) {
netmap, err := regularNode.Netmap()
nm, err := regularNode.Netmap()
assert.NoError(c, err)
if netmap == nil || netmap.SelfNode == nil {
assert.Fail(c, "Netmap or SelfNode is nil")
if nm == nil || !nm.SelfNode.Valid() {
assert.Fail(c, "Netmap or SelfNode is invalid")
return
}
capMap := netmap.SelfNode.CapMap
if capMap == nil {
capMap := nm.SelfNode.CapMap()
if capMap.IsNil() {
assert.Fail(c, "CapMap is nil")
return
}
appConnectorCap := tailcfg.NodeCapability("tailscale.com/app-connectors")
attrs, hasCapability := capMap[appConnectorCap]
attrs, hasCapability := capMap.GetOk(appConnectorCap)
assert.True(c, hasCapability, "Node should have app-connectors capability with wildcard connector")
if hasCapability {
assert.Len(c, attrs, 1, "Should have 1 app connector config")
assert.Equal(c, 1, attrs.Len(), "Should have 1 app connector config")
// Verify the domain
var cfg policyv2.AppConnectorAttr
err := json.Unmarshal([]byte(attrs[0]), &cfg)
err := json.Unmarshal([]byte(attrs.At(0)), &cfg)
assert.NoError(c, err)
assert.Contains(c, cfg.Domains, "*.internal.example.com")
}
}, 60*time.Second, 1*time.Second, "App connector capability should be propagated with wildcard")
t.Log("TestAppConnectorWildcardConnector PASSED: Wildcard connector works correctly")
}