feat: confirm run deployment execution
This commit is contained in:
@@ -887,6 +887,16 @@ type ServerDeploymentDispatchEvidence struct {
|
||||
JobState JobState
|
||||
DeploymentRevision int
|
||||
DeploymentDefinitionIncluded bool
|
||||
RunConfirmed bool
|
||||
}
|
||||
|
||||
type ServerDeploymentExecutionReceipt struct {
|
||||
SchemaVersion string
|
||||
Revision int
|
||||
Action string
|
||||
Mode ServerDeploymentMode
|
||||
Shell ServerCommandShell
|
||||
UsedServerRoot bool
|
||||
}
|
||||
|
||||
type ConfigDiffLine struct {
|
||||
@@ -1087,6 +1097,7 @@ type JobExecutionResult struct {
|
||||
AuditSummary string
|
||||
Content string
|
||||
ServerDeploymentEvidence *ServerDeploymentEvidence
|
||||
DeploymentReceipt *ServerDeploymentExecutionReceipt
|
||||
}
|
||||
|
||||
type Job struct {
|
||||
@@ -1798,6 +1809,14 @@ func CopyServerDeploymentEvidence(evidence *ServerDeploymentEvidence) *ServerDep
|
||||
return ©
|
||||
}
|
||||
|
||||
func CopyServerDeploymentExecutionReceipt(receipt *ServerDeploymentExecutionReceipt) *ServerDeploymentExecutionReceipt {
|
||||
if receipt == nil {
|
||||
return nil
|
||||
}
|
||||
copy := *receipt
|
||||
return ©
|
||||
}
|
||||
|
||||
func CopyServerDeploymentDefinition(definition ServerDeploymentDefinition) ServerDeploymentDefinition {
|
||||
definition.RuntimeBindings = CopyStringMap(definition.RuntimeBindings)
|
||||
definition.CreateInputs = CopyStringMap(definition.CreateInputs)
|
||||
@@ -1877,6 +1896,7 @@ func CopyJob(job Job) Job {
|
||||
job.ExecutionInput.SourceRCON = CopyRuntimeSourceRCONPlan(job.ExecutionInput.SourceRCON)
|
||||
job.ExecutionInput.ServerDeploymentPlan = CopyServerDeploymentPlan(job.ExecutionInput.ServerDeploymentPlan)
|
||||
job.ExecutionResult.ServerDeploymentEvidence = CopyServerDeploymentEvidence(job.ExecutionResult.ServerDeploymentEvidence)
|
||||
job.ExecutionResult.DeploymentReceipt = CopyServerDeploymentExecutionReceipt(job.ExecutionResult.DeploymentReceipt)
|
||||
if job.ExecutionInput.Deployment != nil {
|
||||
copy := CopyServerDeploymentDefinition(*job.ExecutionInput.Deployment)
|
||||
job.ExecutionInput.Deployment = ©
|
||||
|
||||
+35
-12
@@ -139,9 +139,19 @@ type ServerDeploymentEvidenceBody struct {
|
||||
FailureCode string `json:"failureCode,omitempty"`
|
||||
}
|
||||
|
||||
type ServerDeploymentExecutionReceiptBody struct {
|
||||
SchemaVersion string `json:"schemaVersion"`
|
||||
Revision int `json:"revision"`
|
||||
Action string `json:"action"`
|
||||
Mode domain.ServerDeploymentMode `json:"mode"`
|
||||
Shell domain.ServerCommandShell `json:"shell,omitempty"`
|
||||
UsedServerRoot bool `json:"usedServerRoot"`
|
||||
}
|
||||
|
||||
// ServerDeploymentExecutionBody is included only in a leased Run assignment.
|
||||
// It is intentionally absent from all public server and job response DTOs.
|
||||
type ServerDeploymentExecutionBody struct {
|
||||
SchemaVersion string `json:"schemaVersion"`
|
||||
Mode domain.ServerDeploymentMode `json:"mode"`
|
||||
ProfileKey string `json:"profileKey,omitempty"`
|
||||
RuntimeBindings map[string]string `json:"runtimeBindings,omitempty"`
|
||||
@@ -166,16 +176,17 @@ type RuntimeSourceRCONPlanBody struct {
|
||||
}
|
||||
|
||||
type RunJobExecutionResultBody struct {
|
||||
Kind string `json:"kind,omitempty"`
|
||||
ProcessState string `json:"processState,omitempty"`
|
||||
ExitClassification string `json:"exitClassification,omitempty"`
|
||||
ExitCode int `json:"exitCode,omitempty"`
|
||||
Version int `json:"version,omitempty"`
|
||||
Checksum string `json:"checksum,omitempty"`
|
||||
SizeBytes int64 `json:"sizeBytes,omitempty"`
|
||||
AuditSummary string `json:"auditSummary,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
ServerDeploymentEvidence *ServerDeploymentEvidenceBody `json:"serverDeploymentEvidence,omitempty"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
ProcessState string `json:"processState,omitempty"`
|
||||
ExitClassification string `json:"exitClassification,omitempty"`
|
||||
ExitCode int `json:"exitCode,omitempty"`
|
||||
Version int `json:"version,omitempty"`
|
||||
Checksum string `json:"checksum,omitempty"`
|
||||
SizeBytes int64 `json:"sizeBytes,omitempty"`
|
||||
AuditSummary string `json:"auditSummary,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
ServerDeploymentEvidence *ServerDeploymentEvidenceBody `json:"serverDeploymentEvidence,omitempty"`
|
||||
DeploymentReceipt *ServerDeploymentExecutionReceiptBody `json:"deploymentReceipt,omitempty"`
|
||||
}
|
||||
|
||||
type RunJobResultResponse struct {
|
||||
@@ -408,7 +419,7 @@ func (request RunJobResultRequest) ToDomain() domain.RunJobResult {
|
||||
Message: request.Message,
|
||||
ErrorCode: request.ErrorCode,
|
||||
Retryable: request.Retryable,
|
||||
ExecutionResult: domain.JobExecutionResult{Kind: request.ExecutionResult.Kind, ProcessState: request.ExecutionResult.ProcessState, ExitClassification: request.ExecutionResult.ExitClassification, ExitCode: request.ExecutionResult.ExitCode, Version: request.ExecutionResult.Version, Checksum: request.ExecutionResult.Checksum, SizeBytes: request.ExecutionResult.SizeBytes, AuditSummary: request.ExecutionResult.AuditSummary, Content: request.ExecutionResult.Content, ServerDeploymentEvidence: serverDeploymentEvidenceToDomain(request.ExecutionResult.ServerDeploymentEvidence)},
|
||||
ExecutionResult: domain.JobExecutionResult{Kind: request.ExecutionResult.Kind, ProcessState: request.ExecutionResult.ProcessState, ExitClassification: request.ExecutionResult.ExitClassification, ExitCode: request.ExecutionResult.ExitCode, Version: request.ExecutionResult.Version, Checksum: request.ExecutionResult.Checksum, SizeBytes: request.ExecutionResult.SizeBytes, AuditSummary: request.ExecutionResult.AuditSummary, Content: request.ExecutionResult.Content, ServerDeploymentEvidence: serverDeploymentEvidenceToDomain(request.ExecutionResult.ServerDeploymentEvidence), DeploymentReceipt: deploymentReceiptToDomain(request.ExecutionResult.DeploymentReceipt)},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -657,13 +668,25 @@ func serverDeploymentEvidenceFromDomain(evidence *domain.ServerDeploymentEvidenc
|
||||
}
|
||||
return &ServerDeploymentEvidenceBody{TemplateKey: evidence.TemplateKey, TemplateVersion: evidence.TemplateVersion, PreflightState: evidence.PreflightState, DiscoveryState: evidence.DiscoveryState, MappingState: evidence.MappingState, VerificationState: evidence.VerificationState, DiscoveredFacts: domain.CopyStringMap(evidence.DiscoveredFacts), MappingResults: domain.CopyStringMap(evidence.MappingResults), VerificationResults: domain.CopyStringMap(evidence.VerificationResults), FailureCode: evidence.FailureCode}
|
||||
}
|
||||
func deploymentReceiptToDomain(body *ServerDeploymentExecutionReceiptBody) *domain.ServerDeploymentExecutionReceipt {
|
||||
if body == nil {
|
||||
return nil
|
||||
}
|
||||
return &domain.ServerDeploymentExecutionReceipt{SchemaVersion: body.SchemaVersion, Revision: body.Revision, Action: body.Action, Mode: body.Mode, Shell: body.Shell, UsedServerRoot: body.UsedServerRoot}
|
||||
}
|
||||
func deploymentReceiptFromDomain(value *domain.ServerDeploymentExecutionReceipt) *ServerDeploymentExecutionReceiptBody {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
return &ServerDeploymentExecutionReceiptBody{SchemaVersion: value.SchemaVersion, Revision: value.Revision, Action: value.Action, Mode: value.Mode, Shell: value.Shell, UsedServerRoot: value.UsedServerRoot}
|
||||
}
|
||||
|
||||
func deploymentExecutionFromDomain(definition *domain.ServerDeploymentDefinition) *ServerDeploymentExecutionBody {
|
||||
if definition == nil {
|
||||
return nil
|
||||
}
|
||||
copy := domain.CopyServerDeploymentDefinition(*definition)
|
||||
return &ServerDeploymentExecutionBody{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}
|
||||
return &ServerDeploymentExecutionBody{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 runtimeSourceRCONPlanFromDomain(plan *domain.RuntimeSourceRCONPlan) *RuntimeSourceRCONPlanBody {
|
||||
|
||||
@@ -54,6 +54,7 @@ type ServerDeploymentDispatchEvidenceBody struct {
|
||||
JobState domain.JobState `json:"jobState"`
|
||||
DeploymentRevision int `json:"deploymentRevision"`
|
||||
DeploymentDefinitionIncluded bool `json:"deploymentDefinitionIncluded"`
|
||||
RunConfirmed bool `json:"runConfirmed"`
|
||||
}
|
||||
|
||||
type ServerDeploymentProjectionBody struct {
|
||||
@@ -133,7 +134,7 @@ func deploymentDispatchEvidenceFromDomain(evidence *domain.ServerDeploymentDispa
|
||||
if evidence == nil {
|
||||
return nil
|
||||
}
|
||||
return &ServerDeploymentDispatchEvidenceBody{JobID: evidence.JobID, JobState: evidence.JobState, DeploymentRevision: evidence.DeploymentRevision, DeploymentDefinitionIncluded: evidence.DeploymentDefinitionIncluded}
|
||||
return &ServerDeploymentDispatchEvidenceBody{JobID: evidence.JobID, JobState: evidence.JobState, DeploymentRevision: evidence.DeploymentRevision, DeploymentDefinitionIncluded: evidence.DeploymentDefinitionIncluded, RunConfirmed: evidence.RunConfirmed}
|
||||
}
|
||||
|
||||
func deploymentProjectionFromDomain(projection domain.ServerDeploymentProjection) ServerDeploymentProjectionBody {
|
||||
|
||||
@@ -269,6 +269,12 @@ func (svc *CoreService) CompleteRunJob(result domain.RunJobResult) (domain.RunJo
|
||||
}
|
||||
|
||||
func validateExecutionResultForJob(job domain.Job, result domain.RunJobResult) error {
|
||||
if definition := job.ExecutionInput.Deployment; definition != nil {
|
||||
receipt := result.ExecutionResult.DeploymentReceipt
|
||||
if receipt == nil || receipt.SchemaVersion != "1" || receipt.Revision != definition.Revision || receipt.Action != job.ExecutionInput.LifecycleOperation || receipt.Mode != definition.Mode || receipt.Shell != definition.Shell {
|
||||
return validationError("deployment execution receipt does not match leased definition")
|
||||
}
|
||||
}
|
||||
if job.ExecutionInput.ServerDeploymentPlan != nil {
|
||||
return validateSCUMDeploymentEvidence(job.ExecutionInput.ServerDeploymentPlan, result)
|
||||
}
|
||||
|
||||
@@ -242,7 +242,9 @@ func (svc *CoreService) deploymentView(instance domain.ServerInstance) (domain.S
|
||||
if job.ExecutionInput.Deployment == nil || (view.LatestDispatch != nil && !job.CreatedAt.After(latestDispatchAt)) {
|
||||
continue
|
||||
}
|
||||
view.LatestDispatch = &domain.ServerDeploymentDispatchEvidence{JobID: job.ID, JobState: job.State, DeploymentRevision: job.ExecutionInput.Deployment.Revision, DeploymentDefinitionIncluded: true}
|
||||
receipt := job.ExecutionResult.DeploymentReceipt
|
||||
confirmed := receipt != nil && receipt.Revision == job.ExecutionInput.Deployment.Revision && receipt.Action == job.ExecutionInput.LifecycleOperation
|
||||
view.LatestDispatch = &domain.ServerDeploymentDispatchEvidence{JobID: job.ID, JobState: job.State, DeploymentRevision: job.ExecutionInput.Deployment.Revision, DeploymentDefinitionIncluded: true, RunConfirmed: confirmed}
|
||||
latestDispatchAt = job.CreatedAt
|
||||
}
|
||||
return domain.CopyServerDeploymentView(view), nil
|
||||
|
||||
Reference in New Issue
Block a user