-
Notifications
You must be signed in to change notification settings - Fork 226
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit splits TEP-0083 (scheduled and polling runs) into two TEPs, one for scheduled runs and one for polling runs, and adds an implementation plan for scheduled runs.
- Loading branch information
Showing
5 changed files
with
290 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,279 @@ | ||
--- | ||
status: implementable | ||
title: Scheduled Runs | ||
creation-date: '2022-12-20' | ||
last-updated: '2022-12-20' | ||
authors: | ||
- '@vdemeester' | ||
- '@sm43' | ||
- '@lbernick' | ||
collaborators: [] | ||
--- | ||
|
||
# TEP-0128: Scheduled Runs | ||
|
||
<!-- toc --> | ||
- [Summary](#summary) | ||
- [Motivation](#motivation) | ||
- [Goals](#goals) | ||
- [Non-Goals](#non-goals) | ||
- [Use Cases](#use-cases) | ||
- [Proposal](#proposal) | ||
- [Design Evaluation](#design-evaluation) | ||
- [Reusability](#reusability) | ||
- [Simplicity](#simplicity) | ||
- [Flexibility](#flexibility) | ||
- [Performance](#performance) | ||
- [Security](#security) | ||
- [Drawbacks](#drawbacks) | ||
- [Alternatives](#alternatives) | ||
- [Implementation Plan](#implementation-plan) | ||
- [Implementation Pull Requests](#implementation-pull-requests) | ||
- [References](#references) | ||
<!-- /toc --> | ||
|
||
## Summary | ||
|
||
This TEP proposes allowing Task/Pipeline users to schedule runs on a recurring basis. | ||
|
||
## Motivation | ||
|
||
Currently, to get a run to occur on a regular basis, a user must write a cron job that either creates the run itself | ||
(which duplicates much of triggers' functionality) or pings an EventListener. | ||
If the EventListener is exposed outside of the cluster, the user must also sign the cron job event body and verify it in a custom interceptor | ||
(although it's unlikely a user would choose to expose an ingress for an EventListener used only for cron jobs). | ||
|
||
### Goals | ||
|
||
- Can create new PipelineRuns, TaskRuns, or CustomRuns on a recurring basis without creating a webhook or writing a CronJob | ||
|
||
### Non-Goals | ||
|
||
- Polling a repository (or other external system) for changes; this is covered in [TEP-0083](./0083-polling-runs-in-tekton.md). | ||
|
||
### Use Cases | ||
|
||
- Release Pipeline: User would like to create releases of their project on a nightly basis. | ||
|
||
## Proposal | ||
|
||
Add a `schedule` field following Kubernetes CronJob syntax to the EventListener CRD, for example: | ||
|
||
```yaml | ||
kind: EventListener | ||
spec: | ||
schedule: "0 0 * * *" | ||
triggers: | ||
- bindings: | ||
- name: project-name | ||
value: wait-task | ||
- name: triggers-uuid | ||
value: $(context.eventID) | ||
- name: datetime | ||
value: $(context.datetime) | ||
template: | ||
ref: experimental-release-pipeline-template | ||
``` | ||
```yaml | ||
kind: EventListener | ||
spec: | ||
schedule: "0 0 * * *" | ||
triggerGroups: | ||
- triggerSelector: | ||
labelSelector: | ||
matchLabels: | ||
type: nightly-release | ||
``` | ||
An EventListener with a `schedule` would send an empty event body at the specified times. | ||
This means that any bindings containing `$(body.foo)` or `$(header.bar)` would fail, as well as any interceptors | ||
responsible for processing the event. | ||
An EventListener with a `schedule` would still create a service for receiving events. | ||
|
||
### Bindings | ||
|
||
As part of future work for this proposal, we can add two new variable replacements in bindings: | ||
- $(context.date): date when the run was created, in RFC3339 format | ||
- $(context.datetime): timestamp when the run was created, in RFC3339 format | ||
|
||
### CLI | ||
|
||
As part of future work for this proposal, we can add a CLI command to manually trigger execution of an EventListener, | ||
similar to the kubectl functionality `kubectl create job --from=cronjob/my-cronjob`, for example: | ||
|
||
```sh | ||
tkn eventlistener start <el_name> | ||
``` | ||
|
||
## Design Evaluation | ||
|
||
### Reusability | ||
|
||
This feature is essentially syntactic sugar for a CronJob creating a Tekton resource. | ||
It reuses EventListener functionality such as TriggerGroups and CloudEventSinks. | ||
The schedule is a runtime concern, similar to other fields specified in EventListeners. | ||
|
||
### Simplicity | ||
|
||
The user experience with this proposal is much simpler with this proposal | ||
(a single additional line of configuration) than without it. | ||
For an example of what the user experience looks like without this proposal, see | ||
the [nightly release CronJob](https://github.com/tektoncd/plumbing/blob/be9826a5e75722782799e8094c3441295b185fe9/tekton/cronjobs/bases/release/trigger-with-uuid.yaml) | ||
used in the plumbing repo. | ||
|
||
### Flexibility | ||
|
||
- No new dependencies needed for this proposal | ||
- We are not coupling projects together, but we are coupling event generation to resource creation to some extent. | ||
|
||
### Conformance | ||
|
||
- This proposal doesn't require the user to understand how the API is implemented, | ||
or introduce new Kubernetes concepts into the API. | ||
- The `schedule` field should not be required for Triggers conformance. | ||
|
||
### Performance | ||
|
||
Creating a CronJob to simply send an empty event body to an EventListener may not be very performant; | ||
however, performance of creating scheduled runs is not as important as (for example) performance | ||
of creating a run used for CI. Using CronJobs is a reasonable way to start, especially if it helps us avoid | ||
reimplementing cron syntax. | ||
|
||
### Security | ||
|
||
EventListeners with ingresses exposed outside of the cluster are expected to use interceptors to validate event payloads. | ||
EventListeners with `schedules` don't have a way of validating event payloads, as the event body is empty. | ||
While there's less opportunity for attacks using malicious payloads, it's still possible to DOS an EventListener. | ||
Therefore, we should advise users not to expose scheduled EventListener ingresses (there's no clear use case for doing so). | ||
Alternatively, we could include a header for the event with a signature that can be verified by an interceptor. | ||
|
||
In addition, this proposal would also mean the triggers controller has permissions to create, update, and delete CronJobs. | ||
|
||
### Drawbacks | ||
|
||
- We might want to avoid setting a precedent of building functionality into Triggers to trigger on many different types | ||
of events. This proposal couples an event (a time occurring) with a Tekton resource creation, when we may prefer to keep | ||
events and resource creation separate. However, cron jobs are an extremely common simple use case that likely makes sense | ||
to address specifically. | ||
|
||
- We might want to build this functionality into a higher level API like [Workflows](./0098-workflows.md) or a larger | ||
feature like [polling runs](./0083-polling-runs-in-tekton.md). This proposal doesn't prevent that, | ||
and CronTriggers could be leveraged to implement similar functionality in a higher level system. | ||
|
||
- The use of the name "EventListener" for a CRD that doesn't need to "listen" for incoming events may be confusing. | ||
|
||
## Alternatives | ||
|
||
### Create a new CronTrigger CRD | ||
|
||
Example: | ||
|
||
```yaml | ||
apiVersion: triggers.tekton.dev/v1alpha1 | ||
kind: CronTrigger | ||
metadata: | ||
name: nightly-release | ||
spec: | ||
schedule: "0 0 * * *" | ||
bindings: | ||
- name: project-name | ||
value: wait-task | ||
- name: triggers-uuid | ||
value: $(context.eventID) | ||
- name: datetime | ||
value: $(context.datetime) | ||
template: | ||
ref: experimental-release-pipeline-template | ||
serviceAccountName: default | ||
cloudEventSink: http://eventlistener.free.beeceptor.com | ||
``` | ||
|
||
CronTriggers don't support interceptors, and cannot be used in EventListeners. | ||
The `schedule` field uses the same syntax as Kubernetes CronJobs. | ||
`serviceAccountName` defaults to "default", and `cloudEventSink` is optional. | ||
|
||
Bindings for CronTriggers are optional and don't support `$(body.foo)` or `$(header.foo)` syntax. | ||
They support variable replacement for $(context.eventID), a UUID for the event, which is already supported in Triggers. | ||
|
||
Pros: | ||
- No need to worry about handling validation errors for interceptors, especially in referenced Triggers | ||
|
||
Cons: | ||
- Awkward syntax for creating many Triggers with the same schedule, unlike TriggerGroups | ||
- Reuses many features from EventListener | ||
|
||
### Add schedule to Trigger CRD | ||
|
||
Example: | ||
|
||
```yaml | ||
kind: Trigger | ||
spec: | ||
schedule: "0 0 * * *" | ||
bindings: | ||
- name: project-name | ||
value: wait-task | ||
- name: triggers-uuid | ||
value: $(context.eventID) | ||
- name: datetime | ||
value: $(context.datetime) | ||
template: | ||
ref: experimental-release-pipeline-template | ||
``` | ||
|
||
Triggers with both a `schedule` and `interceptors` would result in a validation error. | ||
Inline TriggerBindings using `$(body.foo)` and `$(header.foo)` syntax would also result in a validation error. | ||
|
||
Unlike a Trigger without a `schedule`, a Trigger with a `schedule` can create resources without being used in an | ||
EventListener, using the default serviceAccount. (We could also add a `serviceAccountName` field to the Trigger CRD, | ||
which would override a `serviceAccountName` specified in any EventListeners.) If used in an EventListener, an incoming | ||
event could trigger this Trigger at any time, using the `serviceAccountName` specified in the EventListener. | ||
|
||
### Create a PingSource | ||
|
||
This CRD would be extremely similar to the [Knative Eventing PingSource](https://knative.dev/docs/eventing/sources/ping-source), | ||
without requiring installation of Knative Eventing. | ||
|
||
For example: | ||
|
||
```yaml | ||
apiVersion: triggers.tekton.dev/v1alpha1 | ||
kind: PingSource | ||
metadata: | ||
name: nightly-release | ||
spec: | ||
schedule: "0 0 * * *" | ||
sink: | ||
ref: | ||
name: my-eventlistener | ||
``` | ||
|
||
This would send an empty event body to the EventListener, and we could later add support for a fixed | ||
payload if desired. | ||
|
||
Pros: | ||
- Avoids coupling eventing with resource creation | ||
- Adding support for fixed payloads allows Triggers that do process event bodies to be reused on a cron schedule | ||
|
||
Cons | ||
- Reimplements same functionality as Knative | ||
- More verbose than proposed solution | ||
|
||
## Implementation Plan | ||
|
||
Create a CronJob which sends an empty event body to the EventListener service. | ||
|
||
## Implementation Pull Requests | ||
|
||
<!-- | ||
Once the TEP is ready to be marked as implemented, list down all the GitHub | ||
merged pull requests. | ||
|
||
Note: This section is exclusively for merged pull requests for this TEP. | ||
It will be a quick reference for those looking for implementation of this TEP. | ||
--> | ||
|
||
## References | ||
|
||
- [[feature proposal] Alternate ways of running triggers](https://github.com/tektoncd/triggers/issues/504) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters