113 lines
3.0 KiB
Go
113 lines
3.0 KiB
Go
package workflows
|
|
|
|
import portainer "github.com/portainer/portainer/api"
|
|
|
|
func deriveStackTargetState(s portainer.Stack) WorkflowPhaseStatus {
|
|
if len(s.DeploymentStatus) == 0 {
|
|
return WorkflowPhaseStatus{Status: StatusHealthy}
|
|
}
|
|
last := s.DeploymentStatus[len(s.DeploymentStatus)-1]
|
|
switch last.Status {
|
|
case portainer.StackStatusActive:
|
|
return WorkflowPhaseStatus{Status: StatusHealthy}
|
|
case portainer.StackStatusError:
|
|
return WorkflowPhaseStatus{Status: StatusError, Error: last.Message}
|
|
case portainer.StackStatusDeploying:
|
|
return WorkflowPhaseStatus{Status: StatusSyncing}
|
|
case portainer.StackStatusInactive:
|
|
return WorkflowPhaseStatus{Status: StatusPaused}
|
|
default:
|
|
return WorkflowPhaseStatus{Status: StatusUnknown}
|
|
}
|
|
}
|
|
|
|
func deriveEdgeStackTargetState(statuses []portainer.EdgeStackStatusForEnv) WorkflowPhaseStatus {
|
|
result := StatusUnknown
|
|
for _, epStatus := range statuses {
|
|
ws, msg := endpointWorkflowStatus(epStatus)
|
|
if ws == StatusError {
|
|
return WorkflowPhaseStatus{Status: ws, Error: msg}
|
|
}
|
|
if statusPriority(ws) > statusPriority(result) {
|
|
result = ws
|
|
}
|
|
}
|
|
return WorkflowPhaseStatus{Status: result}
|
|
}
|
|
|
|
func endpointWorkflowStatus(epStatus portainer.EdgeStackStatusForEnv) (Status, string) {
|
|
if len(epStatus.Status) == 0 {
|
|
return StatusUnknown, ""
|
|
}
|
|
last := epStatus.Status[len(epStatus.Status)-1]
|
|
switch last.Type {
|
|
case portainer.EdgeStackStatusError:
|
|
return StatusError, last.Error
|
|
case portainer.EdgeStackStatusDeploying,
|
|
portainer.EdgeStackStatusRollingBack,
|
|
portainer.EdgeStackStatusRemoving,
|
|
portainer.EdgeStackStatusPending,
|
|
portainer.EdgeStackStatusDeploymentReceived,
|
|
portainer.EdgeStackStatusAcknowledged,
|
|
portainer.EdgeStackStatusImagesPulled:
|
|
return StatusSyncing, ""
|
|
case portainer.EdgeStackStatusPausedDeploying:
|
|
return StatusPaused, ""
|
|
case portainer.EdgeStackStatusRunning,
|
|
portainer.EdgeStackStatusRolledBack,
|
|
portainer.EdgeStackStatusCompleted,
|
|
portainer.EdgeStackStatusRemoved,
|
|
portainer.EdgeStackStatusRemoteUpdateSuccess:
|
|
return StatusHealthy, ""
|
|
default:
|
|
return StatusUnknown, ""
|
|
}
|
|
}
|
|
|
|
// EffectiveStatus returns the highest-priority status across all three phases of a workflow.
|
|
func EffectiveStatus(w Workflow) Status {
|
|
s := w.Status.Target.Status
|
|
if statusPriority(w.Status.Source.Status) > statusPriority(s) {
|
|
s = w.Status.Source.Status
|
|
}
|
|
if statusPriority(w.Status.Artifact.Status) > statusPriority(s) {
|
|
s = w.Status.Artifact.Status
|
|
}
|
|
return s
|
|
}
|
|
|
|
// CountByStatus counts workflows per effective status and returns a StatusSummary.
|
|
func CountByStatus(workflows []Workflow) StatusSummary {
|
|
var s StatusSummary
|
|
for _, w := range workflows {
|
|
switch EffectiveStatus(w) {
|
|
case StatusHealthy:
|
|
s.Healthy++
|
|
case StatusSyncing:
|
|
s.Syncing++
|
|
case StatusError:
|
|
s.Error++
|
|
case StatusPaused:
|
|
s.Paused++
|
|
default:
|
|
s.Unknown++
|
|
}
|
|
}
|
|
return s
|
|
}
|
|
|
|
func statusPriority(s Status) int {
|
|
switch s {
|
|
case StatusError:
|
|
return 4
|
|
case StatusSyncing:
|
|
return 3
|
|
case StatusPaused:
|
|
return 2
|
|
case StatusHealthy:
|
|
return 1
|
|
default:
|
|
return 0
|
|
}
|
|
}
|