Make generated run lifecycle autonomous
This commit is contained in:
@@ -124,28 +124,29 @@ func (svc *CoreService) platformDistributionBuildInput(job domain.Job) (domain.D
|
||||
if err != nil {
|
||||
return domain.DistributionBuildInput{}, err
|
||||
}
|
||||
profileKey, workspaceSeed, err := svc.runDistributionWorkspaceSeed(distribution)
|
||||
packageInput, err := svc.runDistributionPackageContext(distribution)
|
||||
if err != nil {
|
||||
return domain.DistributionBuildInput{}, err
|
||||
}
|
||||
return domain.DistributionBuildInput{
|
||||
JobID: job.ID,
|
||||
ComponentKind: domain.DistributionComponentRun,
|
||||
ServerInstanceID: distribution.ServerInstanceID,
|
||||
PluginID: distribution.PluginID,
|
||||
RunEndpointID: distribution.RunEndpointID,
|
||||
ProfileKey: profileKey,
|
||||
TargetOS: distribution.TargetOS,
|
||||
TargetArch: distribution.TargetArch,
|
||||
TargetRelease: distribution.ID,
|
||||
PlatformURL: runReleasePlatformURL(),
|
||||
PackageFormat: distribution.PackageFormat,
|
||||
ArtifactID: distribution.ArtifactID,
|
||||
OutputFilename: executableFilename("run", distribution.TargetOS),
|
||||
SecretRef: distribution.SecretRef,
|
||||
KeyGeneration: distribution.KeyGeneration,
|
||||
AuthKey: plainKey,
|
||||
WorkspaceSeed: workspaceSeed,
|
||||
JobID: job.ID,
|
||||
ComponentKind: domain.DistributionComponentRun,
|
||||
ServerInstanceID: distribution.ServerInstanceID,
|
||||
PluginID: distribution.PluginID,
|
||||
RunEndpointID: distribution.RunEndpointID,
|
||||
ProfileKey: packageInput.profileKey,
|
||||
TargetOS: distribution.TargetOS,
|
||||
TargetArch: distribution.TargetArch,
|
||||
TargetRelease: distribution.ID,
|
||||
PlatformURL: runReleasePlatformURL(),
|
||||
PackageFormat: distribution.PackageFormat,
|
||||
ArtifactID: distribution.ArtifactID,
|
||||
OutputFilename: executableFilename("run", distribution.TargetOS),
|
||||
SecretRef: distribution.SecretRef,
|
||||
KeyGeneration: distribution.KeyGeneration,
|
||||
AuthKey: plainKey,
|
||||
WorkspaceSeed: packageInput.workspaceSeed,
|
||||
AutonomousLifecycle: packageInput.autonomousLifecycle,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -191,26 +192,160 @@ func (svc *CoreService) platformDistributionBuildInput(job domain.Job) (domain.D
|
||||
return domain.DistributionBuildInput{}, repo.ErrNotFound
|
||||
}
|
||||
|
||||
func (svc *CoreService) runDistributionWorkspaceSeed(distribution domain.RunDistribution) (string, string, error) {
|
||||
type runDistributionPackageContext struct {
|
||||
profileKey string
|
||||
workspaceSeed string
|
||||
autonomousLifecycle *domain.RunAutonomousLifecyclePlan
|
||||
}
|
||||
|
||||
func (svc *CoreService) runDistributionPackageContext(distribution domain.RunDistribution) (runDistributionPackageContext, error) {
|
||||
instance, err := svc.store.ServerInstances().Get(distribution.ServerInstanceID)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
return runDistributionPackageContext{}, err
|
||||
}
|
||||
plugin, err := svc.store.GamePlugins().Get(distribution.PluginID)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
seed, err := encodePluginWorkspaceSeed(plugin.LifecycleAssets)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
return runDistributionPackageContext{}, err
|
||||
}
|
||||
profileKey := instance.Deployment.ProfileKey
|
||||
bindings := map[string]string(nil)
|
||||
if binding, bindingErr := svc.runtimeBindingForServer(distribution.ServerInstanceID); bindingErr == nil {
|
||||
profileKey = binding.ProfileKey
|
||||
bindings = domain.CopyStringMap(binding.Bindings)
|
||||
} else if !errors.Is(bindingErr, repo.ErrNotFound) {
|
||||
return "", "", bindingErr
|
||||
return runDistributionPackageContext{}, bindingErr
|
||||
}
|
||||
return profileKey, seed, nil
|
||||
plan, err := runAutonomousLifecyclePlan(distribution, instance, plugin, profileKey, bindings)
|
||||
if err != nil {
|
||||
return runDistributionPackageContext{}, err
|
||||
}
|
||||
seed, err := encodeRunWorkspaceSeed(plugin.LifecycleAssets, plan)
|
||||
if err != nil {
|
||||
return runDistributionPackageContext{}, err
|
||||
}
|
||||
return runDistributionPackageContext{profileKey: profileKey, workspaceSeed: seed, autonomousLifecycle: plan}, nil
|
||||
}
|
||||
|
||||
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",
|
||||
ServerInstanceID: instance.ID,
|
||||
PluginID: plugin.ID,
|
||||
PluginVersion: plugin.Version,
|
||||
RunEndpointID: distribution.RunEndpointID,
|
||||
ProfileKey: profileKey,
|
||||
TargetOS: distribution.TargetOS,
|
||||
TargetArch: distribution.TargetArch,
|
||||
TargetRelease: distribution.ID,
|
||||
DeploymentRevision: instance.Deployment.Revision,
|
||||
RuntimeBindings: domain.CopyStringMap(bindings),
|
||||
Deployment: autonomousDeploymentFromDefinition(instance.Deployment, profileKey, bindings),
|
||||
}
|
||||
profile, hasProfile := runtimeLifecycleProfileForKey(plugin.RuntimeProfiles, profileKey)
|
||||
for _, action := range []domain.ServerLifecycleAction{domain.ServerLifecycleActionCreate, domain.ServerLifecycleActionStart, domain.ServerLifecycleActionStop, domain.ServerLifecycleActionStatus} {
|
||||
entry := autonomousLifecycleAction(plugin, profile, hasProfile, action)
|
||||
if entry.TargetKey == "" {
|
||||
continue
|
||||
}
|
||||
plan.Actions = append(plan.Actions, entry)
|
||||
}
|
||||
bootstrap := autonomousLifecycleAction(plugin, profile, hasProfile, autonomousBootstrapLifecycleAction(plugin, profile, hasProfile))
|
||||
if bootstrap.TargetKey != "" {
|
||||
plan.Bootstrap = &bootstrap
|
||||
}
|
||||
for _, probe := range plugin.RuntimeProfiles.DependencyProbes {
|
||||
if runtimePlatformsContain(probe.Platforms, distribution.TargetOS) {
|
||||
plan.DependencyProbes = append(plan.DependencyProbes, autonomousDependencyProbe(probe))
|
||||
}
|
||||
}
|
||||
for _, installPlan := range plugin.RuntimeProfiles.InstallPlans {
|
||||
if runtimePlatformsContain(installPlan.Platforms, distribution.TargetOS) {
|
||||
plan.InstallPlans = append(plan.InstallPlans, autonomousInstallPlan(installPlan))
|
||||
}
|
||||
}
|
||||
for _, source := range plugin.RuntimeProfiles.LogSources {
|
||||
if source.Kind == "process.stdout" || source.Kind == "process.stderr" {
|
||||
plan.LogSources = append(plan.LogSources, autonomousLogSource(source))
|
||||
}
|
||||
}
|
||||
if hasProfile && len(profile.DLLExtensionRefs) > 0 {
|
||||
endpoint := domain.RunEndpoint{ID: distribution.RunEndpointID, Platform: distribution.TargetOS, Architecture: distribution.TargetArch}
|
||||
extensions, err := lifecycleDLLExtensionPlans(plugin.RuntimeProfiles, profile, endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, extension := range extensions {
|
||||
plan.DLLExtensions = append(plan.DLLExtensions, autonomousDLLExtension(extension))
|
||||
}
|
||||
}
|
||||
return domain.CopyRunAutonomousLifecyclePlanPtr(plan), nil
|
||||
}
|
||||
|
||||
func autonomousLifecycleAction(plugin domain.GamePlugin, profile domain.RuntimeLifecycleProfile, hasProfile bool, action domain.ServerLifecycleAction) domain.RunAutonomousLifecycleAction {
|
||||
targetKey := ""
|
||||
if hasProfile {
|
||||
targetKey = runtimeProfileActionRef(profile.ActionRefs, action)
|
||||
}
|
||||
if targetKey == "" {
|
||||
targetKey = lifecycleActionRef(plugin, action)
|
||||
}
|
||||
if targetKey == "" {
|
||||
return domain.RunAutonomousLifecycleAction{}
|
||||
}
|
||||
return domain.RunAutonomousLifecycleAction{Action: action, Operation: lifecycleExecutionOperation(action), Capability: domain.LifecycleCapabilityForAction(action), TargetKey: targetKey}
|
||||
}
|
||||
|
||||
func autonomousBootstrapLifecycleAction(plugin domain.GamePlugin, profile domain.RuntimeLifecycleProfile, hasProfile bool) domain.ServerLifecycleAction {
|
||||
if autonomousLifecycleAction(plugin, profile, hasProfile, domain.ServerLifecycleActionStart).TargetKey != "" {
|
||||
return domain.ServerLifecycleActionStart
|
||||
}
|
||||
return domain.ServerLifecycleActionCreate
|
||||
}
|
||||
|
||||
func autonomousDependencyProbe(probe domain.RuntimeDependencyProbe) domain.RunAutonomousDependencyProbe {
|
||||
return domain.RunAutonomousDependencyProbe{Key: probe.Key, Kind: probe.Kind, TargetKey: probe.TargetKey, Required: probe.Required, MinimumVersion: probe.MinimumVersion, Platforms: domain.CopyStringSlice(probe.Platforms)}
|
||||
}
|
||||
|
||||
func autonomousInstallPlan(plan domain.RuntimeInstallPlan) domain.RunAutonomousInstallPlan {
|
||||
steps := make([]domain.RunAutonomousInstallStep, len(plan.Steps))
|
||||
for i, step := range plan.Steps {
|
||||
steps[i] = domain.RunAutonomousInstallStep{Type: step.Type, TargetKey: step.TargetKey, PackageManager: step.PackageManager, PackageName: step.PackageName, Version: step.Version, DownloadRef: step.DownloadRef, Checksum: step.Checksum}
|
||||
}
|
||||
return domain.RunAutonomousInstallPlan{Key: plan.Key, Title: plan.Title, Platforms: domain.CopyStringSlice(plan.Platforms), Steps: steps}
|
||||
}
|
||||
|
||||
func autonomousLogSource(source domain.RuntimeLogSource) domain.RunAutonomousLogSource {
|
||||
return domain.RunAutonomousLogSource{Key: source.Key, Kind: source.Kind, TargetKey: source.TargetKey, StreamKey: source.StreamKey, CursorKind: source.CursorKind, RetentionDays: source.RetentionDays}
|
||||
}
|
||||
|
||||
func autonomousDLLExtension(extension domain.RuntimeDLLExtensionPlan) domain.RunAutonomousDLLExtension {
|
||||
return domain.RunAutonomousDLLExtension{Key: extension.Key, Version: extension.Version, ReleaseURL: extension.ReleaseURL, Checksum: extension.Checksum, SizeBytes: extension.SizeBytes, TargetKey: extension.TargetKey, ModKey: extension.ModKey, DLLRef: extension.DLLRef, SCUMExecutableChecksum: extension.SCUMExecutableChecksum, UE4SSABI: extension.UE4SSABI, RCONPort: extension.RCONPort}
|
||||
}
|
||||
|
||||
func autonomousDeploymentFromDefinition(definition domain.ServerDeploymentDefinition, profileKey string, bindings map[string]string) *domain.RunAutonomousDeployment {
|
||||
if definition.Mode == "" {
|
||||
return nil
|
||||
}
|
||||
copy := domain.CopyServerDeploymentDefinition(definition)
|
||||
if copy.ProfileKey == "" {
|
||||
copy.ProfileKey = profileKey
|
||||
}
|
||||
if len(copy.RuntimeBindings) == 0 {
|
||||
copy.RuntimeBindings = domain.CopyStringMap(bindings)
|
||||
}
|
||||
return &domain.RunAutonomousDeployment{SchemaVersion: "1", Mode: copy.Mode, ProfileKey: copy.ProfileKey, RuntimeBindings: copy.RuntimeBindings, CreateInputs: copy.CreateInputs, ServerRoot: copy.ServerRoot, WorkingDirectory: copy.WorkingDirectory, InstallCommand: copy.InstallCommand, StartCommand: copy.StartCommand, StopCommand: copy.StopCommand, StatusCommand: copy.StatusCommand, Shell: copy.Shell, Revision: copy.Revision}
|
||||
}
|
||||
|
||||
func encodeRunWorkspaceSeed(files []domain.PluginAssetFile, plan *domain.RunAutonomousLifecyclePlan) (string, error) {
|
||||
seedFiles := append([]domain.PluginAssetFile(nil), files...)
|
||||
if plan != nil {
|
||||
payload, err := json.Marshal(plan)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
seedFiles = append(seedFiles, domain.PluginAssetFile{Path: ".platform/autonomous-lifecycle-plan.json", Content: string(payload), Mode: 0o600})
|
||||
}
|
||||
return encodePluginWorkspaceSeed(seedFiles)
|
||||
}
|
||||
|
||||
func encodePluginWorkspaceSeed(files []domain.PluginAssetFile) (string, error) {
|
||||
|
||||
Reference in New Issue
Block a user