Fix run package profile and log ingestion
This commit is contained in:
@@ -234,6 +234,7 @@ func (svc *CoreService) runDistributionPackageContext(distribution domain.RunDis
|
||||
} else if !errors.Is(bindingErr, repo.ErrNotFound) {
|
||||
return runDistributionPackageContext{}, bindingErr
|
||||
}
|
||||
profileKey = defaultRunDistributionProfileKey(plugin, profileKey)
|
||||
plan, err := runAutonomousLifecyclePlan(distribution, instance, plugin, profileKey, bindings)
|
||||
if err != nil {
|
||||
return runDistributionPackageContext{}, err
|
||||
@@ -245,6 +246,20 @@ func (svc *CoreService) runDistributionPackageContext(distribution domain.RunDis
|
||||
return runDistributionPackageContext{profileKey: profileKey, workspaceSeed: seed, autonomousLifecycle: plan}, nil
|
||||
}
|
||||
|
||||
func defaultRunDistributionProfileKey(plugin domain.GamePlugin, profileKey string) string {
|
||||
profileKey = strings.TrimSpace(profileKey)
|
||||
if profileKey != "" {
|
||||
if profile, ok := runtimeLifecycleProfileForKey(plugin.RuntimeProfiles, profileKey); ok {
|
||||
return profile.Key
|
||||
}
|
||||
return profileKey
|
||||
}
|
||||
if len(plugin.RuntimeProfiles.LifecycleProfiles) == 0 {
|
||||
return ""
|
||||
}
|
||||
return plugin.RuntimeProfiles.LifecycleProfiles[0].Key
|
||||
}
|
||||
|
||||
func runAutonomousLifecyclePlan(distribution domain.RunDistribution, instance domain.ServerInstance, plugin domain.GamePlugin, profileKey string, bindings map[string]string) (*domain.RunAutonomousLifecyclePlan, error) {
|
||||
plan := &domain.RunAutonomousLifecyclePlan{
|
||||
SchemaVersion: "1",
|
||||
|
||||
@@ -214,6 +214,55 @@ func hasAutonomousLogSource(sources []domain.RunAutonomousLogSource, kind string
|
||||
return false
|
||||
}
|
||||
|
||||
func TestCoreServiceRunDistributionDefaultsEmptyDeploymentProfileToPluginLifecycleProfile(t *testing.T) {
|
||||
svc := newTestCoreService()
|
||||
plugin := scumDeploymentTestPlugin()
|
||||
plugin.Name = "SCUM"
|
||||
plugin.Version = "0.1.1"
|
||||
plugin.ServerType = "scum"
|
||||
plugin.Status = domain.GamePluginStatusInstalled
|
||||
plugin.SupportedOS = []string{"windows"}
|
||||
plugin.DeclaredPermissions = []string{"server.run.distribution"}
|
||||
plugin.LifecycleActions = domain.PluginLifecycleActions{Install: "actions/install.json", Start: "actions/start.json", Stop: "actions/stop.json", Status: "actions/status.json"}
|
||||
plugin.RuntimeProfiles.LifecycleProfiles = []domain.RuntimeLifecycleProfile{{Key: "run-local", Mode: "local-process", Capabilities: []string{domain.LifecycleCapabilityInstall, domain.LifecycleCapabilityStart, domain.LifecycleCapabilityStop, domain.LifecycleCapabilityStatus}, ActionRefs: domain.PluginLifecycleActions{Install: "actions/install.json", Start: "actions/start.json", Stop: "actions/stop.json", Status: "actions/status.json"}, Platforms: []string{"windows"}}}
|
||||
requireManualSCUMRuntimeBindings(&plugin, "run-local")
|
||||
if err := svc.store.GamePlugins().Create(plugin); err != nil {
|
||||
t.Fatalf("create SCUM plugin: %v", err)
|
||||
}
|
||||
session := createServiceUserAndLogin(t, svc, domain.User{ID: "scum-default-profile-owner", DisplayName: "SCUM Default Profile Owner", Email: "scum-default-profile@example.test", Roles: []string{"server-owner"}, PasswordHash: "secret-password"})
|
||||
created, err := svc.CreateServerInstanceWorkflowForSession(session, domain.ServerLifecycleCreate{
|
||||
ID: "scum-default-profile-package", PluginID: plugin.ID, Name: "SCUM Default Profile Package", IdempotencyKey: "scum-default-profile-package-create",
|
||||
Deployment: domain.ServerDeploymentDefinition{Mode: domain.ServerDeploymentModeGuided, ServerRoot: `D:\scum-default-profile`, CreateInputs: map[string]string{"serverName": "Moon", "gamePort": "27000", "queryPort": "27015", "maxPlayers": "128"}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("create SCUM guided draft without explicit profile: %v", err)
|
||||
}
|
||||
if created.Instance.Deployment.ProfileKey != "run-local" {
|
||||
t.Fatalf("expected create defaults to persist plugin lifecycle profile, got %+v", created.Instance.Deployment)
|
||||
}
|
||||
|
||||
legacy := created.Instance
|
||||
legacy.Deployment.ProfileKey = ""
|
||||
if err := svc.store.ServerInstances().Update(legacy); err != nil {
|
||||
t.Fatalf("simulate legacy empty deployment profile: %v", err)
|
||||
}
|
||||
inputs := make(chan domain.DistributionBuildInput, 1)
|
||||
svc.ConfigureDistributionBuilder(captureDistributionBuilder{inputs: inputs, payload: []byte("profile-default-build")})
|
||||
if _, err := svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{ServerInstanceID: legacy.ID, TargetOS: "windows", TargetArch: "amd64", IdempotencyKey: "scum-default-profile-package"}); err != nil {
|
||||
t.Fatalf("generate Run distribution with empty deployment profile: %v", err)
|
||||
}
|
||||
var platformInput domain.DistributionBuildInput
|
||||
select {
|
||||
case platformInput = <-inputs:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("platform builder did not receive profile-defaulted input")
|
||||
}
|
||||
plan := platformInput.AutonomousLifecycle
|
||||
if platformInput.ProfileKey != "run-local" || plan == nil || plan.ProfileKey != "run-local" || plan.Deployment == nil || plan.Deployment.ProfileKey != "run-local" {
|
||||
t.Fatalf("expected package context to default empty deployment profile to run-local, input=%+v plan=%+v", platformInput, plan)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreServiceBuildsWithoutRegisteredDistributionWorker(t *testing.T) {
|
||||
svc, session, instance := newDistributionTestFixture(t)
|
||||
bootstrapEndpoint, err := svc.store.RunEndpoints().Get(instance.RunEndpointID)
|
||||
|
||||
@@ -150,7 +150,7 @@ func (svc *CoreService) ensureRunLogStreamForBatch(batch domain.LogBatchIngest,
|
||||
expectedStreamID = runSessionLogStreamID(batch.RunEndpointID, batch.ServerInstanceID, batch.LogSessionID, batch.StreamKey)
|
||||
}
|
||||
if batch.LogStreamID != expectedStreamID {
|
||||
if !legacyAutonomousLogStream(batch) {
|
||||
if !legacySessionRunLogStream(batch) && !legacyAutonomousLogStream(batch) {
|
||||
return repo.ErrNotFound
|
||||
}
|
||||
}
|
||||
@@ -168,6 +168,10 @@ func (svc *CoreService) ensureRunLogStreamForBatch(batch domain.LogBatchIngest,
|
||||
return err
|
||||
}
|
||||
|
||||
func legacySessionRunLogStream(batch domain.LogBatchIngest) bool {
|
||||
return batch.LogSessionID != "" && batch.LogStreamID == runLogStreamID(batch.RunEndpointID, batch.ServerInstanceID, batch.StreamKey)
|
||||
}
|
||||
|
||||
func legacyAutonomousLogStream(batch domain.LogBatchIngest) bool {
|
||||
jobID, ok := jobIDFromLogBatch(batch)
|
||||
return ok && strings.HasPrefix(jobID, "autonomous-")
|
||||
|
||||
@@ -463,6 +463,28 @@ func TestCoreServiceAcceptsSessionMetadataOnLegacyAutonomousStreamID(t *testing.
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreServiceAcceptsSessionMetadataOnLegacyRunStreamID(t *testing.T) {
|
||||
svc, sessionToken := newRegisteredLogIngestService(t)
|
||||
batch := validLogBatch(t, sessionToken, 1, 1)
|
||||
batch.LogStreamID = runLogStreamID("run-local", "server-1", "stdout")
|
||||
batch.LogSessionID = "session-a"
|
||||
batch.SessionStartedAt = time.Date(2026, 7, 3, 12, 30, 0, 0, time.UTC)
|
||||
ack, err := svc.IngestLogBatch(batch)
|
||||
if err != nil {
|
||||
t.Fatalf("ingest session-scoped legacy run stream: %v", err)
|
||||
}
|
||||
if !ack.Accepted || ack.LogStreamID != batch.LogStreamID || ack.LatestSeq != batch.LastSeq {
|
||||
t.Fatalf("unexpected legacy run session ack: %+v", ack)
|
||||
}
|
||||
stream, err := svc.GetLogStream(batch.LogStreamID)
|
||||
if err != nil {
|
||||
t.Fatalf("get session-scoped legacy run stream: %v", err)
|
||||
}
|
||||
if stream.LogSessionID != batch.LogSessionID || !stream.SessionStartedAt.Equal(batch.SessionStartedAt) {
|
||||
t.Fatalf("session metadata was not persisted: %+v", stream)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreServiceRejectsOutOfOrderAndConflictingLogBatches(t *testing.T) {
|
||||
svc, sessionToken := newRegisteredLogIngestService(t)
|
||||
createLogStreamFixture(t, svc)
|
||||
|
||||
@@ -57,7 +57,9 @@ func (svc *CoreService) CreateServerInstanceWorkflow(create domain.ServerLifecyc
|
||||
instance.State = domain.ServerInstanceStateDraft
|
||||
}
|
||||
if instance.Deployment.Mode != "" {
|
||||
instance.Deployment.ProfileKey = create.ProfileKey
|
||||
if strings.TrimSpace(create.ProfileKey) != "" {
|
||||
instance.Deployment.ProfileKey = create.ProfileKey
|
||||
}
|
||||
instance.Deployment.RuntimeBindings = domain.CopyStringMap(create.Bindings)
|
||||
instance.Deployment.Revision = maxInt(1, instance.Deployment.Revision)
|
||||
instance.Deployment.UpdatedAt = stamp
|
||||
|
||||
Reference in New Issue
Block a user