Fix SCUM RCON runtime profile resolution

This commit is contained in:
npc0-hue
2026-08-24 14:13:59 +08:00
parent 3e00737267
commit d6ee482957
2 changed files with 122 additions and 18 deletions
+71 -6
View File
@@ -126,6 +126,65 @@ func TestSourceRCONDispatchCanonicalizesLegacyLocalBinding(t *testing.T) {
}
}
func TestSourceRCONDispatchSelectsDeclaredProfileWithoutManualBinding(t *testing.T) {
svc, session, _, instance := newSourceRCONFixtureWithRuntimeBinding(t, false)
plugin, err := svc.store.GamePlugins().Get(instance.PluginID)
if err != nil {
t.Fatal(err)
}
plugin.RuntimeProfiles.LifecycleProfiles[0].Key = "run-local"
if err := svc.store.GamePlugins().Update(plugin); err != nil {
t.Fatalf("update source RCON profile key: %v", err)
}
dispatch, err := svc.DispatchSourceRCONCommandForSession(session, domain.SourceRCONCommandRequest{ServerInstanceID: instance.ID, Kind: domain.SourceRCONCommandKindCommand, Command: "#ListPlayers", IdempotencyKey: "rcon-without-binding"})
if err != nil {
t.Fatalf("dispatch RCON without manual binding: %v", err)
}
job, err := svc.store.Jobs().Get(dispatch.JobID)
if err != nil {
t.Fatalf("get RCON job: %v", err)
}
if job.ExecutionInput.WorkspaceScope != "run-local" || job.TargetKey != "rcon" || job.ExecutionInput.SourceRCON == nil {
t.Fatalf("expected declared source RCON profile to drive job, got %+v", job)
}
}
func TestSourceRCONDispatchFallsBackFromCustomClientBinding(t *testing.T) {
svc, session, _, instance := newSourceRCONFixture(t)
plugin, err := svc.store.GamePlugins().Get(instance.PluginID)
if err != nil {
t.Fatal(err)
}
plugin.RuntimeProfiles.LifecycleProfiles[0].Key = "run-local"
plugin.RuntimeProfiles.LifecycleProfiles = append(plugin.RuntimeProfiles.LifecycleProfiles, domain.RuntimeLifecycleProfile{Key: "scum-client", Mode: "custom-client", Capabilities: []string{"client-manager.deploy", "client-manager.control", "logs.read"}, ClientManagerRef: "scum-client-manager", Platforms: []string{"windows"}})
if err := svc.store.GamePlugins().Update(plugin); err != nil {
t.Fatalf("update plugin profiles: %v", err)
}
binding, err := svc.store.RuntimeBindings().Get("runtime-binding-" + instance.ID)
if err != nil {
t.Fatalf("get runtime binding: %v", err)
}
binding.ProfileKey = "scum-client"
binding.Mode = "custom-client"
binding.Bindings = map[string]string{"scum-client-manager": "runtime-client-manager"}
if err := svc.store.RuntimeBindings().Update(binding); err != nil {
t.Fatalf("point binding at custom client profile: %v", err)
}
dispatch, err := svc.DispatchSourceRCONCommandForSession(session, domain.SourceRCONCommandRequest{ServerInstanceID: instance.ID, Kind: domain.SourceRCONCommandKindCommand, Command: "#ListPlayers", IdempotencyKey: "rcon-custom-client-binding"})
if err != nil {
t.Fatalf("dispatch RCON with custom-client binding fallback: %v", err)
}
job, err := svc.store.Jobs().Get(dispatch.JobID)
if err != nil {
t.Fatalf("get RCON job: %v", err)
}
if job.ExecutionInput.WorkspaceScope != "run-local" || job.TargetKey != "rcon" || job.ExecutionInput.RemoteAdapterKey != "rcon" {
t.Fatalf("expected source RCON to use run-local despite custom-client binding, got %+v", job)
}
}
func TestSourceRCONBrokerExpiresWithoutReplay(t *testing.T) {
stamp := fixedTime
broker := newSourceRCONCommandBroker(func() time.Time { return stamp })
@@ -139,6 +198,10 @@ func TestSourceRCONBrokerExpiresWithoutReplay(t *testing.T) {
}
func newSourceRCONFixture(t *testing.T) (*CoreService, string, string, domain.ServerInstance) {
return newSourceRCONFixtureWithRuntimeBinding(t, true)
}
func newSourceRCONFixtureWithRuntimeBinding(t *testing.T, createBinding bool) (*CoreService, string, string, domain.ServerInstance) {
t.Helper()
svc := newCoreService(repo.NewMemoryStore(), func() time.Time { return fixedTime })
capability := domain.JobCapabilityRemoteRunRCONCommand
@@ -177,12 +240,14 @@ func newSourceRCONFixture(t *testing.T) (*CoreService, string, string, domain.Se
if err != nil {
t.Fatalf("create RCON server: %v", err)
}
binding, err := svc.buildRuntimeBinding(instance, plugin, domain.RuntimeBindingUpdate{ProfileKey: "local", Bindings: map[string]string{"rcon": "runtime-rcon"}}, true)
if err != nil {
t.Fatalf("create RCON binding: %v", err)
}
if err := svc.store.RuntimeBindings().Create(binding); err != nil {
t.Fatalf("store RCON binding: %v", err)
if createBinding {
binding, err := svc.buildRuntimeBinding(instance, plugin, domain.RuntimeBindingUpdate{ProfileKey: "local", Bindings: map[string]string{"rcon": "runtime-rcon"}}, true)
if err != nil {
t.Fatalf("create RCON binding: %v", err)
}
if err := svc.store.RuntimeBindings().Create(binding); err != nil {
t.Fatalf("store RCON binding: %v", err)
}
}
helloRequest := validRunControlHello()
helloRequest.CapabilityReport.Capabilities = []string{capability}