From 96188e33a34735bc7493bead65eebc3127472ef9 Mon Sep 17 00:00:00 2001 From: Michael Eischer <9106997+MichaelEischer@users.noreply.github.com> Date: Sun, 20 Sep 2026 20:03:48 +0200 Subject: [PATCH] backend/s3: switch tests from minio to seaweedfs (#22067) --- .github/workflows/tests.yml | 25 ++++++++++---- README.md | 2 +- internal/backend/s3/s3_test.go | 59 +++++++++++++++++++--------------- 3 files changed, 52 insertions(+), 34 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7210ff9f3..92ccf730c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -69,14 +69,21 @@ jobs: echo "build Go tools" go install github.com/restic/rest-server/cmd/rest-server@master - echo "install minio server" + echo "install seaweedfs" + SEAWEEDFS_VERSION=4.47 mkdir $HOME/bin + case "$(uname -m)" in + x86_64) seaweed_arch=amd64 ;; + arm64|aarch64) seaweed_arch=arm64 ;; + *) echo "unsupported architecture $(uname -m)"; exit 1 ;; + esac if [ "$RUNNER_OS" == "macOS" ]; then - wget --no-verbose -O $HOME/bin/minio https://dl.minio.io/server/minio/release/darwin-amd64/minio + seaweed_os=darwin else - wget --no-verbose -O $HOME/bin/minio https://dl.minio.io/server/minio/release/linux-amd64/minio + seaweed_os=linux fi - chmod 755 $HOME/bin/minio + wget --no-verbose -O- "https://github.com/seaweedfs/seaweedfs/releases/download/${SEAWEEDFS_VERSION}/${seaweed_os}_${seaweed_arch}.tar.gz" \ + | tar -xzf - -C $HOME/bin weed echo "install rclone" if [ "$RUNNER_OS" == "macOS" ]; then @@ -101,9 +108,13 @@ jobs: echo "build Go tools" go install github.com/restic/rest-server/cmd/rest-server@master - echo "install minio server" + echo "install seaweedfs" + $seaweedVersion = "4.47" mkdir $Env:USERPROFILE/bin - Invoke-WebRequest https://dl.minio.io/server/minio/release/windows-amd64/minio.exe -OutFile $Env:USERPROFILE/bin/minio.exe + Invoke-WebRequest "https://github.com/seaweedfs/seaweedfs/releases/download/$seaweedVersion/windows_amd64.zip" -OutFile seaweedfs.zip + unzip seaweedfs.zip + move weed.exe $Env:USERPROFILE/bin + rm seaweedfs.zip echo "install rclone" Invoke-WebRequest https://downloads.rclone.org/rclone-current-windows-amd64.zip -OutFile rclone.zip @@ -176,7 +187,7 @@ jobs: # fail if any of the following tests cannot be run RESTIC_TEST_DISALLOW_SKIP: "restic/backend/rest.TestBackendREST,\ restic/backend/sftp.TestBackendSFTP,\ - restic/backend/s3.TestBackendMinio,\ + restic/backend/s3.TestBackendSeaweedFS,\ restic/backend/rclone.TestBackendRclone,\ restic/backend/s3.TestBackendS3,\ restic/backend/swift.TestBackendSwift,\ diff --git a/README.md b/README.md index b0861e60f..578b865b5 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Therefore, restic supports the following backends for storing backups natively: - [Local directory](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#local) - [sftp server (via SSH)](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#sftp) - [HTTP REST server](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#rest-server) ([protocol](https://restic.readthedocs.io/en/latest/100_references.html#rest-backend), [rest-server](https://github.com/restic/rest-server)) -- [Amazon S3](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#amazon-s3) (either from Amazon or using the [Minio](https://minio.io) server) +- [Amazon S3](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#amazon-s3) (or any other S3-compatible storage) - [OpenStack Swift](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#openstack-swift) - [BackBlaze B2](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#backblaze-b2) - [Microsoft Azure Blob Storage](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#microsoft-azure-blob-storage) diff --git a/internal/backend/s3/s3_test.go b/internal/backend/s3/s3_test.go index e98fce12f..962533fd6 100644 --- a/internal/backend/s3/s3_test.go +++ b/internal/backend/s3/s3_test.go @@ -10,7 +10,6 @@ import ( "net/http" "os" "os/exec" - "path/filepath" "testing" "time" @@ -22,6 +21,8 @@ import ( rtest "github.com/restic/restic/internal/test" ) +const seaweedFSS3Addr = "127.0.0.1:8333" + func mkdir(t testing.TB, dir string) { err := os.MkdirAll(dir, 0700) if err != nil { @@ -29,18 +30,24 @@ func mkdir(t testing.TB, dir string) { } } -func runMinio(ctx context.Context, t testing.TB, dir, key, secret string) func() { - mkdir(t, filepath.Join(dir, "config")) - mkdir(t, filepath.Join(dir, "root")) +func runSeaweedFS(ctx context.Context, t testing.TB, dir, key, secret string) func() { + mkdir(t, dir) - cmd := exec.CommandContext(ctx, "minio", - "server", - "--address", "127.0.0.1:9000", - "--config-dir", filepath.Join(dir, "config"), - filepath.Join(dir, "root")) + cmd := exec.CommandContext(ctx, "weed", + "mini", + "-dir", dir, + "-ip", "127.0.0.1", + "-ip.bind", "127.0.0.1", + "-s3.port", "8333", + "-s3.port.iceberg", "0", + "-s3.port.lance", "0", + "-webdav=false", + "-admin.ui=false", + "-master.telemetry=false", + ) cmd.Env = append(os.Environ(), - "MINIO_ACCESS_KEY="+key, - "MINIO_SECRET_KEY="+secret, + "AWS_ACCESS_KEY_ID="+key, + "AWS_SECRET_ACCESS_KEY="+secret, ) cmd.Stderr = os.Stderr @@ -49,12 +56,12 @@ func runMinio(ctx context.Context, t testing.TB, dir, key, secret string) func() t.Fatal(err) } - // wait until the TCP port is reachable + // wait until the S3 TCP port is reachable var success bool for range 100 { time.Sleep(200 * time.Millisecond) - c, err := net.Dial("tcp", "localhost:9000") + c, err := net.Dial("tcp", seaweedFSS3Addr) if err == nil { success = true if err := c.Close(); err != nil { @@ -65,7 +72,7 @@ func runMinio(ctx context.Context, t testing.TB, dir, key, secret string) func() } if !success { - t.Fatal("unable to connect to minio server") + t.Fatal("unable to connect to seaweedfs s3 endpoint") return nil } @@ -97,21 +104,23 @@ func newRandomCredentials(t testing.TB) (key, secret string) { return key, secret } -func newMinioTestSuite(t testing.TB) (*test.Suite[s3.Config], func()) { +func newSeaweedFSTestSuite(t testing.TB) (*test.Suite[s3.Config], func()) { ctx, cancel := context.WithCancel(context.Background()) tempdir := rtest.TempDir(t) key, secret := newRandomCredentials(t) - cleanup := runMinio(ctx, t, tempdir, key, secret) + cleanup := runSeaweedFS(ctx, t, tempdir, key, secret) return &test.Suite[s3.Config]{ // NewConfig returns a config for a new temporary backend that will be used in tests. NewConfig: func() (*s3.Config, error) { cfg := s3.NewConfig() - cfg.Endpoint = "localhost:9000" + cfg.Endpoint = seaweedFSS3Addr cfg.Bucket = "restictestbucket" cfg.Prefix = fmt.Sprintf("test-%d", time.Now().UnixNano()) cfg.UseHTTP = true + cfg.Region = "us-east-1" + cfg.BucketLookup = "path" cfg.KeyID = key cfg.Secret = options.NewSecretString(secret) return &cfg, nil @@ -135,35 +144,33 @@ func newMinioTestSuite(t testing.TB) (*test.Suite[s3.Config], func()) { } } -func TestBackendMinio(t *testing.T) { +func TestBackendSeaweedFS(t *testing.T) { defer func() { if t.Skipped() { - rtest.SkipDisallowed(t, "restic/backend/s3.TestBackendMinio") + rtest.SkipDisallowed(t, "restic/backend/s3.TestBackendSeaweedFS") } }() - // try to find a minio binary - _, err := exec.LookPath("minio") + _, err := exec.LookPath("weed") if err != nil { t.Skip(err) return } - suite, cleanup := newMinioTestSuite(t) + suite, cleanup := newSeaweedFSTestSuite(t) defer cleanup() suite.RunTests(t) } -func BenchmarkBackendMinio(t *testing.B) { - // try to find a minio binary - _, err := exec.LookPath("minio") +func BenchmarkBackendSeaweedFS(t *testing.B) { + _, err := exec.LookPath("weed") if err != nil { t.Skip(err) return } - suite, cleanup := newMinioTestSuite(t) + suite, cleanup := newSeaweedFSTestSuite(t) defer cleanup() suite.RunBenchmarks(t)