-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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: allow multiple schedules in a cron workflow #12616
feat: allow multiple schedules in a cron workflow #12616
Conversation
Signed-off-by: eduardodbr <eduardodbr@hotmail.com>
Signed-off-by: eduardodbr <eduardodbr@hotmail.com>
Signed-off-by: eduardodbr <eduardodbr@hotmail.com>
Signed-off-by: eduardodbr <eduardodbr@hotmail.com>
Signed-off-by: eduardodbr <eduardodbr@hotmail.com>
Signed-off-by: eduardodbr <eduardodbr@hotmail.com>
CI is failing because of #12596 |
Signed-off-by: eduardodbr <eduardodbr@hotmail.com>
|
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.
Great work!
Signed-off-by: eduardodbr <eduardodbr@hotmail.com>
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.
LGTM once conflicts are resolved
Signed-off-by: eduardodbr <eduardodbr@hotmail.com>
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.
NOTE: this is my first time ever doing react /typescript it is expected that the code lacks quality. Please suggest changes.
This seems to have not gotten a UI SME before merge. It's mostly good, but I left a few comments on improvements below. In particular, the possible unnecessary new line when schedules
contains only a single schedule is something to check
<> | ||
<PrettySchedule schedule={schedule} /> | ||
<br /> | ||
</> |
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'm pretty sure that most of these instances can be simplified with a <p>
paragraph element instead of a <>
fragment + a <br />
line break
<> | |
<PrettySchedule schedule={schedule} /> | |
<br /> | |
</> | |
<p><PrettySchedule schedule={schedule} /></p> |
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.
Also how does this look when schedules
only contains a single schedule? It seems like there may be an unnecessary new line in that case since it is currently treated differently from schedule
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.
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.
Hmm we use <p>
elements in the new markdown title & description feature. Might need to add similar CSS here (line-height
, display
, and vertical-align
). That and it might not work properly if one column uses <p>
while the other uses <br />
.
Try that; if it doesn't work, I can take a look on my side
@@ -183,3 +199,18 @@ export function CronWorkflowList({match, location, history}: RouteComponentProps | |||
</Page> | |||
); | |||
} | |||
|
|||
function getCronNextScheduledTime(spec: CronWorkflowSpec): Date { |
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 naming is quite confusing -- getNextScheduledTime
already operates on cron schedules (and uses cron-parser
directly and is imported from shared/cron.ts
) so adding a function with Cron
in it sounds identical.
It looks like you wrote "Cron" because it operates on the CronWorkflowSpec
-- "Spec" would be better naming in that case.
Or "Multi" can differentiate it from the other one, since this operates on multiple schedules
function getCronNextScheduledTime(spec: CronWorkflowSpec): Date { | |
function getSpecNextScheduledTime(spec: CronWorkflowSpec): Date { |
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 func calculates the next scheduled time for the combination of cron expressions configured in the cron workflow spec, it handles both"schedule" and "schedules". Changing it to getSpecNextScheduledTime
seems fine to me.
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.
Yea the word "Cron" was ambiguous in this case, whereas "Spec" is very specific
@@ -21,6 +21,7 @@ export interface CronWorkflowSpec { | |||
successfulJobsHistoryLimit?: number; | |||
failedJobsHistoryLimit?: number; | |||
timezone?: string; | |||
schedules?: 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.
this makes more sense on line 18 right below schedule
<> | ||
{schedule} | ||
<br /> | ||
</> |
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.
<> | |
{schedule} | |
<br /> | |
</> | |
<p>{schedule}</p> |
same as above
<> | ||
<code>{schedule}</code> <PrettySchedule schedule={schedule} /> | ||
<br /> | ||
</> |
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.
<> | |
<code>{schedule}</code> <PrettySchedule schedule={schedule} /> | |
<br /> | |
</> | |
<p><code>{schedule}</code> <PrettySchedule schedule={schedule} /><p/> |
same as above
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.
Also clients (CLI and UI) should probably have updated labels: Schedule
-> Schedules
.
@@ -19,7 +19,18 @@ export function CronWorkflowStatusViewer({spec, status}: {spec: CronWorkflowSpec | |||
title: 'Schedule', |
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 probably be plural now, no?
title: 'Schedule', | |
title: 'Schedules', |
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 don't have a strong opinion here. It can be a schedule or multiple schedules, depending on the configuration. If you configure schedule
instead of multiple schedules
it will show a single cron expression:
Schedules: */2 * * * *
which is also weird. Do you think it makes sense to show schedule
or schedules
based on how may cron expressions were configured?
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.
Yes I considered that being the case. My thought process included:
- we might eventually deprecate and remove
schedule
if we haveschedules
, to simplify the code / remove tech debt etc. - Argo and k8s already have fields that are plural even if there is only 1 element in the list, for instance:
labels
,volumes
,volumeMounts
,sidecars
,templates
,tasks
,steps
,nodes
, etc
"Schedule(s)" would be an in between option, although it is inconsistent with other 1 element lists, per above
@@ -12,8 +12,22 @@ export function CronWorkflowSpecEditor({onChange, spec}: {spec: CronWorkflowSpec | |||
<div className='row white-box__details-row'> | |||
<div className='columns small-3'>Schedule</div> |
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.
Same as above on plurality
<div className='columns small-3'>Schedule</div> | |
<div className='columns small-3'>Schedules</div> |
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.
Line 138 should probably also be Schedules
now.
I can't comment on the line since GH does not allow commenting on unchanged lines that are not close to a diff
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.
Similar on line 69 below, SCHEDULE
-> SCHEDULES
@@ -73,7 +73,7 @@ func getCronWorkflowGet(cwf *wfv1.CronWorkflow) string { | |||
out += fmt.Sprintf(fmtStr, "Name:", cwf.ObjectMeta.Name) | |||
out += fmt.Sprintf(fmtStr, "Namespace:", cwf.ObjectMeta.Namespace) | |||
out += fmt.Sprintf(fmtStr, "Created:", humanize.Timestamp(cwf.ObjectMeta.CreationTimestamp.Time)) | |||
out += fmt.Sprintf(fmtStr, "Schedule:", cwf.Spec.Schedule) | |||
out += fmt.Sprintf(fmtStr, "Schedule:", cwf.Spec.GetScheduleString()) |
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.
out += fmt.Sprintf(fmtStr, "Schedule:", cwf.Spec.GetScheduleString()) | |
out += fmt.Sprintf(fmtStr, "Schedules:", cwf.Spec.GetScheduleString()) |
similar to above
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.
The CronWorkflow
s docs also need updating around multiple schedules, with version specifiers (see #12581 for examples)
@@ -61,6 +63,8 @@ type CronWorkflowSpec struct { | |||
WorkflowMetadata *metav1.ObjectMeta `json:"workflowMetadata,omitempty" protobuf:"bytes,9,opt,name=workflowMeta"` | |||
// StopStrategy defines if the cron workflow will stop being triggered once a certain condition has been reached, involving a number of runs of the workflow | |||
StopStrategy *StopStrategy `json:"stopStrategy,omitempty" protobuf:"bytes,10,opt,name=stopStrategy"` | |||
// Schedules is a list of schedules to run the Workflow in Cron format |
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.
// Schedules is a list of schedules to run the Workflow in Cron format | |
// v3.6 and after: Schedules is a list of schedules to run the Workflow in Cron format |
This should ideally have a version specifier
Fixes: #12493
Fixes: #9734
Motivation
This PR introduces a new CronWorkflow spec field
Schedules
, a list of cron schedules for a workflow to execute. It maintains backward compatibility withSpec.Schedule
and adds a validation that ensures that both fields cannot be configured simultaneously.Modifications
Controller
1 - This implementation tries to maintain the same behavior for the controller and operator. This biggest change was made to the
cronFacade
where a key can hold multiple cron entries instead of only one. This involved changing the signature for the methodLoad
to return an array of cronWfOperationCtx since a key can hold multiple entries:This method doesn't seem to be used anywhere and cronFacede is not exposed so I don't think there is any issue with this change. Let me know if you think otherwise.
2 - The controller is currently using the label
cronworkflows.argoproj.io/last-used-schedule
to store the current cron expression. This label is only used to check whether the cron expression has been updated since the last time the WF ran, so this PR changes it to be a comma-separated list of the schedules (if applicable). Whenever any of the schedules is updated the label will be changed.Possible Issues
If two cron expressions overlap (for example the expressions
*/2 * * * *
and*/3 * * * *
will overlap at minute 6,12,18,etc) only one WF will be executed because the second will be seen as a duplicate submission. I don't think there is an issue with this, but let me know if you think otherwise. This makes it a bit harder to create an E2E test that is deterministic. Because of that, I decided to not add an E2E test for this feature.CLI
argo cron list
was updated to show all schedules:argo cron get
was updated:UI
NOTE: this is my first time ever doing react /typescript it is expected that the code lacks quality. Please suggest changes.
Cron Workflow list was updated to show all schedules:
![image](https://private-user-images.githubusercontent.com/22349222/302122385-7caf2fe0-b771-4237-9da2-405745230d2b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE0NTU4MjYsIm5iZiI6MTcyMTQ1NTUyNiwicGF0aCI6Ii8yMjM0OTIyMi8zMDIxMjIzODUtN2NhZjJmZTAtYjc3MS00MjM3LTlkYTItNDA1NzQ1MjMwZDJiLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjAlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzIwVDA2MDUyNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTFjNzc3NDkwYWFlNTJmZjE5YWQxZDUyZDgzNDk2ODQ1MmE1NDRhZjJjNmVmZThmYmQ1OGRhMDMxNTlhYmM4NTkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.Coby2pLaqK53q_pEPazr_dv7oQ9-hOr9A24zztHj-ZY)
Cron Workflow status viewer was also updated:
Cron Spec editor:
Verification
This change can be tested with the following cron workflow: