-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add terminalState to jobset status #594
feat: add terminalState to jobset status #594
Conversation
✅ Deploy Preview for kubernetes-sigs-jobset canceled.
|
6e304ec
to
5397dc9
Compare
root@VM-0-9-ubuntu:/home/ubuntu# kubectl get jobset
NAME PHASE RESTARTS COMPLETED SUSPENDED AGE
max-restarts Failed 3 44m
paralleljobs Completed True 44m
startup-driver-ready Completed True 29m
success-policy Completed True 44m |
5397dc9
to
18c845f
Compare
7c00e55
to
17ac525
Compare
// JobSetRunning means the job is running.
JobSetRunning JobSetConditionType = "Running"
// JobSetCompleted means the job has completed its execution.
JobSetCompleted JobSetConditionType = "Completed"
// JobSetFailed means the job has failed its execution.
JobSetFailed JobSetConditionType = "Failed"
// JobSetSuspended means the job is suspended.
JobSetSuspended JobSetConditionType = "Suspended" The phase is converted according to these four fields. The default is Running |
/assign @danielvegamyhre |
feat: add jobset status
17ac525
to
25396be
Compare
308e200
to
9e78074
Compare
Thanks for doing this @googs1025. I will test this out.. |
api/jobset/v1alpha2/jobset_types.go
Outdated
@@ -134,6 +136,10 @@ type JobSetStatus struct { | |||
// RestartsCountTowardsMax tracks the number of times the JobSet has restarted that counts towards the maximum allowed number of restarts. | |||
RestartsCountTowardsMax int32 `json:"restartsCountTowardsMax,omitempty"` | |||
|
|||
// Phase of the JobSet. | |||
// +kubebuilder:default="Running" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be in the status, not the spec, and we can't default it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently it is set in jobs status
// JobSetStatus defines the observed state of JobSet
type JobSetStatus struct {
// +optional
// +listType=map
// +listMapKey=type
Conditions []metav1.Condition `json:"conditions,omitempty"`
....
// Phase of the JobSet.
// +kubebuilder:default="Running"
Phase string `json:"phase,omitempty"`
}
pkg/controllers/jobset_controller.go
Outdated
@@ -867,14 +867,15 @@ func enqueueEvent(updateStatusOpts *statusUpdateOpts, event *eventParams) { | |||
// function parameters for setCondition | |||
type conditionOpts struct { | |||
eventType string | |||
phase string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to pass this around, we should be able to compute the phase from the condition in the status update function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we only use condition calculation, we may need to exclude other JobSetConditionType. I think it would be more convenient to use one more field such as phase or terminalState.
such as: These conditions are not what this field needs to care about
// These are built-in conditions of a JobSet.
const (
...
// JobSetSuspended means the job is suspended.
JobSetSuspended JobSetConditionType = "Suspended"
// JobSetStartupPolicyInProgress means the StartupPolicy is in progress.
JobSetStartupPolicyInProgress JobSetConditionType = "StartupPolicyInProgress"
// JobSetStartupPolicyCompleted means the StartupPolicy has completed.
JobSetStartupPolicyCompleted JobSetConditionType = "StartupPolicyCompleted"
)
This would work perfectly.. |
I was able to do the following testing on this PR:
|
This is great! Thanks for testing this. |
@shrinandj Thanks for your test |
I changed the field to terminalState. When the jobset reaches the final state, it will be set to Completed or Failed. root@VM-0-16-ubuntu:/home/ubuntu# kubectl get jobset
NAME TERMINALSTATE RESTARTS COMPLETED SUSPENDED AGE
max-restarts Failed 3 89m
paralleljobs Completed True 89m
success-policy Completed True 89m
|
@ahg-g @danielvegamyhre /PTAL Thanks for review |
Signed-off-by: googs1025 <[email protected]>
95adaea
to
4137a08
Compare
Could this be merged and new release be cut with this feature? |
Yep, will do final review shortly |
pkg/controllers/jobset_controller.go
Outdated
@@ -941,6 +944,13 @@ func updateCondition(js *jobset.JobSet, opts *conditionOpts) bool { | |||
js.Status.Conditions = append(js.Status.Conditions, newCond) | |||
shouldUpdate = true | |||
} | |||
|
|||
// If the jobset is in a terminal state, set the terminal state on the jobset. | |||
if opts.terminalState != "" && js.Status.TerminalState != opts.terminalState { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you choose to put the logic updating the terminal state in the function that is responsible for updating the condition, rather than put it in its own function? The logic doesn't seem to depend on the condition updates here, it just depends on the opts
passed in, so I don't see why this logic belongs here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My initial thought was that the TerminalState field is actually a subtype of the Conditions field, specifically the JobSetCompleted or JobSetFailed types. TerminalState can be seen as a special case within Conditions. That's why I grouped these two together and updated them in the same method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If separating them, we can distinguish them into updateCondition and updateTerminalState methods.
// setCondition will add a new condition and terminalState to the JobSet status (or update an existing one),
// and enqueue an event for emission if the status update succeeds at the end of the reconcile.
func setCondition(js *jobset.JobSet, condOpts *conditionOpts, updateStatusOpts *statusUpdateOpts) {
// Return early if no status update is required for this condition and terminalState.
if !updateCondition(js, condOpts) && !updateTerminalState(js, condOpts) {
return
}
if updateStatusOpts == nil {
updateStatusOpts = &statusUpdateOpts{}
}
...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to set status.TerminalState in the same functions where we set the completed or failed condition. Meaning in setJobSetFailedCondition
and setJobSetCompletedCondition
func setJobSetCompletedCondition(js *jobset.JobSet, updateStatusOpts *statusUpdateOpts) {
setCondition(js, makeCompletedConditionsOpts(), updateStatusOpts)
jobset.Status.TerminalState = JobSetCompleted
}
func setJobSetFailedCondition(ctx context.Context, js *jobset.JobSet, reason, msg string, updateStatusOpts *statusUpdateOpts) {
setCondition(js, makeFailedConditionOpts(reason, msg), updateStatusOpts)
jobset.Status.TerminalState = JobSetFailed
}
and that is all, we don't need to track anything in updateStatusOpts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion, this makes the code much simpler! done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a checkJobSetTerminalState function to https://github.com/kubernetes-sigs/jobset/blob/main/test/util/util.go :
func checkJobSetTerminalState(ctx context.Context, k8sClient client.Client, js *jobset.JobSet, state string) (bool, error) {
var fetchedJS jobset.JobSet
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: js.Namespace, Name: js.Name}, &fetchedJS); err != nil {
return false, err
}
return fetchedJS.Status.TerminalState == state
}
and call it from JobSetCompleted to and JobSetFailed to verify the terminalState during integration tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok,i will do it soon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
faa89eb
to
a1c05dc
Compare
/lgtm This is great, thank you for your patience during the review process! |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: ahg-g, googs1025 The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Thank you for moving this forward! |
Fix: #545