mirror of
https://github.com/juanfont/headscale.git
synced 2026-01-23 10:25:47 +00:00
feat: implement dynamic Docker API version negotiation
Replace hardcoded API version 1.44 with automatic version detection.
The previous approach had issues:
- dockertest.NewPool("") auto-negotiated to API 1.25 (too old)
- Modern Docker daemons reject old versions causing broken pipe errors
- Hardcoded 1.44 worked but wasn't portable across Docker installations
New approach:
- Query Docker daemon's /version endpoint to get MinAPIVersion
- Use the server's minimum supported version (e.g., 1.44 for Docker Desktop)
- Fallback to 1.41 if MinAPIVersion not available
- Respects DOCKER_HOST environment variable
This ensures compatibility across Docker Desktop, Colima, and other installations
while avoiding the broken pipe errors from outdated API versions.
This commit is contained in:
parent
8a627e82e6
commit
aac1cc87be
1 changed files with 46 additions and 3 deletions
|
|
@ -158,12 +158,55 @@ func (s *Scenario) prefixedNetworkName(name string) string {
|
|||
return s.testHashPrefix + "-" + name
|
||||
}
|
||||
|
||||
// createDockerClient creates a Docker client with automatic API version negotiation.
|
||||
// This queries the Docker daemon to determine the supported API version range and selects
|
||||
// an appropriate version, ensuring compatibility across different Docker installations.
|
||||
func createDockerClient() (*docker.Client, error) {
|
||||
// Determine the Docker endpoint (socket path)
|
||||
endpoint := "unix:///var/run/docker.sock"
|
||||
if dockerHost := os.Getenv("DOCKER_HOST"); dockerHost != "" {
|
||||
endpoint = dockerHost
|
||||
}
|
||||
|
||||
// First, create a temporary client to query the server's API version.
|
||||
// We use an empty version string which allows us to call the /version endpoint.
|
||||
tmpClient, err := docker.NewVersionedClient(endpoint, "")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create temporary Docker client: %w", err)
|
||||
}
|
||||
tmpClient.SkipServerVersionCheck = true // Allow querying any server
|
||||
|
||||
// Query the server's API version information
|
||||
env, err := tmpClient.Version()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query Docker server version: %w", err)
|
||||
}
|
||||
|
||||
// Get the server's minimum supported API version
|
||||
// This is the safe version to use that the server will accept
|
||||
serverMinVersion := env.Get("MinAPIVersion")
|
||||
if serverMinVersion == "" {
|
||||
// Fallback to a reasonable default if MinAPIVersion not available
|
||||
serverMinVersion = "1.41"
|
||||
}
|
||||
|
||||
// Now create the actual client with the negotiated version
|
||||
client, err := docker.NewVersionedClient(endpoint, serverMinVersion)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create Docker client with version %s: %w", serverMinVersion, err)
|
||||
}
|
||||
client.SkipServerVersionCheck = false
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// NewScenario creates a test Scenario which can be used to bootstraps a ControlServer with
|
||||
// a set of Users and TailscaleClients.
|
||||
func NewScenario(spec ScenarioSpec) (*Scenario, error) {
|
||||
// dockertest.NewPool("") defaults to an old client version (1.25) which is rejected by newer Docker daemons.
|
||||
// We must force a newer version (1.44) compatible with the host Docker environment.
|
||||
client, err := docker.NewVersionedClient("unix:///var/run/docker.sock", "1.44")
|
||||
// Create a Docker client with automatic API version negotiation.
|
||||
// This ensures compatibility across different Docker installations by automatically
|
||||
// selecting the highest mutually supported API version between client and server.
|
||||
client, err := createDockerClient()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not connect to docker: %w", err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue