Files
seaweedfs/weed/s3api/s3api_server_advertise_test.go
Chris LuandGitHub 4149346bb7 s3: register the advertised ip with the master (#10482)
* s3: register the advertised ip with the master

The cluster address came from the bind ip, falling back to the
auto-detected interface, so -ip never reached the S3 registration.
weed mini -ip=localhost binds the wildcard and ended up registering
whatever interface happened to sort first -- on a host with VPN
interfaces, an address that stops routing once the tunnel drops.

IAM changes are pushed to registered S3 servers over gRPC, so every
mutation then blocked the full 10s propagation deadline before logging
a failure, and cluster.ps and the admin UI listed a node nothing could
reach. Identities still arrived through the /etc/iam metadata
subscription, so this cost latency and visibility, not credentials.

Add an advertise ip to the gateway option, preferring it over the bind
address, and wire the parent -ip through server, filer and mini.

* s3: treat any unspecified bind address as a wildcard

net.ParseIP + IsUnspecified covers ::, [::] and the expanded IPv6 forms
instead of only the 0.0.0.0 literal, so an IPv6 wildcard bind no longer
registers an address peers cannot dial. Host names parse as nil and stay
addresses in their own right. Apply the same guard to the advertised ip.
2026-07-29 10:30:46 -07:00

38 lines
1.3 KiB
Go

package s3api
import (
"testing"
"github.com/seaweedfs/seaweedfs/weed/util"
)
func TestAdvertisedHost(t *testing.T) {
detected := util.DetectedHostAddress()
for _, tc := range []struct {
name string
ip string
bindIp string
want string
}{
{"advertised ip wins over wildcard bind", "localhost", "0.0.0.0", "localhost"},
{"advertised ip wins over specific bind", "s3.example.com", "10.0.0.5", "s3.example.com"},
{"bind ip used when no advertised ip", "", "10.0.0.5", "10.0.0.5"},
{"ipv6 bind ip used when no advertised ip", "", "2001:db8::1", "2001:db8::1"},
{"wildcard bind falls back to detected", "", "0.0.0.0", detected},
{"ipv6 wildcard bind falls back to detected", "", "::", detected},
{"bracketed ipv6 wildcard bind falls back to detected", "", "[::]", detected},
{"expanded ipv6 wildcard bind falls back to detected", "", "0:0:0:0:0:0:0:0", detected},
{"wildcard advertised ip falls back to bind ip", "0.0.0.0", "10.0.0.5", "10.0.0.5"},
{"wildcard advertised ip and bind fall back to detected", "::", "0.0.0.0", detected},
{"empty falls back to detected", "", "", detected},
} {
t.Run(tc.name, func(t *testing.T) {
option := &S3ApiServerOption{Ip: tc.ip, BindIp: tc.bindIp}
if got := option.advertisedHost(); got != tc.want {
t.Errorf("advertisedHost() = %q, want %q", got, tc.want)
}
})
}
}