clientupdate,net/tstun: add support for OpenWrt 25.12.0 using apk (#18545)
OpenWrt is changing to using alpine like `apk` for package installation over its previous opkg. Additionally, they are not using the same repo files as alpine making installation fail. Add support for the new repository files and ensure that the required package detection system uses apk. Updates #18535 Signed-off-by: Claus Lensbøl <claus@tailscale.com>
This commit is contained in:
@@ -6,9 +6,12 @@ package clientupdate
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"maps"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
@@ -299,6 +302,127 @@ tailscale-1.58.2-r0 installed size:
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckOutdatedAlpineRepo(t *testing.T) {
|
||||
anyToString := func(a any) string {
|
||||
str, ok := a.(string)
|
||||
if !ok {
|
||||
panic("failed to parse param as string")
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
fileContent string
|
||||
latestHTTPVersion string
|
||||
latestApkVersion string
|
||||
wantHTTPVersion string
|
||||
wantApkVersion string
|
||||
wantAlpineVersion string
|
||||
track string
|
||||
}{
|
||||
{
|
||||
name: "Up to date",
|
||||
fileContent: "https://dl-cdn.alpinelinux.org/alpine/v3.20/main",
|
||||
latestHTTPVersion: "1.95.3",
|
||||
latestApkVersion: "1.95.3",
|
||||
track: "unstable",
|
||||
},
|
||||
{
|
||||
name: "Behind unstable",
|
||||
fileContent: "https://dl-cdn.alpinelinux.org/alpine/v3.20/main",
|
||||
latestHTTPVersion: "1.95.4",
|
||||
latestApkVersion: "1.95.3",
|
||||
wantHTTPVersion: "1.95.4",
|
||||
wantApkVersion: "1.95.3",
|
||||
wantAlpineVersion: "v3.20",
|
||||
track: "unstable",
|
||||
},
|
||||
{
|
||||
name: "Behind stable",
|
||||
fileContent: "https://dl-cdn.alpinelinux.org/alpine/v2.40/main",
|
||||
latestHTTPVersion: "1.94.3",
|
||||
latestApkVersion: "1.92.1",
|
||||
wantHTTPVersion: "1.94.3",
|
||||
wantApkVersion: "1.92.1",
|
||||
wantAlpineVersion: "v2.40",
|
||||
track: "stable",
|
||||
},
|
||||
{
|
||||
name: "Nothing in dist file",
|
||||
fileContent: "",
|
||||
latestHTTPVersion: "1.94.3",
|
||||
latestApkVersion: "1.92.1",
|
||||
wantHTTPVersion: "1.94.3",
|
||||
wantApkVersion: "1.92.1",
|
||||
track: "stable",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dir, err := os.MkdirTemp("", "example")
|
||||
if err != nil {
|
||||
t.Fatalf("error creating temp dir: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { os.RemoveAll(dir) }) // clean up
|
||||
|
||||
file := filepath.Join(dir, "distfile")
|
||||
if err := os.WriteFile(file, []byte(tt.fileContent), 0o666); err != nil {
|
||||
t.Fatalf("error creating dist file: %v", err)
|
||||
}
|
||||
|
||||
testServ := httptest.NewServer(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, _ *http.Request) {
|
||||
version := trackPackages{
|
||||
MSIsVersion: tt.latestHTTPVersion,
|
||||
MacZipsVersion: tt.latestHTTPVersion,
|
||||
TarballsVersion: tt.latestHTTPVersion,
|
||||
SPKsVersion: tt.latestHTTPVersion,
|
||||
}
|
||||
jsonData, err := json.Marshal(version)
|
||||
if err != nil {
|
||||
t.Errorf("failed to marshal version string: %v", err)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if _, err := w.Write(jsonData); err != nil {
|
||||
t.Errorf("failed to write json blob: %v", err)
|
||||
}
|
||||
},
|
||||
))
|
||||
defer testServ.Close()
|
||||
|
||||
oldEndpoint := tailscaleHTTPEndpoint
|
||||
tailscaleHTTPEndpoint = testServ.URL
|
||||
defer func() { tailscaleHTTPEndpoint = oldEndpoint }()
|
||||
|
||||
var paramLatest string
|
||||
var paramApkVer string
|
||||
var paramAlpineVer string
|
||||
logf := func(_ string, params ...any) {
|
||||
paramLatest = anyToString(params[0])
|
||||
paramApkVer = anyToString(params[1])
|
||||
if len(params) > 2 {
|
||||
paramAlpineVer = anyToString(params[2])
|
||||
}
|
||||
}
|
||||
|
||||
err = checkOutdatedAlpineRepo(logf, []string{file}, tt.latestApkVersion, tt.track)
|
||||
if err != nil {
|
||||
t.Errorf("did not expect error, got: %v", err)
|
||||
}
|
||||
if paramLatest != tt.wantHTTPVersion {
|
||||
t.Errorf("expected HTTP version '%s', got '%s'", tt.wantHTTPVersion, paramLatest)
|
||||
}
|
||||
if paramApkVer != tt.wantApkVersion {
|
||||
t.Errorf("expected APK version '%s', got '%s'", tt.wantApkVersion, paramApkVer)
|
||||
}
|
||||
if paramAlpineVer != tt.wantAlpineVersion {
|
||||
t.Errorf("expected alpine version '%s', got '%s'", tt.wantAlpineVersion, paramAlpineVer)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSynoArch(t *testing.T) {
|
||||
tests := []struct {
|
||||
goarch string
|
||||
|
||||
Reference in New Issue
Block a user