github.com/kubeflow/training-operator@v1.7.0/pkg/util/status.go (about) 1 package util 2 3 import ( 4 "fmt" 5 6 v1 "k8s.io/api/core/v1" 7 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 9 apiv1 "github.com/kubeflow/training-operator/pkg/apis/kubeflow.org/v1" 10 ) 11 12 const ( 13 // JobCreatedReason is added in a job when it is created. 14 JobCreatedReason = "Created" 15 // JobSucceededReason is added in a job when it is succeeded. 16 JobSucceededReason = "Succeeded" 17 // JobRunningReason is added in a job when it is running. 18 JobRunningReason = "Running" 19 // JobFailedReason is added in a job when it is failed. 20 JobFailedReason = "Failed" 21 // JobRestartingReason is added in a job when it is restarting. 22 JobRestartingReason = "Restarting" 23 // JobFailedValidationReason is added in a job when it failed validation 24 JobFailedValidationReason = "FailedValidation" 25 // JobSuspendedReason is added in a job when it is suspended. 26 JobSuspendedReason = "Suspended" 27 // JobResumedReason is added in a job when it is unsuspended. 28 JobResumedReason = "Resumed" 29 ) 30 31 func NewReason(kind, reason string) string { 32 return fmt.Sprintf("%s%s", kind, reason) 33 } 34 35 // IsFinished checks if the job is succeeded or failed 36 func IsFinished(status apiv1.JobStatus) bool { 37 return IsSucceeded(status) || IsFailed(status) 38 } 39 40 // IsSucceeded checks if the job is succeeded 41 func IsSucceeded(status apiv1.JobStatus) bool { 42 return isStatusConditionTrue(status, apiv1.JobSucceeded) 43 } 44 45 // IsFailed checks if the job is failed 46 func IsFailed(status apiv1.JobStatus) bool { 47 return isStatusConditionTrue(status, apiv1.JobFailed) 48 } 49 50 func IsRunning(status apiv1.JobStatus) bool { 51 return isStatusConditionTrue(status, apiv1.JobRunning) 52 } 53 54 func IsSuspended(status apiv1.JobStatus) bool { 55 return isStatusConditionTrue(status, apiv1.JobSuspended) 56 } 57 58 // UpdateJobConditions adds to the jobStatus a new condition if needed, with the conditionType, reason, and message 59 func UpdateJobConditions( 60 jobStatus *apiv1.JobStatus, 61 conditionType apiv1.JobConditionType, 62 conditionStatus v1.ConditionStatus, 63 reason, message string, 64 ) { 65 condition := newCondition(conditionType, conditionStatus, reason, message) 66 setCondition(jobStatus, condition) 67 } 68 69 func isStatusConditionTrue(status apiv1.JobStatus, condType apiv1.JobConditionType) bool { 70 for _, condition := range status.Conditions { 71 if condition.Type == condType && condition.Status == v1.ConditionTrue { 72 return true 73 } 74 } 75 return false 76 } 77 78 // newCondition creates a new job condition. 79 func newCondition(conditionType apiv1.JobConditionType, conditionStatus v1.ConditionStatus, reason, message string) apiv1.JobCondition { 80 return apiv1.JobCondition{ 81 Type: conditionType, 82 Status: conditionStatus, 83 LastUpdateTime: metav1.Now(), 84 LastTransitionTime: metav1.Now(), 85 Reason: reason, 86 Message: message, 87 } 88 } 89 90 // getCondition returns the condition with the provided type. 91 func getCondition(status apiv1.JobStatus, condType apiv1.JobConditionType) *apiv1.JobCondition { 92 for _, condition := range status.Conditions { 93 if condition.Type == condType { 94 return &condition 95 } 96 } 97 return nil 98 } 99 100 // setCondition updates the job to include the provided condition. 101 // If the condition that we are about to add already exists 102 // and has the same status and reason then we are not going to update. 103 func setCondition(status *apiv1.JobStatus, condition apiv1.JobCondition) { 104 // Do nothing if JobStatus have failed condition 105 if IsFailed(*status) { 106 return 107 } 108 109 currentCond := getCondition(*status, condition.Type) 110 111 // Do nothing if condition doesn't change 112 if currentCond != nil && currentCond.Status == condition.Status && currentCond.Reason == condition.Reason { 113 return 114 } 115 116 // Do not update lastTransitionTime if the status of the condition doesn't change. 117 if currentCond != nil && currentCond.Status == condition.Status { 118 condition.LastTransitionTime = currentCond.LastTransitionTime 119 } 120 121 // Append the updated condition to the conditions 122 newConditions := filterOutCondition(status.Conditions, condition.Type) 123 status.Conditions = append(newConditions, condition) 124 } 125 126 // filterOutCondition returns a new slice of job conditions without conditions with the provided type. 127 func filterOutCondition(conditions []apiv1.JobCondition, condType apiv1.JobConditionType) []apiv1.JobCondition { 128 var newConditions []apiv1.JobCondition 129 for _, c := range conditions { 130 if condType == apiv1.JobRestarting && c.Type == apiv1.JobRunning { 131 continue 132 } 133 if condType == apiv1.JobRunning && c.Type == apiv1.JobRestarting { 134 continue 135 } 136 137 if c.Type == condType { 138 continue 139 } 140 141 // Set the running condition status to be false when current condition failed or succeeded 142 if (condType == apiv1.JobFailed || condType == apiv1.JobSucceeded) && c.Type == apiv1.JobRunning { 143 c.Status = v1.ConditionFalse 144 } 145 146 newConditions = append(newConditions, c) 147 } 148 return newConditions 149 }