fix(admin): carry filer addresses as ServerAddress in plugin cluster context (#9600)

The plugin cluster context forwarded filers as gRPC-only addresses
(host:grpcPort). The admin-script worker stored that in
ShellOptions.FilerAddress, whose shell commands re-derive the gRPC port
via ToGrpcAddress() and re-add the +10000 offset, dialing a non-existent
host:28888.

Carry filers in pb.ServerAddress form (host:httpPort.grpcPort) and let
each consumer convert when it dials: the admin shell uses it verbatim,
while the s3_lifecycle and iceberg workers collapse it to a gRPC address.
Rename the proto field filer_grpc_addresses -> filer_addresses so the
name matches the content.
This commit is contained in:
Chris Lu
2026-05-21 02:10:27 -07:00
committed by GitHub
parent 303c2be38d
commit 87fdea5330
10 changed files with 110 additions and 56 deletions
+28 -13
View File
@@ -19,9 +19,9 @@ import (
)
const (
adminScriptJobType = "admin_script"
maxAdminScriptOutputBytes = 16 * 1024
defaultAdminScriptRunMins = 17
adminScriptJobType = "admin_script"
maxAdminScriptOutputBytes = 16 * 1024
defaultAdminScriptRunMins = 17
adminScriptDetectTickMinutes = 17
)
@@ -546,13 +546,31 @@ func (h *AdminScriptHandler) buildAdminScriptCommandEnv(
ctx context.Context,
clusterContext *plugin_pb.ClusterContext,
) (*shell.CommandEnv, context.CancelFunc, error) {
options, err := h.buildAdminScriptShellOptions(clusterContext)
if err != nil {
return nil, nil, err
}
commandEnv := shell.NewCommandEnv(&options)
commandEnv.ForceNoLock()
ctx, cancel := context.WithCancel(ctx)
go commandEnv.MasterClient.KeepConnectedToMaster(ctx)
return commandEnv, cancel, nil
}
// buildAdminScriptShellOptions maps a cluster context onto shell.ShellOptions.
// It is split out from buildAdminScriptCommandEnv so the address handling is
// testable without standing up a master client.
func (h *AdminScriptHandler) buildAdminScriptShellOptions(clusterContext *plugin_pb.ClusterContext) (shell.ShellOptions, error) {
if clusterContext == nil {
return nil, nil, fmt.Errorf("cluster context is required")
return shell.ShellOptions{}, fmt.Errorf("cluster context is required")
}
masters := normalizeAddressList(clusterContext.MasterGrpcAddresses)
if len(masters) == 0 {
return nil, nil, fmt.Errorf("missing master addresses for admin script")
return shell.ShellOptions{}, fmt.Errorf("missing master addresses for admin script")
}
filerGroup := ""
@@ -564,20 +582,17 @@ func (h *AdminScriptHandler) buildAdminScriptCommandEnv(
Directory: "/",
}
filers := normalizeAddressList(clusterContext.FilerGrpcAddresses)
// FilerAddresses are pb.ServerAddress strings (host:httpPort.grpcPort).
// ShellOptions.FilerAddress is itself a ServerAddress; shell commands derive
// the gRPC or HTTP port from it as needed, so store it verbatim.
filers := normalizeAddressList(clusterContext.FilerAddresses)
if len(filers) > 0 {
options.FilerAddress = pb.ServerAddress(filers[0])
} else {
glog.V(1).Infof("admin script worker missing filer address; filer-dependent commands may fail")
}
commandEnv := shell.NewCommandEnv(&options)
commandEnv.ForceNoLock()
ctx, cancel := context.WithCancel(ctx)
go commandEnv.MasterClient.KeepConnectedToMaster(ctx)
return commandEnv, cancel, nil
return options, nil
}
func normalizeAddressList(addresses []string) []string {
@@ -10,6 +10,36 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
)
func TestAdminScriptFilerAddressKeepsGrpcPortOffConvention(t *testing.T) {
// FilerAddresses arrive as pb.ServerAddress (host:httpPort.grpcPort). The
// shell derives the gRPC port from FilerAddress via ToGrpcAddress(); it must
// land on the real gRPC port even when that port is off the httpPort+10000
// convention, not double the offset into a non-existent filer:28890.
h := NewAdminScriptHandler(nil)
options, err := h.buildAdminScriptShellOptions(&plugin_pb.ClusterContext{
MasterGrpcAddresses: []string{"master:19333"},
FilerAddresses: []string{"filer:8888.18890"},
})
if err != nil {
t.Fatalf("buildAdminScriptShellOptions returned err = %v", err)
}
if grpc := options.FilerAddress.ToGrpcAddress(); grpc != "filer:18890" {
t.Fatalf("filer gRPC address = %q, want filer:18890 (not filer:28890)", grpc)
}
if http := options.FilerAddress.ToHttpAddress(); http != "filer:8888" {
t.Fatalf("filer HTTP address = %q, want filer:8888", http)
}
}
func TestAdminScriptShellOptionsRequireMasters(t *testing.T) {
h := NewAdminScriptHandler(nil)
if _, err := h.buildAdminScriptShellOptions(&plugin_pb.ClusterContext{
FilerAddresses: []string{"filer:8888.18890"},
}); err == nil {
t.Fatalf("expected error when master addresses are missing")
}
}
func TestAdminScriptDescriptorDefaults(t *testing.T) {
descriptor := NewAdminScriptHandler(nil).Descriptor()
if descriptor == nil {