diff --git a/test/fuse_integration/framework.go b/test/fuse_integration/framework.go index a6d002eeef..9fe62fcd71 100644 --- a/test/fuse_integration/framework.go +++ b/test/fuse_integration/framework.go @@ -424,6 +424,10 @@ func (f *FuseTestFramework) startMini(config *TestConfig) error { // -v is a global flag; before the subcommand or flag parsing dies args = append(args, "-v=4") } + adminPort := freePort(f.t) + for adminPort == f.filerPort { + adminPort = freePort(f.t) + } args = append(args, "mini", "-dir="+f.dataDir, @@ -433,6 +437,9 @@ func (f *FuseTestFramework) startMini(config *TestConfig) error { "-s3=false", "-webdav=false", "-admin.ui=false", + "-admin.port="+strconv.Itoa(adminPort), + "-admin.port.grpc="+strconv.Itoa(adminPort+grpcPortOffset), + "-admin.port.legacy=0", ) proc, err := f.startProcess("mini", args) diff --git a/test/fuse_integration/framework_test.go b/test/fuse_integration/framework_test.go index f045fa157b..3141d9c51d 100644 --- a/test/fuse_integration/framework_test.go +++ b/test/fuse_integration/framework_test.go @@ -320,6 +320,10 @@ func (f *FuseTestFramework) startMini(config *TestConfig) error { if config.EnableDebug { args = append(args, "-v=4") } + adminPort := freePort(f.t) + for adminPort == f.filerPort { + adminPort = freePort(f.t) + } args = append(args, "mini", "-dir="+f.dataDir, @@ -329,6 +333,9 @@ func (f *FuseTestFramework) startMini(config *TestConfig) error { "-s3=false", "-webdav=false", "-admin.ui=false", + "-admin.port="+strconv.Itoa(adminPort), + "-admin.port.grpc="+strconv.Itoa(adminPort+grpcPortOffset), + "-admin.port.legacy=0", ) proc, err := f.startProcess("mini", args) diff --git a/test/s3/iam/s3_iam_admin_test.go b/test/s3/iam/s3_iam_admin_test.go index 75556b43f7..70906dd26e 100644 --- a/test/s3/iam/s3_iam_admin_test.go +++ b/test/s3/iam/s3_iam_admin_test.go @@ -295,8 +295,8 @@ func TestIAMPolicyManagement(t *testing.T) { assert.Equal(t, true, aws.BoolValue(listVersionsResp.Versions[0].IsDefaultVersion)) getVersionResp, err := iamClient.GetPolicyVersion(&iam.GetPolicyVersionInput{ - PolicyArn: createResp.Policy.Arn, - VersionId: aws.String("v1"), + PolicyArn: createResp.Policy.Arn, + VersionId: aws.String("v1"), }) require.NoError(t, err) require.NotNil(t, getVersionResp.PolicyVersion) diff --git a/test/s3/iam/s3_sts_get_federation_token_test.go b/test/s3/iam/s3_sts_get_federation_token_test.go index 2a718cba90..69807bb169 100644 --- a/test/s3/iam/s3_sts_get_federation_token_test.go +++ b/test/s3/iam/s3_sts_get_federation_token_test.go @@ -14,8 +14,8 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/s3" v4 "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/service/s3" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/test/s3/lifecycle/s3_lifecycle_object_lock_test.go b/test/s3/lifecycle/s3_lifecycle_object_lock_test.go index 7196346de9..e601f85500 100644 --- a/test/s3/lifecycle/s3_lifecycle_object_lock_test.go +++ b/test/s3/lifecycle/s3_lifecycle_object_lock_test.go @@ -116,4 +116,3 @@ func TestLifecycleSkipsObjectLockedObjects(t *testing.T) { }) require.NoError(t, err, "object under GOVERNANCE retention must survive the sweep") } - diff --git a/test/s3/normal/s3_integration_test.go b/test/s3/normal/s3_integration_test.go index e9a9ed6908..e37972c4bb 100644 --- a/test/s3/normal/s3_integration_test.go +++ b/test/s3/normal/s3_integration_test.go @@ -117,7 +117,8 @@ func TestS3Integration(t *testing.T) { // Extra flags can be appended via extraArgs. func startMiniCluster(t *testing.T, extraArgs ...string) (*TestCluster, error) { // Allocate non-colliding ports (including gRPC offsets) for weed mini. - ports := testutil.MustFreeMiniPorts(t, []string{"Master", "Volume", "Filer", "S3"}) + ports := testutil.MustFreeMiniPorts(t, []string{"Master", "Volume", "Filer", "S3", "Admin"}) + adminPort := ports[4] masterPort := ports[0] volumePort := ports[1] filerPort := ports[2] @@ -186,13 +187,15 @@ func startMiniCluster(t *testing.T, extraArgs ...string) (*TestCluster, error) { "-volume.port=" + strconv.Itoa(volumePort), "-filer.port=" + strconv.Itoa(filerPort), "-s3.port=" + strconv.Itoa(s3Port), - "-webdav.port=0", // Disable WebDAV + "-webdav=false", // Disable WebDAV "-admin.ui=false", // Disable admin UI "-master.volumeSizeLimitMB=32", // Small volumes for testing "-ip=127.0.0.1", "-master.peers=none", // Faster startup "-s3.iam.readOnly=false", // Enable IAM write operations for tests }, extraArgs...) + os.Args = append(os.Args, testutil.MiniAdminArgs(adminPort)...) + os.Args = append(os.Args, "-s3.port.lance=0", "-s3.port.iceberg=0") // Suppress most logging during tests glog.MaxSize = 1024 * 1024 diff --git a/test/s3/policy/policy_test.go b/test/s3/policy/policy_test.go index 2e3e1364e3..302ddbceb5 100644 --- a/test/s3/policy/policy_test.go +++ b/test/s3/policy/policy_test.go @@ -710,12 +710,12 @@ func startMiniCluster(t *testing.T) (*TestCluster, error) { // mini in a goroutine, but the previous mini's admin goroutine is // still binding 12535 — so the next test's admin can never become // ready and mini.go fatals on its readiness check. - ports := testutil.MustAllocatePorts(t, 10) + ports := testutil.MustAllocatePorts(t, 8) + adminPort := testutil.MustFreeMiniPort(t, "admin") masterPort, masterGrpcPort := ports[0], ports[1] volumePort, volumeGrpcPort := ports[2], ports[3] filerPort, filerGrpcPort := ports[4], ports[5] s3Port, s3GrpcPort := ports[6], ports[7] - adminPort, adminGrpcPort := ports[8], ports[9] // Manually-managed temp dir (not t.TempDir()) so we control removal order: // the dir is removed inside Stop() AFTER the mini goroutine has fully @@ -786,15 +786,16 @@ enabled = true "-filer.port.grpc=" + strconv.Itoa(filerGrpcPort), "-s3.port=" + strconv.Itoa(s3Port), "-s3.port.grpc=" + strconv.Itoa(s3GrpcPort), - "-admin.port=" + strconv.Itoa(adminPort), - "-admin.port.grpc=" + strconv.Itoa(adminGrpcPort), - "-webdav.port=0", + "-webdav=false", + "-s3.port.lance=0", + "-s3.port.iceberg=0", "-admin.ui=false", "-master.volumeSizeLimitMB=32", "-ip=127.0.0.1", "-master.peers=none", "-s3.iam.readOnly=false", } + os.Args = append(os.Args, testutil.MiniAdminArgs(adminPort)...) glog.MaxSize = 1024 * 1024 for _, cmd := range command.Commands { if cmd.Name() == "mini" && cmd.Run != nil { diff --git a/test/s3/remote_cache/remote_cache_evict_test.go b/test/s3/remote_cache/remote_cache_evict_test.go index 49060319f4..cb44f1f3fb 100644 --- a/test/s3/remote_cache/remote_cache_evict_test.go +++ b/test/s3/remote_cache/remote_cache_evict_test.go @@ -16,6 +16,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/s3" + "github.com/seaweedfs/seaweedfs/test/testutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -48,12 +49,15 @@ func startMini(t *testing.T, dir string, args ...string) { logFile, err := os.Create(logPath) require.NoError(t, err) miniLogPaths = append(miniLogPaths, logPath) - cmd := exec.Command(weedBinary, append([]string{"mini", + miniArgs := append([]string{"mini", "-dir=" + dir, "-s3.config=s3_config.json", "-s3.allowDeleteBucketNotEmpty=true", "-ip=127.0.0.1", "-ip.bind=127.0.0.1", - }, args...)...) + }, args...) + miniArgs = append(miniArgs, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + miniArgs = append(miniArgs, "-s3.port.lance=0", "-s3.port.iceberg=0") + cmd := exec.Command(weedBinary, miniArgs...) cmd.Stdout = logFile cmd.Stderr = logFile require.NoError(t, cmd.Start()) diff --git a/test/s3/sdk_v2_routing/s3_sdk_v2_routing_test.go b/test/s3/sdk_v2_routing/s3_sdk_v2_routing_test.go index 2345fdf573..9adc2300f2 100644 --- a/test/s3/sdk_v2_routing/s3_sdk_v2_routing_test.go +++ b/test/s3/sdk_v2_routing/s3_sdk_v2_routing_test.go @@ -207,4 +207,3 @@ func TestCreateAndListBuckets_ServiceLevel(t *testing.T) { } require.True(t, found, "bucket %q must appear in service-level ListBuckets", bucket) } - diff --git a/test/s3/spark/setup_test.go b/test/s3/spark/setup_test.go index efdb2c60d5..3b647a2f8e 100644 --- a/test/s3/spark/setup_test.go +++ b/test/s3/spark/setup_test.go @@ -94,7 +94,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { t.Fatalf("failed to create temp directory: %v", err) } - ports := testutil.MustFreeMiniPorts(t, []string{"Master", "Filer", "S3"}) + ports := testutil.MustFreeMiniPorts(t, []string{"Master", "Filer", "S3", "Admin"}) env.masterPort = ports[0] env.filerPort = ports[1] env.s3Port = ports[2] @@ -105,8 +105,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { t.Fatalf("failed to create IAM config: %v", err) } - env.masterProcess = exec.Command( - env.weedBinary, "mini", + miniArgs := append([]string{"mini", "-ip", bindIP, "-ip.bind", "0.0.0.0", "-master.port", fmt.Sprintf("%d", env.masterPort), @@ -114,7 +113,9 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { "-s3.port", fmt.Sprintf("%d", env.s3Port), "-s3.config", iamConfigPath, "-dir", env.seaweedfsDataDir, - ) + }, testutil.MiniAdminArgs(ports[3])...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.lance=0", "-s3.port.iceberg=0") + env.masterProcess = exec.Command(env.weedBinary, miniArgs...) weedLogPath := filepath.Join(env.seaweedfsDataDir, "weed-mini.log") weedLogFile, err := os.Create(weedLogPath) if err != nil { diff --git a/test/s3tables/admin/admin_iceberg_pages_test.go b/test/s3tables/admin/admin_iceberg_pages_test.go index 4b6b2e4102..1cc32c2168 100644 --- a/test/s3tables/admin/admin_iceberg_pages_test.go +++ b/test/s3tables/admin/admin_iceberg_pages_test.go @@ -91,7 +91,11 @@ func TestMain(m *testing.M) { } func startCluster(testDir string) (*testCluster, error) { - ports, err := testutil.AllocatePorts(10) + ports, err := testutil.AllocatePorts(9) + if err != nil { + return nil, err + } + adminPorts, err := testutil.AllocateMiniPorts(1) if err != nil { return nil, err } @@ -99,7 +103,8 @@ func startCluster(testDir string) (*testCluster, error) { volumePort, volumeGrpc := ports[2], ports[3] filerPort, filerGrpc := ports[4], ports[5] s3Port, s3Grpc := ports[6], ports[7] - adminPort, adminGrpc := ports[8], ports[9] + adminPort := adminPorts[0] + icebergPort := ports[8] // Empty security.toml disables JWT auth. if err := os.WriteFile(filepath.Join(testDir, "security.toml"), []byte("# test\n"), 0644); err != nil { @@ -150,14 +155,15 @@ func startCluster(testDir string) (*testCluster, error) { "-filer.port.grpc=" + strconv.Itoa(filerGrpc), "-s3.port=" + strconv.Itoa(s3Port), "-s3.port.grpc=" + strconv.Itoa(s3Grpc), - "-admin.port=" + strconv.Itoa(adminPort), - "-admin.port.grpc=" + strconv.Itoa(adminGrpc), - "-webdav.port=0", + "-webdav=false", // Disable WebDAV + "-s3.port.lance=0", // Disable Lance + "-s3.port.iceberg=" + strconv.Itoa(icebergPort), "-master.volumeSizeLimitMB=32", "-ip=127.0.0.1", "-master.peers=none", "-s3.iam.readOnly=false", } + args = append(args, testutil.MiniAdminArgs(adminPort)...) os.Args = append([]string{"weed"}, args...) glog.MaxSize = 1024 * 1024 for _, cmd := range command.Commands { diff --git a/test/s3tables/catalog/duckdb_oauth_test.go b/test/s3tables/catalog/duckdb_oauth_test.go index 865a7ee8d5..346cd2d096 100644 --- a/test/s3tables/catalog/duckdb_oauth_test.go +++ b/test/s3tables/catalog/duckdb_oauth_test.go @@ -135,6 +135,8 @@ func (env *oauthTestEnv) start(t *testing.T) { if env.s3ExternalURL != "" { args = append(args, "-s3.externalUrl", env.s3ExternalURL) } + args = append(args, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + args = append(args, "-s3.port.lance=0") cmd := exec.CommandContext(ctx, env.weedBinary, args...) cmd.Dir = env.dataDir diff --git a/test/s3tables/catalog/iceberg_catalog_test.go b/test/s3tables/catalog/iceberg_catalog_test.go index b45f3714ad..908f54b176 100644 --- a/test/s3tables/catalog/iceberg_catalog_test.go +++ b/test/s3tables/catalog/iceberg_catalog_test.go @@ -63,6 +63,7 @@ type TestEnvironment struct { s3GrpcPort int icebergPort int lancePort int + adminPort int masterPort int masterGrpcPort int filerPort int @@ -117,6 +118,10 @@ func newTestEnvironmentForMain() (*TestEnvironment, error) { if err != nil { return nil, fmt.Errorf("allocate ports: %w", err) } + adminPorts, err := testutil.AllocateMiniPorts(1) + if err != nil { + return nil, fmt.Errorf("allocate admin port: %w", err) + } return &TestEnvironment{ seaweedDir: seaweedDir, @@ -132,6 +137,7 @@ func newTestEnvironmentForMain() (*TestEnvironment, error) { volumePort: ports[7], volumeGrpcPort: ports[8], lancePort: ports[9], + adminPort: adminPorts[0], dockerAvailable: testutil.HasDocker(), }, nil } @@ -152,7 +158,7 @@ func (env *TestEnvironment) startSeaweedFSForMain() error { } } - cmd := exec.CommandContext(ctx, env.weedBinary, "mini", + miniArgs := append([]string{"mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -165,7 +171,9 @@ func (env *TestEnvironment) startSeaweedFSForMain() error { "-s3.port.lance", fmt.Sprintf("%d", env.lancePort), "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(env.adminPort)...) + miniArgs = append(miniArgs, "-webdav=false") + cmd := exec.CommandContext(ctx, env.weedBinary, miniArgs...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/catalog_clickhouse/clickhouse_catalog_test.go b/test/s3tables/catalog_clickhouse/clickhouse_catalog_test.go index d12173398c..098fae43a5 100644 --- a/test/s3tables/catalog_clickhouse/clickhouse_catalog_test.go +++ b/test/s3tables/catalog_clickhouse/clickhouse_catalog_test.go @@ -364,7 +364,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) env.weedCancel = cancel - cmd := exec.CommandContext(ctx, env.weedBinary, "mini", + miniArgs := append([]string{"mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -378,7 +378,9 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { "-ip", env.bindIP, "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.lance=0") + cmd := exec.CommandContext(ctx, env.weedBinary, miniArgs...) cmd.Dir = env.dataDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/catalog_doris/doris_catalog_test.go b/test/s3tables/catalog_doris/doris_catalog_test.go index b7b071b3f2..3a8aaf9e22 100644 --- a/test/s3tables/catalog_doris/doris_catalog_test.go +++ b/test/s3tables/catalog_doris/doris_catalog_test.go @@ -303,7 +303,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) env.weedCancel = cancel - cmd := exec.CommandContext(ctx, env.weedBinary, "mini", + miniArgs := append([]string{"mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -317,7 +317,9 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { "-ip", env.bindIP, "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.lance=0") + cmd := exec.CommandContext(ctx, env.weedBinary, miniArgs...) cmd.Dir = env.dataDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/catalog_dremio/dremio_catalog_test.go b/test/s3tables/catalog_dremio/dremio_catalog_test.go index 09eed0055e..35fedb00f1 100644 --- a/test/s3tables/catalog_dremio/dremio_catalog_test.go +++ b/test/s3tables/catalog_dremio/dremio_catalog_test.go @@ -289,7 +289,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) env.weedCancel = cancel - cmd := exec.CommandContext(ctx, env.weedBinary, "mini", + miniArgs := append([]string{"mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -303,7 +303,9 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { "-ip", env.bindIP, "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.lance=0") + cmd := exec.CommandContext(ctx, env.weedBinary, miniArgs...) cmd.Dir = env.dataDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/catalog_duckdb_lance/duckdb_lance_test.go b/test/s3tables/catalog_duckdb_lance/duckdb_lance_test.go index 997cab2601..5cefd12059 100644 --- a/test/s3tables/catalog_duckdb_lance/duckdb_lance_test.go +++ b/test/s3tables/catalog_duckdb_lance/duckdb_lance_test.go @@ -142,7 +142,7 @@ func (env *environment) start(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) env.weedCancel = cancel - cmd := exec.CommandContext(ctx, env.weedBinary, "mini", + miniArgs := append([]string{"mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -156,7 +156,9 @@ func (env *environment) start(t *testing.T) { "-ip", env.bindIP, "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.iceberg=0") + cmd := exec.CommandContext(ctx, env.weedBinary, miniArgs...) cmd.Dir = env.dataDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/catalog_lancedb/lancedb_catalog_test.go b/test/s3tables/catalog_lancedb/lancedb_catalog_test.go index 85a31861f6..96613937c0 100644 --- a/test/s3tables/catalog_lancedb/lancedb_catalog_test.go +++ b/test/s3tables/catalog_lancedb/lancedb_catalog_test.go @@ -137,7 +137,7 @@ func (env *environment) start(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) env.weedCancel = cancel - cmd := exec.CommandContext(ctx, env.weedBinary, "mini", + miniArgs := append([]string{"mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -151,7 +151,9 @@ func (env *environment) start(t *testing.T) { "-ip", env.bindIP, "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.iceberg=0") + cmd := exec.CommandContext(ctx, env.weedBinary, miniArgs...) cmd.Dir = env.dataDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/catalog_olake/olake_catalog_test.go b/test/s3tables/catalog_olake/olake_catalog_test.go index eafd815e11..bbed0c2a3d 100644 --- a/test/s3tables/catalog_olake/olake_catalog_test.go +++ b/test/s3tables/catalog_olake/olake_catalog_test.go @@ -275,7 +275,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { t.Fatalf("Failed to create IAM config: %v", err) } - cmd := exec.Command(env.weedBinary, "mini", + miniArgs := append([]string{"mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -292,7 +292,9 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { "-ip", env.bindIP, "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.lance=0") + cmd := exec.Command(env.weedBinary, miniArgs...) cmd.Dir = env.dataDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/catalog_risingwave/setup_test.go b/test/s3tables/catalog_risingwave/setup_test.go index b893c1d91a..155c390eed 100644 --- a/test/s3tables/catalog_risingwave/setup_test.go +++ b/test/s3tables/catalog_risingwave/setup_test.go @@ -113,7 +113,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { t.Fatalf("failed to create temp directory: %v", err) } - ports := testutil.MustFreeMiniPorts(t, []string{"Master", "Filer", "S3", "Iceberg"}) + ports := testutil.MustFreeMiniPorts(t, []string{"Master", "Filer", "S3", "Iceberg", "Admin"}) env.masterPort = ports[0] env.filerPort = ports[1] env.s3Port = ports[2] @@ -134,8 +134,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { env.logFile = logFile // Start SeaweedFS using weed mini (all-in-one including Iceberg REST) - env.masterProcess = exec.Command( - "weed", "mini", + miniArgs := append([]string{"mini", "-ip", env.bindIP, "-ip.bind", "0.0.0.0", "-master.port", fmt.Sprintf("%d", env.masterPort), @@ -144,7 +143,9 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { "-s3.port.iceberg", fmt.Sprintf("%d", env.icebergRestPort), "-s3.config", iamConfigPath, "-dir", env.seaweedfsDataDir, - ) + }, testutil.MiniAdminArgs(ports[4])...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.lance=0") + env.masterProcess = exec.Command("weed", miniArgs...) env.masterProcess.Stdout = logFile env.masterProcess.Stderr = logFile env.masterProcess.Env = append(os.Environ(), diff --git a/test/s3tables/catalog_spark/setup_test.go b/test/s3tables/catalog_spark/setup_test.go index 9091b201c8..7d64dfd6eb 100644 --- a/test/s3tables/catalog_spark/setup_test.go +++ b/test/s3tables/catalog_spark/setup_test.go @@ -90,7 +90,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { t.Fatalf("failed to create temp directory: %v", err) } - ports := testutil.MustFreeMiniPorts(t, []string{"Master", "Filer", "S3", "Iceberg"}) + ports := testutil.MustFreeMiniPorts(t, []string{"Master", "Filer", "S3", "Iceberg", "Admin"}) env.masterPort = ports[0] env.filerPort = ports[1] env.s3Port = ports[2] @@ -104,8 +104,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { } // Start SeaweedFS using weed mini (all-in-one including Iceberg REST) - env.masterProcess = exec.Command( - "weed", "mini", + miniArgs := append([]string{"mini", "-ip", bindIP, "-ip.bind", "0.0.0.0", "-master.port", fmt.Sprintf("%d", env.masterPort), @@ -114,7 +113,9 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { "-s3.port.iceberg", fmt.Sprintf("%d", env.icebergRestPort), "-s3.config", iamConfigPath, "-dir", env.seaweedfsDataDir, - ) + }, testutil.MiniAdminArgs(ports[4])...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.lance=0") + env.masterProcess = exec.Command("weed", miniArgs...) env.masterProcess.Env = append(os.Environ(), "AWS_ACCESS_KEY_ID="+env.accessKey, "AWS_SECRET_ACCESS_KEY="+env.secretKey, diff --git a/test/s3tables/catalog_spark_lance/spark_lance_test.go b/test/s3tables/catalog_spark_lance/spark_lance_test.go index d5d808096d..5bf1a0359f 100644 --- a/test/s3tables/catalog_spark_lance/spark_lance_test.go +++ b/test/s3tables/catalog_spark_lance/spark_lance_test.go @@ -137,7 +137,7 @@ func (env *environment) start(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) env.weedCancel = cancel - cmd := exec.CommandContext(ctx, env.weedBinary, "mini", + miniArgs := append([]string{"mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -151,7 +151,9 @@ func (env *environment) start(t *testing.T) { "-ip", env.bindIP, "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.iceberg=0") + cmd := exec.CommandContext(ctx, env.weedBinary, miniArgs...) cmd.Dir = env.dataDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/catalog_trino/trino_catalog_test.go b/test/s3tables/catalog_trino/trino_catalog_test.go index 7645dd2a8a..ddfc60fdeb 100644 --- a/test/s3tables/catalog_trino/trino_catalog_test.go +++ b/test/s3tables/catalog_trino/trino_catalog_test.go @@ -256,7 +256,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) env.weedCancel = cancel - cmd := exec.CommandContext(ctx, env.weedBinary, "mini", + miniArgs := append([]string{"mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -270,7 +270,9 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { "-ip", env.bindIP, "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.lance=0") + cmd := exec.CommandContext(ctx, env.weedBinary, miniArgs...) cmd.Dir = env.dataDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/lakekeeper/lakekeeper_test.go b/test/s3tables/lakekeeper/lakekeeper_test.go index 7076cf187a..d3a23c76c4 100644 --- a/test/s3tables/lakekeeper/lakekeeper_test.go +++ b/test/s3tables/lakekeeper/lakekeeper_test.go @@ -205,7 +205,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { env.weedCancel = cancel // Start weed mini with both S3 config (standard IAM) and IAM config (advanced IAM/STS) - cmd := exec.CommandContext(ctx, env.weedBinary, "-v", "4", "mini", + miniArgs := append([]string{"-v", "4", "mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -220,7 +220,9 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { "-ip", env.bindIP, "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.lance=0", "-s3.port.iceberg=0") + cmd := exec.CommandContext(ctx, env.weedBinary, miniArgs...) cmd.Dir = env.dataDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/lifecycle/cluster_test.go b/test/s3tables/lifecycle/cluster_test.go index 2ab04812e3..ce5037f6b5 100644 --- a/test/s3tables/lifecycle/cluster_test.go +++ b/test/s3tables/lifecycle/cluster_test.go @@ -99,6 +99,7 @@ type environment struct { s3GrpcPort int icebergPort int lancePort int + adminPort int weedCancel context.CancelFunc weedCmd *exec.Cmd @@ -138,6 +139,10 @@ func newEnvironment() (*environment, error) { if err != nil { return nil, fmt.Errorf("allocate ports: %w", err) } + adminPorts, err := testutil.AllocateMiniPorts(1) + if err != nil { + return nil, fmt.Errorf("allocate admin port: %w", err) + } return &environment{ weedBinary: weedBinary, rootDir: seaweedDir, @@ -153,6 +158,7 @@ func newEnvironment() (*environment, error) { s3GrpcPort: ports[7], icebergPort: ports[8], lancePort: ports[9], + adminPort: adminPorts[0], }, nil } @@ -166,7 +172,7 @@ func (env *environment) start() error { ctx, cancel := context.WithCancel(context.Background()) env.weedCancel = cancel - cmd := exec.CommandContext(ctx, env.weedBinary, "mini", + miniArgs := append([]string{"mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -180,7 +186,9 @@ func (env *environment) start() error { "-s3.config", iamConfigPath, "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(env.adminPort)...) + miniArgs = append(miniArgs, "-webdav=false") + cmd := exec.CommandContext(ctx, env.weedBinary, miniArgs...) cmd.Dir = env.dataDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/maintenance/maintenance_integration_test.go b/test/s3tables/maintenance/maintenance_integration_test.go index 4a5b763497..a92ef92657 100644 --- a/test/s3tables/maintenance/maintenance_integration_test.go +++ b/test/s3tables/maintenance/maintenance_integration_test.go @@ -92,7 +92,11 @@ func TestMain(m *testing.M) { } func startCluster(testDir string, extraArgs []string) (*testCluster, error) { - ports, err := testutil.AllocatePorts(10) + ports, err := testutil.AllocatePorts(9) + if err != nil { + return nil, err + } + adminPorts, err := testutil.AllocateMiniPorts(1) if err != nil { return nil, err } @@ -100,7 +104,8 @@ func startCluster(testDir string, extraArgs []string) (*testCluster, error) { volumePort, volumeGrpc := ports[2], ports[3] filerPort, filerGrpc := ports[4], ports[5] s3Port, s3Grpc := ports[6], ports[7] - adminPort, adminGrpc := ports[8], ports[9] + adminPort := adminPorts[0] + icebergPort := ports[8] _ = os.Remove(filepath.Join(testDir, "mini.options")) @@ -146,15 +151,16 @@ func startCluster(testDir string, extraArgs []string) (*testCluster, error) { "-filer.port.grpc=" + strconv.Itoa(filerGrpc), "-s3.port=" + strconv.Itoa(s3Port), "-s3.port.grpc=" + strconv.Itoa(s3Grpc), - "-admin.port=" + strconv.Itoa(adminPort), - "-admin.port.grpc=" + strconv.Itoa(adminGrpc), - "-webdav.port=0", + "-webdav=false", // Disable WebDAV + "-s3.port.lance=0", // Disable Lance + "-s3.port.iceberg=" + strconv.Itoa(icebergPort), "-admin.ui=false", "-master.volumeSizeLimitMB=32", "-ip=127.0.0.1", "-master.peers=none", "-s3.iam.readOnly=false", } + args = append(args, testutil.MiniAdminArgs(adminPort)...) args = append(args, extraArgs...) os.Args = append([]string{"weed"}, args...) glog.MaxSize = 1024 * 1024 diff --git a/test/s3tables/polaris/polaris_env_test.go b/test/s3tables/polaris/polaris_env_test.go index fe286e18ab..8a0c58a505 100644 --- a/test/s3tables/polaris/polaris_env_test.go +++ b/test/s3tables/polaris/polaris_env_test.go @@ -182,7 +182,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) env.weedCancel = cancel - cmd := exec.CommandContext(ctx, env.weedBinary, "-v", "4", "mini", + miniArgs := append([]string{"-v", "4", "mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -197,7 +197,9 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { "-ip", env.bindIP, "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.lance=0", "-s3.port.iceberg=0") + cmd := exec.CommandContext(ctx, env.weedBinary, miniArgs...) cmd.Dir = env.dataDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/sts_integration/sts_integration_test.go b/test/s3tables/sts_integration/sts_integration_test.go index 672043cab3..524713fe47 100644 --- a/test/s3tables/sts_integration/sts_integration_test.go +++ b/test/s3tables/sts_integration/sts_integration_test.go @@ -242,7 +242,7 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) env.weedCancel = cancel - cmd := exec.CommandContext(ctx, env.weedBinary, "mini", + miniArgs := append([]string{"mini", "-master.port", fmt.Sprintf("%d", env.masterPort), "-master.port.grpc", fmt.Sprintf("%d", env.masterGrpcPort), "-volume.port", fmt.Sprintf("%d", env.volumePort), @@ -257,7 +257,9 @@ func (env *TestEnvironment) StartSeaweedFS(t *testing.T) { "-ip", env.bindIP, "-ip.bind", "0.0.0.0", "-dir", env.dataDir, - ) + }, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + miniArgs = append(miniArgs, "-webdav=false", "-s3.port.lance=0", "-s3.port.iceberg=0") + cmd := exec.CommandContext(ctx, env.weedBinary, miniArgs...) cmd.Dir = env.dataDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/s3tables/table-buckets/s3tables_integration_test.go b/test/s3tables/table-buckets/s3tables_integration_test.go index 80b711e478..c99d6d4393 100644 --- a/test/s3tables/table-buckets/s3tables_integration_test.go +++ b/test/s3tables/table-buckets/s3tables_integration_test.go @@ -594,11 +594,16 @@ func testTargetOperations(t *testing.T, client *S3TablesClient) { // directory. It does not require a *testing.T so it can be called from TestMain. // extraArgs are appended to the default mini command flags. func startMiniClusterInDir(testDir string, extraArgs []string) (*TestCluster, error) { - // We need 10 unique ports: Master(2), Volume(2), Filer(2), S3(2), Admin(2) - ports, err := testutil.AllocatePorts(10) + // We need 9 unique ports: Master(2), Volume(2), Filer(2), S3(2), Iceberg(1); + // the admin pair comes from the mini-safe range. + ports, err := testutil.AllocatePorts(9) if err != nil { return nil, fmt.Errorf("failed to find available ports: %v", err) } + adminPorts, err := testutil.AllocateMiniPorts(1) + if err != nil { + return nil, fmt.Errorf("failed to allocate admin port: %v", err) + } masterPort := ports[0] masterGrpcPort := ports[1] @@ -608,8 +613,8 @@ func startMiniClusterInDir(testDir string, extraArgs []string) (*TestCluster, er filerGrpcPort := ports[5] s3Port := ports[6] s3GrpcPort := ports[7] - adminPort := ports[8] - adminGrpcPort := ports[9] + adminPort := adminPorts[0] + icebergPort := ports[8] // Ensure no configuration file from previous runs configFile := filepath.Join(testDir, "mini.options") @@ -674,15 +679,16 @@ func startMiniClusterInDir(testDir string, extraArgs []string) (*TestCluster, er "-filer.port.grpc=" + strconv.Itoa(filerGrpcPort), "-s3.port=" + strconv.Itoa(s3Port), "-s3.port.grpc=" + strconv.Itoa(s3GrpcPort), - "-admin.port=" + strconv.Itoa(adminPort), - "-admin.port.grpc=" + strconv.Itoa(adminGrpcPort), - "-webdav.port=0", // Disable WebDAV + "-webdav=false", // Disable WebDAV + "-s3.port.lance=0", // Disable Lance + "-s3.port.iceberg=" + strconv.Itoa(icebergPort), "-admin.ui=false", // Disable admin UI "-master.volumeSizeLimitMB=32", // Small volumes for testing "-ip=127.0.0.1", "-master.peers=none", // Faster startup "-s3.iam.readOnly=false", // Enable IAM write operations for tests } + baseArgs = append(baseArgs, testutil.MiniAdminArgs(adminPort)...) if len(extraArgs) > 0 { baseArgs = append(baseArgs, extraArgs...) } diff --git a/test/s3tables/unity_catalog/setup_test.go b/test/s3tables/unity_catalog/setup_test.go index b56044cb40..3309aff254 100644 --- a/test/s3tables/unity_catalog/setup_test.go +++ b/test/s3tables/unity_catalog/setup_test.go @@ -183,6 +183,8 @@ func (env *testEnv) startSeaweedFS(t *testing.T, iamJSON string) { if enableSTS { weedArgs = append(weedArgs, "-s3.iam.config", iamConfigPath, "-s3.iam.readOnly=false") } + weedArgs = append(weedArgs, testutil.MiniAdminArgs(testutil.MustFreeMiniPort(t, "admin"))...) + weedArgs = append(weedArgs, "-webdav=false", "-s3.port.lance=0", "-s3.port.iceberg=0") cmd := exec.CommandContext(ctx, env.weedBinary, weedArgs...) cmd.Dir = env.dataDir diff --git a/test/testutil/ports.go b/test/testutil/ports.go index 0950cf5209..5a1ce76d46 100644 --- a/test/testutil/ports.go +++ b/test/testutil/ports.go @@ -167,6 +167,22 @@ func MustFreeMiniPort(t *testing.T, name string) int { return MustFreeMiniPorts(t, []string{name})[0] } +// MiniAdminArgs returns weed mini flags pinning the admin server to +// adminPort and adminPort+GrpcPortOffset and disabling the legacy compat +// listener. Unconfigured minis all bind the fixed default admin port 12535 +// and the legacy port 23646 (+33646 gRPC), so sequential or concurrent +// minis on one host collide on them. Allocate adminPort with +// MustFreeMiniPort(s) — the admin binds late in mini startup, after the +// cluster's own outbound connections may steal an ephemeral port, so it +// must stay below the Linux ephemeral port floor. +func MiniAdminArgs(adminPort int) []string { + return []string{ + fmt.Sprintf("-admin.port=%d", adminPort), + fmt.Sprintf("-admin.port.grpc=%d", adminPort+GrpcPortOffset), + "-admin.port.legacy=0", + } +} + // AllocatePortSet atomically allocates miniCount master-style port pairs (each // with port and port+GrpcPortOffset reserved) plus regularCount additional // distinct ports. All listeners are held open until the entire batch is diff --git a/test/volume_server/grpc/fetch_remote_s3_test.go b/test/volume_server/grpc/fetch_remote_s3_test.go index d3c9aa673e..856b712357 100644 --- a/test/volume_server/grpc/fetch_remote_s3_test.go +++ b/test/volume_server/grpc/fetch_remote_s3_test.go @@ -37,23 +37,28 @@ func startWeedMini(t *testing.T) (s3Endpoint string, cleanup func()) { } } - miniPorts := testutil.MustFreeMiniPorts(t, []string{"Master", "Volume", "Filer", "S3"}) + miniPorts := testutil.MustFreeMiniPorts(t, []string{"Master", "Volume", "Filer", "S3", "Admin"}) miniMasterPort := miniPorts[0] miniVolumePort := miniPorts[1] miniFilerPort := miniPorts[2] miniS3Port := miniPorts[3] + miniAdminPort := miniPorts[4] miniDir := t.TempDir() os.WriteFile(filepath.Join(miniDir, "security.toml"), []byte("# empty\n"), 0644) ctx, cancel := context.WithCancel(context.Background()) - miniCmd := exec.CommandContext(ctx, weedBin, "mini", + miniArgs := append([]string{"mini", fmt.Sprintf("-dir=%s", miniDir), fmt.Sprintf("-master.port=%d", miniMasterPort), fmt.Sprintf("-volume.port=%d", miniVolumePort), fmt.Sprintf("-filer.port=%d", miniFilerPort), fmt.Sprintf("-s3.port=%d", miniS3Port), - ) + "-webdav=false", + "-s3.port.lance=0", + "-s3.port.iceberg=0", + }, testutil.MiniAdminArgs(miniAdminPort)...) + miniCmd := exec.CommandContext(ctx, weedBin, miniArgs...) miniCmd.Env = append(os.Environ(), "AWS_ACCESS_KEY_ID=admin", "AWS_SECRET_ACCESS_KEY=admin") miniCmd.Dir = miniDir logFile, _ := os.CreateTemp("", "weed-mini-*.log")