diff --git a/teps/0056-pipelines-in-pipelines.md b/teps/0056-pipelines-in-pipelines.md index 08bff562d..a2a651e39 100644 --- a/teps/0056-pipelines-in-pipelines.md +++ b/teps/0056-pipelines-in-pipelines.md @@ -2,283 +2,388 @@ status: proposed title: Pipelines in Pipelines creation-date: '2021-03-08' -last-updated: '2021-08-16' +last-updated: '2022-05-03' authors: - '@jerop' +- '@abayer' +see-also: +- TEP-0044 +- TEP-0050 +- TEP-0059 +- TEP-0084 +- TEP-0090 +- TEP-0100 --- # TEP-0056: Pipelines in Pipelines - + - [Summary](#summary) + - [Motivation](#motivation) + - [Composability](#composability) + - [Reusability](#reusability) + - [Failure Strategies](#failure-strategies) + - [Skipping Strategies](#skipping-strategies) + - [Data Locality and Pod Overhead](#data-locality-and-pod-overhead) + - [Software Supply Chain Security](#software-supply-chain-security) + - [Fanning Out Pipelines](#fanning-out-pipelines) + - [Requirements](#requirements) + - [References](#references) + + +## Summary -To get started with this template: +Today, users can define and execute `Tasks` and `Custom Tasks` in `Pipelines`. In this TEP, we propose +allowing users to define and execute `Pipelines` in `Pipelines`, alongside `Tasks` and `Custom Tasks`. -- [ ] **Fill out this file as best you can.** - At minimum, you should fill in the "Summary", and "Motivation" sections. - These should be easy if you've preflighted the idea of the TEP with the - appropriate Working Group. -- [ ] **Create a PR for this TEP.** - Assign it to people in the SIG that are sponsoring this process. -- [ ] **Merge early and iterate.** - Avoid getting hung up on specific details and instead aim to get the goals of - the TEP clarified and merged quickly. The best way to do this is to just - start with the high-level sections and fill out details incrementally in - subsequent PRs. +## Motivation -Just because a TEP is merged does not mean it is complete or approved. Any TEP -marked as a `proposed` is a working document and subject to change. You can -denote sections that are under active debate as follows: +A `Pipeline` is a collection of `PipelineTasks` that are connected through resource dependencies (such as `Results`) +and ordering dependencies (via `runAfter`). A `Pipeline` is executed as a directed acyclic graph where each +`PipelineTask` is a node, the ordering & resource dependencies define edges, and connected `PipelineTasks` make up +`Branches`. A `Pipeline` is executed through a `PipelineRun` that creates a corresponding `TaskRun` for each +`PipelineTask` in the `Pipeline`. + +While the above workflow is simple, it presents the following challenges and limitations: +- [Composability](#composability) +- [Reusability](#reusability) +- [Failure Strategies](#failure-strategies) +- [Skipping Strategies](#skipping-strategies) +- [Data Locality and Pod Overhead](#data-locality-and-pod-overhead) +- [Software Supply Chain Security](#software-supply-chain-security) +- [Fanning Out Pipelines](#fanning-out-pipelines) + +### Composability + +Today, a subset of `Tasks` in a `Pipeline` cannot be grouped together as a unit of execution within the `Pipeline`. +Users need to define a set of `Tasks` as a complete unit of execution. The grouping of sets of `Tasks` as units of +execution would also improve visualization of `Pipelines`. + +As a `Pipeline` author, I need to define a set of `Tasks` as a complete unit of execution within a `Pipeline`. For +example, I have 5 `Tasks` that apply templates including a `DeploymentConfig`. After the 5 `Tasks` are completed, +I have 3 other `Tasks` that add `ConfigMaps` and `Secrets` to the `DeploymentConfig`. I need to specify that the second +set of `Tasks` all need to wait for the first set of `Tasks` to complete execution. Today, I'd have to add each of the +5 `Task` names to the `runAfter` section of each of the 3 `Task` names - adding up to 15 items in `runAfter` that I +have to maintain. ``` -<<[UNRESOLVED optional short context or usernames ]>> -Stuff that is being argued. -<<[/UNRESOLVED]>> + git-clone + | + v + build + | + v + ---------------------------------------------------------- + | | | | | + v v v v v + apply-configmap apply-pvc apply-route apply-service apply-dc + ---------------------------------------------------------------------- + | | | + v v v + add-configmap add-columna-service add-kafka-config + ------------------------------------------------------------ + | + v + deploy ``` -When editing TEPS, aim for tightly-scoped, single-topic PRs to keep discussions -focused. If you disagree with what is already in a document, open a new PR -with suggested changes. +Instead, I want to define and distribute `apply-config` set of 5 `Tasks` and `add-config` set of 3 `Tasks` so that I +can specify that the latter waits for the former to complete execution. -If there are new details that belong in the TEP, edit the TEP. Once a -feature has become "implemented", major changes should get new TEPs. +``` + git-clone + | + v + build + | + v + apply-config + | + v + add-config + | + v + deploy +``` -The canonical place for the latest set of instructions (and the likely source -of this file) is [here](/teps/NNNN-TEP-template/README.md). +For further information, read [Tekton Pipelines Issue #2134][issue-2134] and [Tekton Pipelines Issue #4067][issue-4067]. ---> +### Reusability - +Today, a subset of `Tasks` in a `Pipeline` cannot be distributed as a unit of execution within `Pipelines`. As +such, users have to specify those related `Tasks` separately and repeatedly across many `Pipelines`. - +For example, I can define and distribute `set-sta` set of `Tasks` and `testing` set of `Tasks`: - -- [Summary](#summary) -- [Motivation](#motivation) - - [Reusability and Composability](#reusability-and-composability) - - [Failure Strategies](#failure-strategies) - - [Goals](#goals) - - [Non-Goals](#non-goals) - - [Use Cases](#use-cases) - - [Reusability and Composability](#reusability-and-composability-1) - - [Linting and Testing](#linting-and-testing) - - [Apply and Add Configuration](#apply-and-add-configuration) - - [Failure Strategies](#failure-strategies-1) -- [Requirements](#requirements) -- [References](#references) - +``` + git-clone + | + v + run-unit-tests-with-status + | + v + run-scans +``` -## Summary +Where `run-unit-tests-with-status` is made up of `set-status`, `unit-tests` and `set-status` set of `Tasks`: - +Today, when a `Task` in a `Branch` fails, it stops the execution of unrelated `Branches` and the `Pipeline` as a whole. +When `Tasks` are specified in independent `Branches`, there are no dependencies between them, so users may expect that +a failure in one `Branch` would not stop the execution of the other `Branch`. -To improve the reusability, composability and failure strategies in Tekton Pipelines, this TEP addresses defining and executing Pipelines in Pipelines. This TEP scopes the problem, describes the use cases, and identifies the goals and constrains/requirements for the solution. +Users need a way to prevent the failure of unrelated `Tasks` from affecting the execution of set of related `Tasks` +that should execute to completion once the first one has started. -## Motivation +As a `Pipeline` author, I need to decouple failures in unrelated sets of `Tasks`. For example, I can design a +`Pipeline` where `lint` might fail, but the `unit-tests`, `integration-tests` and `report-test-results` will +continue executing so that I can get the test results without a rerun of the `Pipeline`. - +The above is possible because we don't interrupt execution upon first failure, instead we don't schedule anything +new and wait for ongoing execution to complete. -A `Pipeline` is a collection of `Tasks` that are connected through resource dependencies (such as `Results`) and ordering dependencies (via `runAfter`). The `Pipeline` is executed as a directed acyclic graph where each `Task` is a node, the ordering/resource dependencies define edges, and connected `Tasks` make up `Branches`. The `Pipeline` is executed through a `PipelineRun` that creates a corresponding `TaskRun` for each `Task` in the `Pipeline`. While the above workflow is simple, it has limitations in terms of composability, reusability and failure strategies in `Pipelines`. +For related work, read [TEP-0050][tep-0050]. -#### Reusability and Composability +### Skipping Strategies -Today, a subset of `Tasks` in a `Pipeline` cannot be grouped together and distributed as a unit of execution within the `Pipeline`. As such, users have to specify those related `Tasks` separately and repeatedly across many `Pipelines`. +Today, users guard the execution of a `PipelineTask` using `when` expressions. The declared `when` expression are +evaluated before a `PipelineTask` is executed. If the `when` expressions evaluate to `"false"`, the `PipelineTask` +is skipped and the dependent `PipelineTasks` continue execution. To guard a `PipelineTask` and its dependent +`PipelineTasks`, a user has to cascade the `when` expressions to the dependent `PipelineTasks` - this is verbose and +error-prone as shown in the example below. -Users need to define and share a set of `Tasks` as a complete unit of execution. +As a `Pipeline` author, I need to guard `manual-approval` and its dependent `Tasks` - `build-image`, `deploy-image` +and `slack-msg` - in a `Pipeline` based on the git operation triggering the `Pipeline` being a merge action. Today, +I'd have to cascade that `when` expression across the four `PipelineTasks`. +``` + tests + | + v + manual-approval + | | + v (approver) + build-image | + | v + v slack-msg + deploy-image +``` -The grouping of sets of `Tasks` as units of execution would also improve visualization of `Pipelines`. +I need to combine those four `PipelineTasks` into one `Pipeline` - let's refer to this `Pipeline` as +`approval-build-deploy-slack`: -#### Failure Strategies +``` + manual-approval + | | + v (approver) + build-image | + | v + v slack-msg + deploy-image +``` -Today, when a `Task` in a `Branch` fails, it stops the execution of unrelated `Branches` and the `Pipeline` as a whole. When `Tasks` are specified in independent `Branches`, there are no dependencies between them, so users may expect that a failure in one `Branch` would not stop the execution of the other `Branch`. +Then, I can guard and execute the above `Pipeline` within the main `Pipeline`: -Users need a way to prevent the failure of unrelated `Tasks` from affecting the execution of set of related `Tasks` that should execute to completion once the first one has started. +``` + tests + | + v + approval-build-deploy-slack +``` -### Goals +Users have been using the `Pipeline` in `Pipeline` `Custom Task` to guard a `PipelineTask` and its dependent +`PipelineTasks`. For further information, read the [documentation][when] and [TEP-0059][tep-0059]. - +### Data Locality and Pod Overhead -- Defining a set of `Tasks` as a complete unit of execution -- Decoupling failures in unrelated sets of `Tasks` +In [TEP-0044][tep-0044], we are exploring supporting executing a `Pipeline` in a `Pod` to provide data locality and +reduce pod overhead. Users will need a way to group a set of `Tasks` in a `Pipeline` that should execute in a `Pod`. -### Non-Goals +As a `Pipeline` author, I need to define a subset of `Tasks` in a `Pipeline` that should execute in a `Pod`. For +example, I need `fetch-source`, `unit-tests` and `upload-results` set of `Tasks` to execute in one `Pod` while +`update-slack` to execute in its own `Pod`: - +``` + fetch-source + | + v + unit-tests + | + v + upload-results + | + v + update-slack +``` -- Ignoring `Task` failures, which is addressed in [TEP-0050 Ignore Task Failures](https://github.com/tektoncd/community/blob/main/teps/0050-ignore-task-failures.md) -- Composing `Tasks` in `Tasks`, which is addressed in [TEP-0044 Composing Tasks with Tasks](https://github.com/tektoncd/community/pull/316) +I need to combine `fetch-source`, `unit-tests` and `upload-results` set of `Tasks` into one `Pipeline` - let's +refer to this `Pipeline` as `fetch-test-upload`: -### Use Cases +``` + fetch-source + | + v + unit-tests + | + v + upload-results +``` - +``` + fetch-test-upload + | + v + update-slack +``` -#### Reusability and Composability +### Software Supply Chain Security -As a `Pipeline` author, I need to define a set of `Tasks` as a complete unit of execution that I can share across `Pipelines`. +In [TEP-0084][tep-0084], we are exploring generating `PipelineRun` level provenance in *Tekton Chains* to meet +[SLSA][slsa] L2 requirements and support secure software supply chain. Users will need to validate the provenance +generated from a set of `Tasks` in a `Pipeline` before proceeding with execution. -###### Linting and Testing +As a `Pipeline` author, I need to define a subset of `Tasks` in a `Pipeline` whose provenance I need to validate +before executing subsequent Tasks. For example, I need `fetch-source` and `build-image` end-to-end provenance validated +before executing `deploy-image`: -For example, I can define and distribute `linting` set of `Tasks` and `testing` set of `Tasks`: ``` - linting + fetch-source + | + v + build-image | v - testing + deploy-image ``` -where `linting` is made up of `lint` and `report-linter-output` tasks: -``` - lint +I need to combine `fetch-source` and `build-image` set of `Tasks` into one `Pipeline` - let's refer to this +`Pipelines` as `fetch-source-build-image`: + +``` + fetch-source | v - report-linter-output + build-image ``` +Then I can validate the end-to-end provenance generated from the above `Pipeline` before executing `deploy-image`: -and `testing` is made up of `unit-tests`, `integration-tests` and `report-test-results` `Tasks`: -``` - unit-tests +``` +fetch-source-build-image | - v - integration-tests - | - v - report-test-results + v + deploy-image ``` -###### Apply and Add Configuration - -For example, I have 5 `Tasks` that apply templates including a DeploymentConfig. After the 5 tasks are completed, I have 3 other `Tasks` that add ConfigMaps and Secrets to the DeploymentConfig. +In addition, a user [described][slack] how `Pipelines` in `Pipelines` would allow them to define and distribute +`Pipelines` to meet their security requirements, including separation of concerns between different roles: -I need to specify that the second set of `Tasks` all need to wait for the first set of `Tasks` to complete execution. +> We want to use different Pipelines for building images and for scanning vulnerabilities because they are built by +different people: developers and security experts. Adding the Tasks to scan images in all Pipelines that build them is +less maintainable. Pipelines in Pipelines fits perfectly for this. -Today, I'd have to add each of the 5 `Task` names to the `runAfter` section of each of the 3 `Task` names - adding up to 15 items in `runAfter` that I have to maintain. +### Fanning Out Pipelines -``` - git-clone - | - v - build - | - v - ---------------------------------------------------------- - | | | | | - v v v v v - apply-configmap apply-pvc apply-route apply-service apply-dc - ---------------------------------------------------------------------- - | | | - v v v - add-configmap add-columna-service add-kafka-config - ------------------------------------------------------------ - | - v - deploy -``` +In [TEP-0090][tep-0090], we proposed fanning out `PipelineTasks` with substitutions from combinations of `Parameters` +in a `Matrix`. So far, it'd support fanning out `Tasks` into multiple `TaskRuns` and `Custom Tasks` into multiple +`Runs`. Users need a way to fan out `Pipelines` into multiple `PipelineRuns` as well. -Instead, I want to define and distribute `apply-config` set of 5 `Tasks` and `add-config` set of 3 `Tasks` so that I can specify that the latter waits for the former to complete execution. +As a `Pipeline` author, I have a `Pipeline` with several `Tasks` that validate a repository meets compliance and +security requirements then sends out a notification with the outcomes to the security team. For example, the `Tasks` +include `fetch-source`, [`scorecard`][scorecard], [`codeql`][codeql] and `notification`: -``` - git-clone +``` + fetch-source | - v - build - | - v - apply-config + v + scorecards | - v - add-config - | - v - deploy + v + codeql + | + v + notification ``` -#### Failure Strategies +The above `Pipeline` needs to be run on several repositories in my organization; I need to pass an array repository +names as a `Parameter` to a `PipelineTask` that has the above `Pipeline` within a `Pipeline`. -As a `Pipeline` author, I need to decouple failures in unrelated sets of `Tasks`. +In addition, a user [shared][matrix-uc] a related use case for supporting `Matrix` at the `Pipeline` level: -For example, I can design a `Pipeline` where `lint`might fail, but the `unit-tests`, `integration-tests` and `report-test-results` will continue executing so that I can get the test results without a rerun of the `Pipeline`: - -``` - lint unit-tests - | | - v v - report-linter-output integration-tests - | - v - report-test-results -``` +> There is a Pipeline which clones a node-based project and then we want to test that repo on different versions of +nodejs, ie, node-12, node-14 and node-16. ## Requirements - - -- Users should be able to define and distribute a set of `Tasks` as a complete unit of execution -- Users should be able decouple failures in unrelated sets of `Tasks` -- Users should be able to pass inputs (such as `Parameters`) from the main-`Pipeline` to the sub-`Pipeline` -- Users should be able to access outputs (`Results`) from the sub-`Pipeline` in the main-`Pipeline` -- Users should be able to access the status (`ConditionSucceeded`) of the sub-`Pipeline` in the main-`Pipeline` -- Users should be able to propagate actions from the main-`Pipeline` to the sub-`Pipeline`, such as deletion and cancellation +1. Users should be able to define and distribute a set of `PipelineTasks` as a complete unit of execution. +2. Users should be able decouple failures in unrelated sets of `PipelineTasks`. +3. Users should be able to pass inputs (such as `Parameters`) from the main-`Pipeline` to the sub-`Pipeline`. +4. Users should be able to access outputs (`Results`) from the sub-`Pipeline` in the main-`Pipeline`. +5. Users should be able to access sufficient information about the sub-`PipelineRun` from the status of the +main-`PipelineRun` to be able to fetch and access the sub-`PipelineRun`'s full status. +6. Users should be able to propagate actions from the main-`Pipeline` to the sub-`Pipeline`, such as deletion and +cancellation. ## References - -- [Issue #2134: Support using a PipelineTask in the Pipeline CRD to run other Pipelines the same way we run a Task](https://github.com/tektoncd/pipeline/issues/2134) -- [Issue #4067: Add a gateway task or grouping for pipelines](https://github.com/tektoncd/pipeline/issues/4067) -- [Project Proposal](https://github.com/tektoncd/community/issues/330) -- [Experimental Project](https://github.com/tektoncd/experimental/tree/main/pipelines-in-pipelines) -- [Original Proposal](https://docs.google.com/document/d/14Uf7XQEnkMFBpNYRZiwo4dwRfW6do--m3yPhXHx4ybk/edit) +- Issues + - [Issue #2134: Support using a PipelineTask in the Pipeline CRD to run other Pipelines the same way we run a Task][issue-2134] + - [Issue #4067: Add a gateway task or grouping for pipelines][issue-4067] +- Experiments + - [Experimental Project Proposal][experiment-proposal] + - [Pipelines in Pipelines Custom Task][pip] +- Proposals + - [TEP-0044: Data Locality and Pod Overhead in Pipelines][tep-0044] + - [TEP-0050: Ignore Task Failures][tep-0050] + - [TEP-0059: Skipping Strategies][tep-0059] + - [TEP-0084: End-to-End Provenance Collection][tep-0084] + - [TEP-0090: Matrix][tep-0090] + - [TEP-0100: Embedded TaskRuns and Runs Status in PipelineRuns][tep-0100] + - [Original Proposal][doc] + +[tep-0044]: 0044-data-locality-and-pod-overhead-in-pipelines.md +[tep-0050]: 0050-ignore-task-failures.md +[tep-0059]: 0059-skipping-strategies.md +[tep-0084]: 0084-endtoend-provenance-collection.md +[tep-0090]: 0090-matrix.md +[tep-0100]: 0100-embedded-taskruns-and-runs-status-in-pipelineruns.md +[pip]: https://github.com/tektoncd/experimental/tree/main/pipelines-in-pipelines +[doc]: https://docs.google.com/document/d/14Uf7XQEnkMFBpNYRZiwo4dwRfW6do--m3yPhXHx4ybk/edit +[experiment-proposal]: https://github.com/tektoncd/community/issues/330 +[issue-4067]: https://github.com/tektoncd/pipeline/issues/4067 +[issue-2134]: https://github.com/tektoncd/pipeline/issues/2134 +[when]: https://github.com/tektoncd/pipeline/blob/main/docs/pipelines.md#guarding-a-task-and-its-dependent-tasks +[slack]: ../teps/images/0056-slack-thread.png +[slsa]: https://slsa.dev/ +[scorecard]: https://github.com/ossf/scorecard +[codeql]: https://github.com/github/codeql +[matrix-uc]: https://github.com/tektoncd/community/pull/600#pullrequestreview-851817251 +[status-test]: https://github.com/tektoncd/pipeline/issues/2134#issuecomment-631552148 diff --git a/teps/0081-add-chains-subcommand-to-the-cli.md b/teps/0081-add-chains-subcommand-to-the-cli.md index 0b664d07c..12dc5fcef 100644 --- a/teps/0081-add-chains-subcommand-to-the-cli.md +++ b/teps/0081-add-chains-subcommand-to-the-cli.md @@ -1,54 +1,16 @@ --- -status: implementable +status: implemented title: Add Chains sub-command to the CLI -creation-date: '2021-08-31' -last-updated: '2021-10-21' +creation-date: "2021-08-31" +last-updated: "2022-04-27" authors: -- '@rgreinho' + - "@rgreinho" --- # TEP-0081: Add Chains sub-command to the CLI - - + - [Summary](#summary) - [Motivation](#motivation) - [Goals](#goals) @@ -80,10 +42,11 @@ by adding a new command to the Tekton CLI. When working with `Chains`, the user experience will be enhanced if users are able to: -* use the Tekton CLI rather than a combination of other tools like `kubectl`, -`jq`, and `base64` -* not having to memorize which exact TaskRun annotation or key to query. -* discover available `Chains` features via the CLI and/or its documentation. + +- use the Tekton CLI rather than a combination of other tools like `kubectl`, + `jq`, and `base64` +- not having to memorize which exact TaskRun annotation or key to query. +- discover available `Chains` features via the CLI and/or its documentation. ### Goals @@ -95,9 +58,9 @@ While the idea is to use the Tekton CLI to replace a combination of shell commands, we may not want to implement all exotic variations and focus only on the most common use cases in order to avoid overloading the `chains` command. -A command allowing to configure Tekton Chains. While it would be a great -feature to have, ths ideal implementation would require creating a new command, -for instance `tkn adm chains`. This will be part of a future TEP. +A command allowing to configure Tekton Chains. While it would be a great feature +to have, ths ideal implementation would require creating a new command, for +instance `tkn adm chains`. This will be part of a future TEP. ### Use Cases @@ -162,7 +125,7 @@ kubectl get taskrun $TASKRUN -o=json \ Change the provenance format: ```bash -$ tkn chains format in-toto +tkn chains format in-toto ``` instead of: @@ -176,9 +139,9 @@ instead of: #### Other Use Case ideas -* Generate and configure `cosign` keys -* Verify `cosign` signatures -* Validate `in-toto` layout +- Generate and configure `cosign` keys +- Verify `cosign` signatures +- Validate `in-toto` layout ## Requirements @@ -225,9 +188,9 @@ import the `chains` module, there won't be any issue. ### User Experience -* Keep the CLI simple -* Ensure auto-completion is available -* Keep only to 2 levels of commands, i.e `tkn [parameter]...` +- Keep the CLI simple +- Ensure auto-completion is available +- Keep only to 2 levels of commands, i.e `tkn [parameter]...` ## Design Details @@ -242,14 +205,8 @@ DRYer. ## Test Plan -* Unit test and e2e tests will be added or updated to the `chains` module. -* For the CLI, the tests should be similar to any other tekton command. - -## Design Evaluation - +- Unit test and e2e tests will be added or updated to the `chains` module. +- For the CLI, the tests should be similar to any other tekton command. ## Drawbacks @@ -260,27 +217,19 @@ Why should this TEP _not_ be implemented? ## Alternatives The alternative is to use a combination of shell tools and to know which exact -annotation or key to query/update. It was ruled out since it complicates -the operations for no good reason. See the +annotation or key to query/update. It was ruled out since it complicates the +operations for no good reason. See the [Use Cases (optional)](use-cases-optional) section for some examples. -One other alternative would be that chains provides a `tkn-chains` binary, -and with the "execution model" we have in `tkn`, it would appear as a -subcommand.One downside of this, is that it wouldn't be available by default and -would complicate a bit the "packaging part". I'd rather have the chains command -in, and secure by default (if history teach us anything is that things not -enable or shipped by default are less adopted 😓) +One other alternative would be that chains provides a `tkn-chains` binary, and +with the "execution model" we have in `tkn`, it would appear as a subcommand.One +downside of this, is that it wouldn't be available by default and would +complicate a bit the "packaging part". I'd rather have the chains command in, +and secure by default (if history teach us anything is that things not enable or +shipped by default are less adopted 😓) [[ref](https://github.com/tektoncd/community/pull/508#discussion_r712816640)]. ## Implementation Pull request(s) -* -* - -## References (optional) - - +- +- diff --git a/teps/0086-changing-the-way-result-parameters-are-stored.md b/teps/0086-changing-the-way-result-parameters-are-stored.md new file mode 100644 index 000000000..83700a9ed --- /dev/null +++ b/teps/0086-changing-the-way-result-parameters-are-stored.md @@ -0,0 +1,426 @@ +--- +status: proposed +title: Changing the way result parameters are stored +creation-date: '2021-09-27' +last-updated: '2022-04-07' +authors: +- '@tlawrie' +- '@imjasonh' +- '@bobcatfish' +- '@pritidesai' +--- + +# TEP-0086: Changing the way result parameters are stored + + +- [Summary](#summary) +- [Motivation](#motivation) + - [Goals](#goals) + - [Non-Goals](#non-goals) + - [Use Cases (optional)](#use-cases-optional) +- [Requirements](#requirements) + - [Required](#required) +- [Alternatives](#alternatives) + - [Result Sidecar - Upload results from sidecar](#result-sidecar---upload-results-from-sidecar) + - [Option: Supporting multiple sidecars](#option-supporting-multiple-sidecars) + - [Risks and Mitigations](#risks-and-mitigations) + - [User Experience (optional)](#user-experience-optional) + - [Performance (optional)](#performance-optional) + - [Design Evaluation](#design-evaluation) + - [Design Details](#design-details) + - [Considerations](#considerations) + - [Open Design Questions](#open-design-questions) + - [Test Plan](#test-plan) + - [Drawbacks](#drawbacks) + - [Result References vs results in TaskRun](#result-references-vs-results-in-taskrun) + - [N Configmaps Per TaskRun with Patch Merges (c).](#n-configmaps-per-taskrun-with-patch-merges-c) + - [CRD](#crd) + - [Notes/Caveats](#notescaveats) + - [Dedicated HTTP Service](#dedicated-http-service) + - [Self-update / mutate the TaskRun via admission controller](#self-update--mutate-the-taskrun-via-admission-controller) + - [Separate Database](#separate-database) + - [Store results on PVCs](#store-results-on-pvcs) + - [No change. Use workspaces.](#no-change-use-workspaces) + - [Repurpose Artifact Storage API](#repurpose-artifact-storage-api) + - [Using logs emitted by the Task](#using-logs-emitted-by-the-task) +- [Infrastructure Needed (optional)](#infrastructure-needed-optional) +- [Upgrade & Migration Strategy (optional)](#upgrade--migration-strategy-optional) +- [Implementation Pull request(s)](#implementation-pull-requests) +- [Next steps to unblock](#next-steps-to-unblock) +- [References (optional)](#references-optional) + + +## Summary + +To enhance the usage experience of a [Tasks Results](https://tekton.dev/docs/pipelines/tasks/#emitting-results) by end users, we want to change the way Results are stored to allow for greater storage capacity yet with the current ease of [reference](https://tekton.dev/docs/pipelines/variables/#variables-available-in-a-pipeline) and no specific additional dependencies such as a storage mechanism. + +The current way that Results are reported via a containers `terminationMessage` imposes a limit of 4 KB per step, and 12 KB total per TaskRun. + +## Motivation + +The ability to improve Task Result storage size as part of a TaskRun while allowing the Task to continue to use the +[`results`](https://github.com/tektoncd/pipeline/blob/main/docs/tasks.md#emitting-results) feature and without needing +to use other mechanisms such as [workspaces](https://github.com/tektoncd/pipeline/blob/main/docs/tasks.md#specifying-workspaces). + +Additionally, this will help projects that wrap/abstract Tekton where users understand how to reference Task Results between tasks and don't have the ability to adjust a Task to retrieve from a storage path. Part of the motivation for me putting this TEP together is around making that easier. With my [project](https://github.com/boomerang-io) end users run tasks without knowing YAML, they drag and drop tasks on a GUI. + +### Goals + +* Allow larger storage than the current 4096 bytes of the Termination Message. +* Provide a mechanism to plug an external storage to store large results. + +### Non-Goals + +* Not attempting to solve the storage of blobs or large format files such as JARs + +### Use Cases (optional) + +1. Provide Task authors and end users the ability to store larger Results, such as JSON payloads from an HTTP call, that they can inspect later or pass to other tasks without the need to understand storage mechanisms. + +2. The Tekton operator / administrator not dependent on maintaining a storage solution and removing a complex barrier for some installations + +3. Store a CloudEvent payload as a Result for subsequent tasks to reference and process. + +4. _Potential_ Ability to use JSONPath on Results with JSON data to be able to reference specific elements in the contents. + - Do we add this as part of the scope? Not only change the storage but update the access method to build on top of **TEP-0080: Support domain-scoped parameter/result names** to allow access to the contents of Results through JSONPath scoping? + +5. For projects wrapping or extending Tekton, such as with [Boomerang Flow](https://useboomerang.io) the end users may not know about adjusting Tasks to work with Workspaces. In this instance, they drag and drop tasks on a no-code UI and can only pass parameters around. Additional other extensions may also not know or understand storage systems. + +6. emit structured results, e.g. multiple built image results from a task (see https://github.com/tektoncd/pipeline/issues/4282 for a relevant release pipeline failure, and [TEP-0075](https://github.com/tektoncd/pipeline/issues/4282) and [TEP-0076](https://github.com/tektoncd/community/pull/477) for structured result support) <-- or this could just be part of item (1) + +7. The ability to emit [SBOMs](https://en.wikipedia.org/wiki/Software_bill_of_materials) as results from Tasks and make them easily consumable by tools observing execution (e.g. Tekton Chains) without requiring those tools to mount and access volumes + +## Requirements + + +* Allow users to reference a Task Result in its current form `$(tasks.Task Name.results.Result Name)` +* Use existing objects (or standard ones incl CRDs) where the complexity _can_ be abstracted from a user. +* Allow flexibility in the design for additional plug and play storage mechanisms. +* Ensure secure RBAC is in place. +* The default mechanism for storing results out of the box should not require giving the Tekton Controller any ability + to modify Roles or RoleBindings (i.e. it should not require that Tekton dynamically change the permissions of the + ServiceAccount executing the Task that emits results). +* It must be clear from looking at a Task whether or not a Tekton installation can support the results storage + requirements (i.e. we want to avoid having Tasks that require writing huge results and finding out at runtime that + the backing storage used by a Tekton installation doesn't support it). +* Allow flexibility in the design such that the TaskRun status continue to be the source of truth for the contents of the result. + This flexible design must benefit the use cases which must avoid results in the TaskRun status. + * Some important notes/limitations with having results in the TaskRun: + * This requirement can potentially introduce an upper bound on the result size that is limited by + [the total allowed size of a CRD](https://github.com/kubernetes/kubernetes/issues/82292). + * This may mean sensitive information can never be stored in a result (maybe that is a reasonable restriction). + * This may also prevent encrypting results (unless they are encrypted within the TaskRun itself). + * Define a clear upper limit on the expected maximum size of a result. + * Support an environment where executing pods are not permitted to make network connections within the cluster. + +## Alternatives + +### Result Sidecar - Upload results from sidecar + +In this solution we include a sidecar in all pods that back TaskRuns which waits for individual steps to write results +and then writes these results somewhere else, so they can be stored and made available. + +**Sidecar API:** + +1. The controller is passed a flag, -sidecar-image= +2. This image is added as a container in every TaskRun Pod, with each steps’ results emptyDir volume attached as read–only, and params emptyDir volumes attached as read-write. +3. Watch directory, and any time it sees a result file appear, it writes that content externally (GCS, datastore, cuneiform tablets, the moon) +it must be able to produce an opaque string that represents that result value, which it writes to TaskRun status +> TODO: Do we achieve this via terminationMessage? We can enforce that these opaque strings be small; otherwise, ConfigMap? – an example signed URL is 824 bytes, this limits to ~12 per TaskRun. +4. The TaskRun controller updates the status to include that opaque string +5. When the next TaskRun starts, for each passed-in param that’s passed by reference, the TaskRun controller passes opaque reference strings to the sidecar along with the associated param name. the sidecar dereferences the opaque strings and writes the real param value to the param value file mounted into steps. +6. The sidecar reports READY only after these steps are complete, allowing the first step to begin as normal. + +#### Option: Supporting multiple sidecars + +With this API in place, Tekton can provide an implementation that writes results to a centralized HTTP service and other +operators can implement their own that write results to cluster-local persistent volumes, external object storage, +document store, relational database, etc. + +Implementations should take care to ensure the integrity of result/param contents: + +- ideally, content-addressed for tamper-evidence +- ideally, incremental for speed and cost efficiency +- ideally, with tight access controls to prevent tampering and leakage + for example, an implementation that stored contents in GCS could use signed URLs to only authorize one POST of object contents, only authorize GETs for only one hour, and delete the object contents entirely after one day. + +However, we are currently leaning toward using implementations of [the HTTP service](#dedicated-http-service) as the place +to plug in support for different backends instead. + +This alternative provides options for handling a change to result parameter storage and potentially involves adjusting the +`entrypoint` or additional sidecar to write to this storage implementation. + +We need to consider both performance and security impacts of the changes and trade off with the amount of capacity we would gain from the option. + +#### Risks and Mitigations + +* Concern on using kubernetes (backed by etcd) as a database +* Storing results outside a TaskRun means that all systems integrating with Tekton that want access to that + result must now integrate with the results storage + * Mitigation: if we define an interface for accessing results storage, this can at least be limited to integrating + with this one interface +* Complexity of the solution (see [Design Evaluation](#design-evaluation) below). + +#### User Experience (optional) + +* Users must be able to refer to these result parameters exactly as they currently do and still be able to reference in subsequent tasks (i.e. read access) + +#### Performance (optional) + +* Speed: + * Adding any additional communication required in order to write and read results will likely decrease performance +* Storage: + * Supporting larger results may mean storing more results data + +#### Design Evaluation + +* Reusability + * At authoring time, it must be possible to communicate to users if there are any special assumptions a Task is making + about results it expects to be able to emit +* Simplicity + * This makes our implementations more complex, and likley makes administration/operation more complex + * More potential points of failure +* Flexibility + * Can use your own backing storage (depending on [the requirement we use the TaskRun as the source of truth](#requirements)) +* Conformance + * Must be possible to use Tasks across Tekton installations - if a Task expects to be run in an installation that + supports larger Task runs, this must be clear + +#### Design Details + +This approach for recording results coupled with the [*Dedicated HTTP Service*](#dedicated-http-service) +(with a well defined interface that can be swapped out) can help abstract the backend. With this approach the default +backend could be a ConfigMap (or CRD) - or we could even continue to use the TaskRun itself to store results - since +only the HTTP service would need the permissions required to make teh edits (vs a solution where we need to on the fly +configure every service account associated with every taskrun to have this permission). + +##### Considerations + +Overall by using a plug-and-play extensible design, the question of what the storage mechanism is becomes less of an implementation design choice. Instead, the questions now become + +1. **What is the default storage mechanism shipped?** We want to provide a mechanism that does not require storage or additional dependencies. Configmaps is the ideal choice here, even if it creates additional ServiceAccount changes as when it comes time to production, these can be tightened as well as an alternative Results backing mechanism chosen. + +2. **Are we wanting a centralized or distributed design?** If we combine the Result Sidecar with the Dedicated HTTP + Service we potentially get the best of both worlds. A centralized service for security and extensibility. With a + sidecar of reading and processing the results. + +**Auth** +We could use built in k8s OIDC token support to materialize short lived tokens in the pod running the Task for +authentication with the centralized service. For example: + +1. Sidecar reads result from disk +2. Sidecar in the pod gets an OIDC token from k8s +3. Sidecar uses OIDC token to authenticate with HTTP Result storage service +4. Sidecar uploads result +5. HTTP Result storage service records the result + +**Encryption** +Communication between the pods and the HTTP Results storage service could be encrypted. + +**Defined Interface** +The HTTP Results storage service would implement a standardized interface that could be implemented by anyone desiring +to use a different mechanism to store results. TBD: depends on whether or not we have a [requirement](#requirements) +that results are stored on the TaskRun itself + +##### Open Design Questions + +- How should the sidecar report that results-writing or param-getting failed, and how should the TaskRun controller be notified so that the TaskRun can also be failed? +- Do we need the extra byRef boolean in the model? And should byRef become the default always. +- Should the sidecar be responsible for deciding whether the result should be reported by-value or by-reference? Or is that a controller-wide configuration? +- Is passing by-value still useful for small pieces of data to be able to have them inlined in TaskRun/PipelineRun statuses? + +##### Test Plan + +* All end-to-end tests and examples that use results would be updated to setup and use the default result handling + mechanism +* Any additional ways of backing results would need their own set of tests + +#### Drawbacks + +* Increased complexity within Tekton Pipelines execution +* Increased complexity for systems integrating with Tekton Pipelines + +(See [Risks and mitigations](#risks-and-mitigations).) + +### Result References vs results in TaskRun + +Beyond size limits of specific TaskRuns’ results, the fundamental issue is that API objects in etcd are not suitable for +storing arbitrarily large data. + +In this option we introduce a way to pass one TaskRun’s output results into another TaskRun’s input parameters by reference, instead of +only by value as they are today. +The `byRef` could also be configured and handled by the controller and not something that needs to be made explicit at authoring time. +**Example:** + +```yaml +tasks: +- name: first-task + taskSpec: foo + results: + - name: out + byRef: true # <-- *new field* +- name: second-task + taskSpec: bar + params: + - name: in + value: "$(tasks.first-task.results.out)" +``` + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: TaskRun +... +status: + taskResults: + - name: out + valueRef: # <-- *new field* +``` + +**Implementation:** + +Result references require some code to take the contents of `/tekton/results/out` in the container environment, copy +them elsewhere, and mint a unique reference. It also requires some code to take that reference, locate the contents +wherever they are, and make them available to other TaskRuns at `/tekton/params/in`. + +Questions: +- Do we need the extra byRef boolean in the model? And should byRef become the default always. +- Should the sidecar be responsible for deciding whether the result should be reported by-value or by-reference? Or is that a controller-wide configuration? +- Is passing by-value still useful for small pieces of data to be able to have them inlined in TaskRun/PipelineRun statuses? + +### N Configmaps Per TaskRun with Patch Merges (c). + + - As the TaskRun Pod proceeds, the injected entrypoint would write result data from `/tekton/results/foo` to the ConfigMap. After a TaskRun completes, the TaskRun controller would read the associated ConfigMap data and copy it into the TaskRun’s status. The ConfigMap is then deleted. + - **Create N ConfigMaps** for each of N results, and grant the workload access to write to these results using one of these focused Roles: + - https://github.com/tektoncd/pipeline/blob/9c61cdf6d4b7b5e26c787d62447c0eed1c92b68f/config/200-role.yaml#L100 + - The **ConfigMaps**, the Role, and the RoleBinding could all be OwnerRef'd to the **Run**, to deal with cleanup. + - Concerns: + - Results in the pipelines controller being given more power, i.e. to create and delete roles and rolebindings + - Having to create a new **ConfigMap**, Role and RoleBinding per TaskRun, when at the end of the day we don't actually care about updating that **ConfigMap**, but the TaskRun's results. + - Parallelism even with queued Patch Merges + - Increased load on the API server, on the order of 3+ more API requests per TaskRun: + - create the ConfigMap + - update RBAC to the ConfigMap + - (during TaskRun execution) N ConfigMap updates, where N is the number of steps that produce a result. + - (after the TaskRun completes) delete the ConfigMap + - 'scale fail' - The maximum size of a ConfigMap is ~1.5 MB, if the data it reports is copied into the TaskRun status, and again into the aggregated PipelineRun status, the effective maximum result size is ~1.5 MB per PipelineRun. + + +### CRD + + - Help reduce load in the presence of controllers that watch for ConfigMaps cluster-wide + - Minimally limits the accidentally chance of editing with `kubectl edit cm ` + - Similar benefits to ConfigMap from a Role and Rolebinding perspective + - Webhook to validate the write once immutability + +#### Notes/Caveats + +* The storage of the result parameter may still be limited by a number of scenarios, including: + - [1.5 MB CRD size](https://github.com/kubernetes/kubernetes/issues/82292) + - The total size of the PipelineRun _if_ the TaskRun content is included, however + [TEP-100 is removing this](https://github.com/tektoncd/community/blob/main/teps/0100-embedded-taskruns-and-runs-status-in-pipelineruns.md) +* Eventually this may result in running into a limit with etcd overall, however not a problem for now. Can be solved via cleanups / offloading history. +* We want to try and minimize reimplementing access control in a webhook (in part because it means the webhook needs to know which task identities can update which task runs, which starts to get annoyingly stateful) + + + +### Dedicated HTTP Service + + - Potential Auth and HA problems + - Could run as part of the controller + - Could be a separate HTTP server(s) which write to TaskRuns (or even config maps); task pods connect to this server to submit results, this server records the results (means result size would be limited to what can be stored in the CRD but there probably needs to be an upper bound on result size anyway) + +### Self-update / mutate the TaskRun via admission controller + + - With the various controls i.e. first write, subsequent read only + - Potential issue with self updating its own Status + +### Separate Database + + - Introducing an additional database requirement to Tekton to support the storage of information outside of etcd. + +### Store results on PVCs + + - Use PVCs to store results + +Cons: +- Any downsides of PVCs we've encountered in other places (e.g. [TEP-0044 data locality](https://github.com/tektoncd/community/blob/main/teps/0044-data-locality-and-pod-overhead-in-pipelines.md)) +- Any consumer of the results would need to mount the PVC + +### No change. Use workspaces. + + - There is the alternative of storing result parameters as data in a workspace, however Workspaces + - require there has to be a storage mechanism in the cluster that can be shared between Tasks. That can be complex, or have performance issues in itself if using an As A Service that orders the storage at spin-up time. Or forces Tasks to all run on the same node. etc. Storage is a big complex adoption hurdle. + - changes the way end users refer to the result parameter or pass between containers + - requires some tasks to be altered to retrieve data from the file system in a certain location. This makes it difficult to use a library of Tekton Tasks or an abstraction that doesn't provide access to where a parameter comes from. + +### Repurpose Artifact Storage API + + - Already supported by Tekton Pipelines for `PipelineResources` + - Support buckets and temporary PVCs + - Only requires a one-time configuration by operators + - Transparently moves data between tasks in a pipeline + - Currently, tightly coupled with `OutputResources` and `InputResources` but this could evolve + - [Docs on setting up storage](https://github.com/tektoncd/pipeline/blob/main/docs/install.md#configuring-pipelineresource-storage) + - [Interface](https://github.com/tektoncd/pipeline/blob/main/pkg/artifacts/artifacts_storage.go#L39-L47) + +### Using logs emitted by the Task + + - We are also exploring using **stdout logs from a dedicated sidecar to return a json result object** as a simpler way +to support larger TaskResults, but we need to explore this in a POC as we suspect we may not be able to rely on logs for this. + - The controller would wait for the sidecar to exit and then read the logs based on a particular query and append info to the TaskRun + - Potential to use a CloudEvent object to wrap result object + +Cons: +- No guarantees on when logs will be available (would have to wait for this before considering a TaskRun complete) +- No guarantee you'll be able to access a log before it disappears (e.g. logs will not be available via the k8s API + once a pod is deleted) +- The storage of the result parameter may still be limited by a number of scenarios, including: + - [1.5 MB CRD size](https://github.com/kubernetes/kubernetes/issues/82292) + - The total size of the PipelineRun _if_ the TaskRun content is included, however + [TEP-100 is removing this](https://github.com/tektoncd/community/blob/main/teps/0100-embedded-taskruns-and-runs-status-in-pipelineruns.md) + + +## Infrastructure Needed (optional) + + + +## Upgrade & Migration Strategy (optional) + + + +Backwards compatability with the default option using ConfigMaps (or CRD) and the ability to resolve the value. + +Potentially feature flag depending on the object used and security role changes. + +## Implementation Pull request(s) + + + +## Next steps to unblock + +* [x] Determine if WIP [requirements](#requirements) should be included:(esp the requirement that results be stored + on the TaskRun + * Marked this as a requirement with flexible design based on the discussion in the API WG with @skaegi and [TEP-0089](0089-nonfalsifiable-provenance-support.md). +* [ ] Determine if we can agree to an upper limit on the size of a result. +* [ ] POC of a [logs based approach](#using-logs-emitted-by-the-task). + + +## References (optional) + +- [Original issue](https://github.com/tektoncd/pipeline/issues/4012) +- [HackMD Result Collector Sidecar Design](https://hackmd.io/a6Kl4oS0SaOyBqBPTirzaQ) +- [TEP-0086 Design Breakout Session Recording](https://drive.google.com/file/d/1lIqyy1RyZMYOrMCC2CLZD8eOf0NrVeDb/view?usp=sharing) +- [TEP-0086 Design Breakout Session Notes](https://hackmd.io/YU_g27vRS2S5DwfBXDGpYA?view) \ No newline at end of file diff --git a/teps/0101-env-in-pod-template.md b/teps/0101-env-in-pod-template.md new file mode 100644 index 000000000..0ac714dd7 --- /dev/null +++ b/teps/0101-env-in-pod-template.md @@ -0,0 +1,661 @@ +--- +status: proposed +title: Env in POD template +creation-date: '2022-03-17' +last-updated: '2022-05-09' +authors: +- '@rafalbigaj' +- '@tomcli' +--- + +# TEP-0101: Env in POD template + + + + + + + + +- [Summary](#summary) +- [Motivation](#motivation) + - [Goals](#goals) + - [Non-Goals](#non-goals) + - [Use Cases](#use-cases) +- [Requirements](#requirements) +- [Proposal](#proposal) + - [Notes/Caveats (optional)](#notescaveats-optional) + - [Risks and Mitigations](#risks-and-mitigations) + - [User Experience (optional)](#user-experience-optional) + - [Performance (optional)](#performance-optional) +- [Design Details](#design-details) +- [Test Plan](#test-plan) +- [Design Evaluation](#design-evaluation) +- [Drawbacks](#drawbacks) +- [Alternatives](#alternatives) +- [Infrastructure Needed (optional)](#infrastructure-needed-optional) +- [Upgrade & Migration Strategy (optional)](#upgrade--migration-strategy-optional) +- [Implementation Pull request(s)](#implementation-pull-request-s) +- [References (optional)](#references-optional) + + +## Summary + + + +A [Pod template](https://github.com/tektoncd/pipeline/blob/main/docs/podtemplates.md) should support configuration +of environment variables, which are combined with those defined in steps and `stepTemplate`, and then passed to all step containers. +That allows to exclude common variables to the global level as well as overwrite defaults specified +on the particular step level. + +## Motivation + + + +One of the most important motivators for this feature is the ability to eliminate redundant code from +the `PipelineRun` as well as `TaskRun` specification. On average this can reduce 3-5 lines of yaml per +each environment variable per each task in the pipeline. +In case of complex pipelines, which consist of dozen or even hundreds of tasks, any kind of repetition +significantly impacts the final size of `PipelineRun` and leads to resource exhaustion on the +Kubernetes ETCD limitation. + +Besides, users quite frequently are willing to overwrite environment variable values +specified in a `stepTemplate` in the single place when running pipelines. +That helps to optionally pass settings, without a need to define additional pipeline parameters. + +Having an `env` field in the pod template allows to: + +- specify global level defaults, what is important to reduce the size of `TaskRun` and `PipelineRun` +- override defaults from `stepTemplate` at `TaskRun` and `PipelineRun` level + +### Goals + + + +1. The main goal of this proposal is to enable support for specification of environment variables on the global level +(`TaskRun` and `PipelineRun`). + +2. Environment variables defined in the Pod template at `TaskRun` and `PipelineRun` level + take precedence over ones defined in steps and `stepTemplate`. + +3. Allow cluster admin to define a list of cluster-wide forbidden environment variables so that users won't overwritten + important Tekton environment variables such as "HTTP_PROXY". Default cluster-wide environment variables can also be + set in the default pod template settings at the [config-defaults.yaml](https://github.com/tektoncd/pipeline/blob/76e40b5a7b11262bfaa96ae31f28db2009002115/config/config-defaults.yaml#L57). + +### Non-Goals + + + +### Use Cases + + + +1. In the first case, common environment variables can be defined in a single place on a `PipelineRun` level. + Values can be specified as literals or through Kubernetes references. + Variables defined on a `PipelineRun` or `TaskRun` level are then available in all steps. + That allows to simplify the Tekton run resource configuration and significantly reduce the size of + `PipelineRun` and `TaskRun` resource, + by excluding the common environment variables like: static global settings, common values coming from metadata, ... + +2. Secondly, environment variables defined in steps can be easily overwritten by the ones from `PipelineRun` and `TaskRun`. + With that, common settings like API keys, connection details, ... can be optionally overwritten in a single place. + +3. For Cloud Providers, it's very common to inject user credentials using Kubernetes API `valueFrom` to avoid credentials + being exposed to the PodSpec. Since each cloud provider has different credential format, able to assign environment + variables at the `PipelineRun` and `TaskRun` can reuse the same task with different Cloud Provider credentials. + Kubernetes API `valueFrom` can also refe to values in the pod labels/annotations for specific Kubernetes cluster + information such as namespace, application labels, and service annotations. + +4. Allow users to reuse stock Tekton catalogs on different cloud environment by setting up a cloud specific global container + spec. + +## Requirements + + + +1. In the first case, common environment variables can be defined in a single place on a `PipelineRun` level. + Values can be specified as literals or through references. + Variables defined on a `PipelineRun` or `TaskRun` level are then available in all steps. + That allows to significantly reduce the size of `PipelineRun` and `TaskRun` resource, + by excluding the common environment variables like: static global settings, common values coming from metadata, ... + +2. Secondly, environment variables defined in steps can be easily overwritten by the ones from `PipelineRun` and `TaskRun`. + With that, common settings like API keys, connection details, ... can be optionally overwritten in a single place. For + example, if both `PipelineRun` and task `StepTemplate` has environment variables PROXY, it will overwrite the task + `StepTemplate` with the environment variable values inside `PipelineRun`. + +3. Allow cluster admin to define a list of cluster-wide forbidden environment variables in the Tekton `config-defaults` + configmap. When users define environment variables in the Taskrun and Pipelinerun spec, check the list of forbidden + environment variables and throw out a validation error if any of the environment variables is forbidden. + +4. Since there are many places that can define the environment variables with this feature, the precedence order is + a. Global Level Forbidden Environment Variables + b. Global Level Default Environment Variables in Tekton Default Pod Template + c. PipelineRun Level Environment Variables in PipelineRun Pod Template + d. TaskRun Level Environment Variables in TaskRun Pod Template + e. Task Level Environment Variables in Task Step Template + f. Step Level Environment Variables in Step Container Spec + +## Proposal + + + +Common environment variables can be defined in a single place on a `PipelineRun` level. +Values can be specified as literals or through references, e.g.: + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + name: mypipelinerun +spec: + podTemplate: + env: + - name: TOKEN_PATH + value: /opt/user-token + - name: TKN_PIPELINE_RUN + valueFrom: + fieldRef: + fieldPath: metadata.labels['tekton.dev/pipelineRun'] +``` + +Environment variables defined in steps can be easily overwritten by the ones from a `TaskRun`, e.g.: + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: mytask + namespace: default +spec: + steps: + - name: echo-msg + image: ubuntu + command: ["bash", "-c"] + args: ["echo $MSG"] + envs: + - name: "MSG" + value: "Default message" +--- +apiVersion: tekton.dev/v1beta1 +kind: TaskRun +metadata: + name: mytaskrun + namespace: default +spec: + taskRef: + name: mytask + podTemplate: + envs: + - name: "MSG" + value: "Overwritten message" +``` + +Similarly, environment variables defined in steps can be easily overwritten by the ones from a `PipelineRun`, e.g.: +```yaml +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: mytask + namespace: default +spec: + steps: + - name: echo-msg + image: ubuntu + command: ["bash", "-c"] + args: ["echo $MSG $SECRET_PASSWORD $NAMESPACE"] + envs: + - name: "MSG" + value: "Default message" + - name: "SECRET_PASSWORD" + value: "Default secret password" + - name: "NAMESPACE" + value: "tekton-pipelines" +--- +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + name: one-task-pipeline-run + namespace: default +spec: + pipelineSpec: + tasks: + - name: mytaskrun + taskRef: + name: mytask + podTemplate: + envs: + - name: "MSG" + value: "Overwritten message" +--- +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + name: three-task-pipeline-run + namespace: default +spec: + pipelineSpec: + tasks: + - name: mytaskrun + taskRef: + name: mytask + - name: mytaskrun2 + taskRef: + name: mytask + runAfter: + - mytaskrun + - name: mytaskrun3 + taskRef: + name: mytask + runAfter: + - mytaskrun2 + podTemplate: + envs: + - name: "MSG" + valueFrom: + fieldRef: + fieldPath: metadata.labels['messages'] + - name: "SECRET_PASSWORD" + valueFrom: + secretKeyRef: + name: mysecret + key: password + optional: false + - name: "NAMESPACE" + valueFrom: + fieldRef: + fieldPath: metadata.namespace +``` + +Without the ENV in podTemplate, every new pipelinerun above will need to create a new +`Task` resource using stepTemplate to run the same examples. e.g.: +```yaml +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: mytask + namespace: default +spec: + stepTemplate: + envs: + - name: "MSG" + value: "Overwritten message" + steps: + - name: echo-msg + image: ubuntu + command: ["bash", "-c"] + args: ["echo $MSG $SECRET_PASSWORD $NAMESPACE"] + envs: + - name: "MSG" + value: "Default message" + - name: "SECRET_PASSWORD" + value: "Default secret password" + - name: "NAMESPACE" + value: "tekton-pipelines" +--- +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: mytask2 + namespace: default +spec: + stepTemplate: + envs: + - name: "MSG" + valueFrom: + fieldRef: + fieldPath: metadata.labels['messages'] + - name: "SECRET_PASSWORD" + valueFrom: + secretKeyRef: + name: mysecret + key: password + optional: false + - name: "NAMESPACE" + valueFrom: + fieldRef: + fieldPath: metadata.namespace + steps: + - name: echo-msg + image: ubuntu + command: ["bash", "-c"] + args: ["echo $MSG $SECRET_PASSWORD $NAMESPACE"] + envs: + - name: "MSG" + value: "Default message" + - name: "SECRET_PASSWORD" + value: "Default secret password" + - name: "NAMESPACE" + value: "tekton-pipelines" +--- +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + name: one-task-pipeline-run + namespace: default +spec: + pipelineSpec: + tasks: + - name: mytaskrun + taskRef: + name: mytask +--- +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + name: three-task-pipeline-run + namespace: default +spec: + pipelineSpec: + tasks: + - name: mytaskrun + taskRef: + name: mytask2 + - name: mytaskrun2 + taskRef: + name: mytask2 + runAfter: + - mytaskrun + - name: mytaskrun3 + taskRef: + name: mytask2 + runAfter: + - mytaskrun2 +``` + +Another use case is where admin can define a list of immutable environment variables in the cluster-wide configmap. +Then, the podTemplate will not replace any variable in the Tekon cluster-wide configmap. + +Tekton configmap +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-defaults + namespace: tekton-pipelines + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-pipelines +data: + default-pod-template-rules: | { + "forbidden-env-variables" : ["HTTP_PROXY"] + } + default-pod-template: | + envs: + - name: "MSG" + value: "Default message" +``` + +Tekton pipelinerun +```yaml +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: mytask + namespace: default +spec: + steps: + - name: echo-msg + image: ubuntu + command: ["bash", "-c"] + args: ["echo $HTTP_PROXY"] +--- +apiVersion: tekton.dev/v1beta1 +kind: TaskRun +metadata: + name: mytaskrun + namespace: default +spec: + taskRef: + name: mytask + podTemplate: + envs: + - name: "HTTP_PROXY" + value: "8080" +``` + +The above pipeline will return "HTTP_PROXY" is not a valid environment variable to define in the podTemplate. +List of forbidden environment variables are located at the "config-defaults" configmap at the Tekton controller +namespace. All the tasks will have the default "MSG" environment variable in their step since it's set as part +of the global default pod template. + +### Notes/Caveats (optional) + + + +### Risks and Mitigations + + + +In case of some environment variables are not allowed to change, it can have +a feature flag to opt-in with this new feature. Similar to the alpha API feature flag, +we can let the validation webhook fail with an error message when the feature flag is +disabled. The default behavior can change after 9 months of the Tekton release cycles. + +### User Experience (optional) + + + +### Performance (optional) + + + +## Design Details + + + +Bring the task `stepTemplate` spec to the taskRuns and pipelineRuns. Similar to +`podTemplate`, pipelineRun `stepTemplate` can overwrite the taskRun and task `stepTemplate`. + + +## Test Plan + + + +## Design Evaluation + + +## Drawbacks + + + +## Alternatives + + + +Define with a Top-level environment variable field. This new top-level field will be under the pipelinerun/taskrun spec level. Since the requirements also need to support Kubernetes value references such as secret, configmap, and Kubernetes downstream API, the type for this new spec will be an array of Kubernetes container V1 environment variable types. + +## Infrastructure Needed (optional) + + + +## Upgrade & Migration Strategy (optional) + + + +No impact on existing features. + +## Implementation Pull request(s) + + + +Previously open: https://github.com/tektoncd/pipeline/pull/3566 + +## References (optional) + + + +Previously open: https://github.com/tektoncd/pipeline/issues/1606 diff --git a/teps/0103-skipping-reason.md b/teps/0103-skipping-reason.md index 471e8b62a..3ef92ddc6 100644 --- a/teps/0103-skipping-reason.md +++ b/teps/0103-skipping-reason.md @@ -1,8 +1,8 @@ --- -status: implementable +status: implemented title: Skipping Reason creation-date: '2022-04-06' -last-updated: '2022-04-06' +last-updated: '2022-05-05' authors: - '@jerop' see-also: @@ -205,11 +205,14 @@ status: * [Tekton Pipelines Issue 4738: Skipping Reason][issue-4738] * [Tekton Pipelines Issue 4571: Task skipped when parallel task fails][issue-4571] * [Tekton Community Slack Thread][slack] +* Pull Requests: + * [Tekton Pipelines Pull Request 4829][pr-4829] [tep-0007]: https://github.com/tektoncd/community/blob/main/teps/0007-conditions-beta.md [tep-0059]: https://github.com/tektoncd/community/blob/main/teps/0059-skipping-strategies.md [skipped-tasks]: https://github.com/tektoncd/pipeline/blob/053833cb10f3829d5a366daa1f431b293dcf3285/pkg/apis/pipeline/v1beta1/pipelinerun_types.go#L466-L476 [issue-4738]: https://github.com/tektoncd/pipeline/issues/4738 [issue-4571]: https://github.com/tektoncd/pipeline/issues/4571 -[slack]: https://tektoncd.slack.com/archives/CK3HBG7CM/p1642349040014100 -[reasons]: https://github.com/tektoncd/pipeline/blob/053833cb10f3829d5a366daa1f431b293dcf3285/pkg/reconciler/pipelinerun/resources/pipelinerunresolution.go#L42-L62 \ No newline at end of file +[slack]: ../teps/images/0103-slack-thread.png +[reasons]: https://github.com/tektoncd/pipeline/blob/053833cb10f3829d5a366daa1f431b293dcf3285/pkg/reconciler/pipelinerun/resources/pipelinerunresolution.go#L42-L62 +[pr-4829]: https://github.com/tektoncd/pipeline/pull/4829 diff --git a/teps/0106-support-specifying-metadata-per-task-in-runtime.md b/teps/0106-support-specifying-metadata-per-task-in-runtime.md new file mode 100644 index 000000000..00d091ceb --- /dev/null +++ b/teps/0106-support-specifying-metadata-per-task-in-runtime.md @@ -0,0 +1,310 @@ +--- +status: proposed +title: Support Specifying Metadata per Task in Runtime +creation-date: '2022-04-19' +last-updated: '2022-04-19' +authors: +- '@austinzhao-go' +--- + +# TEP-0106: Support Specifying Metadata per Task in Runtime + + +- [TEP-0106: Support Specifying Metadata per Task in Runtime](#tep-0106-support-specifying-metadata-per-task-in-runtime) + - [Summary](#summary) + - [Motivation](#motivation) + - [Goals](#goals) + - [Non-Goals](#non-goals) + - [Use Cases](#use-cases) + - [Vault Sidecar Injection](#vault-sidecar-injection) + - [Hermetically Executed Task](#hermetically-executed-task) + - [General Use Case](#general-use-case) + - [Proposal](#proposal) + - [Notes and Caveats](#notes-and-caveats) + - [Metadata Conflicts](#metadata-conflicts) + - [(UPDATE) Tekton Metadata Overriding](#update-tekton-metadata-overriding) + - [Design Details](#design-details) + - [Metadata Precedence](#metadata-precedence) + - [Design Evaluation](#design-evaluation) + - [Reusability](#reusability) + - [Simplicity](#simplicity) + - [Drawbacks](#drawbacks) + - [Alternatives](#alternatives) + - [Add Metadata under `TaskRef` in `Pipeline`](#add-metadata-under-taskref-in-pipeline) + - [Create a `PipelineTaskRef` type](#create-a-pipelinetaskref-type) + - [Utilize Parameter Substitutions](#utilize-parameter-substitutions) + - [Test Plan](#test-plan) + - [Implementation Pull Requests](#implementation-pull-requests) + - [References](#references) + + +## Summary + +This work will support a user specifying the required metadata (annotations and/or labels) for a referenced `Task` in a `PipelineRun`. So the metadata depending on an execution context can be added in the runtime when they can not be statically defined in a `Task` during the "authoring" time. + +## Motivation + +The required metadata currently can be added under a `Task` entity while a user is authoring/configuring the template for a `TaskRun`. As two contexts are considered for Tekton - the “authoring time” and “runtime”, a stretch of thinking will lead to if the metadata could be defined “dynamically” under the runtime. + +The [issue #4105](https://github.com/tektoncd/pipeline/issues/4105) brings a solid usage case where annotations needed for a sidecar injection will depend on the user input and can not be statically defined in a `Task`. So this work could meet the requirements on metadata while keeping a loose coupling between defining a `Task` and a `TaskRun`. + +### Goals + +- Support a user specify metadata in a referenced `Task` in a `PipelineRun`. +- The allowed metadata will be annotations and labels. + +### Non-Goals + +The below consideration is applied to limit the problem scope: + +- This support will only be offered for a `PipelineRun` entity. +- The metadata will only mean annotations and labels. + +## Use Cases + +### Vault Sidecar Injection + +A user wants to use [Vault Agent Injector](https://www.vaultproject.io/docs/platform/k8s/injector) to offer required secrets, like API keys, credentials etc., into a target `Pod`, so via a `TaskRun` for the Tekton context. And the Injector will need the related Vault Agent to render the secrets which are specified either by annotations or templates. This configuration will be done based on the required secrets for each `TaskRun` in the runtime as they can not be statically defined in a `Task`. + +Here is an example of configuring the secrets: + +```yaml +# via Annotations +vault.hashicorp.com/agent-inject-secret-${unique-name}: ${/path/to/secret} +vault.hashicorp.com/role: ${role} + +# via Secret Templates +vault.hashicorp.com/agent-inject-template-${unique-name}: | + < + TEMPLATE + HERE + > +vault.hashicorp.com/role: ${role} +``` + +So for either way, the needed annotations will depend on the secrets a user wants to pass into a `TaskRun`. + +### Hermetically Executed Task + +Supported by the [Hermetic Execution Mode](https://github.com/tektoncd/pipeline/blob/main/docs/hermetic.md#enabling-hermetic-execution-mode), a `Task` can be run hermetically by specifying an annotation as: + +```yaml +experimental.tekton.dev/execution-mode: hermetic +``` + +So depending on a user’s context, a `Task` could be executed as a `TaskRun` under the hermetic execution mode by adding the annotation in runtime. + +_(Note: Activating the hermetic execution via an annotation is an alpha feature for this moment, which can be changed in the stable version.)_ + +### General Use Case + +Generalized from above use cases, a user can decide to pass metadata into a `Pod` in the runtime while configuring a `PipelineRun`. Under the Tekton context, the provided metadata for a referenced `Task` in a `PipelineRun` will be propagated into the corresponding `TaskRun`, and then to the target `Pod`. + +## Proposal + +A metadata field is proposed to be added under the `PipelineRun` type. + +## Notes and Caveats + +The below considerations could be further digged into: + +### Metadata Conflicts + +Check if possible conflicts will come from the metadata specified in the different positions, such as `Task`, `TaskSpec`, `EmbeddedTask`, `PipelineTaskRunSpec` etc. + +(UPDATE) This concern was handled by implementing [the logic](https://github.com/tektoncd/pipeline/pull/4834/commits/e53e2c1d0721855e5a8b6fef5d4cf59059e78ab3#diff-fcdbb0e0ea64e13920b270bf5cb2ca8993c040d77a6173ec004d1795e9e20135R1021) to keep an order as: + +```markdown +Metadata Precedence Order: PipelineTaskRunSpec > PipelineRun > PipelineTaskSpec +``` + +So a higher precedence (left) metadata will keep its value when meeting a same key metadata populated from a lower one (right). + +### (UPDATE) Tekton Metadata Overriding + +There is a chance that the runtime inputted metadata can override the metadata set by Tekton components, by the above metadata precedence as discussed [here](https://github.com/tektoncd/community/pull/695#discussion_r864813657). + +Validation should be added to ensure the Tekton self-owned metadata not getting overridden. There is an ongoing work to implement the restriction as [here](https://github.com/tektoncd/pipeline/issues/4366). Similar work will be done as a follow-up action. + +Examples of metadata set by different Tekton components (thanks @afrittoli for sharing this context): + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: TaskRun +metadata: + annotations: + chains.tekton.dev/retries: "3" + chains.tekton.dev/signed: failed. + pipeline.tekton.dev/affinity-assistant: affinity-assistant-24428a19af + pipeline.tekton.dev/release: 6b5710c + results.tekton.dev/record: default/results/5ffb52cc-ce6f-466b-8ddf-827b955cf6c5/records/43f5e888-b935-4264-91c2-7ff54fd09b3e + results.tekton.dev/result: default/results/5ffb52cc-ce6f-466b-8ddf-827b955cf6c5 + labels: + tekton.dev/memberOf: tasks + tekton.dev/pipeline: catalog-publish + tekton.dev/pipelineRun: publish-catalog-tekton-ghn4b + tekton.dev/pipelineTask: git-clone + tekton.dev/task: git-clone + triggers.tekton.dev/eventlistener: tekton-cd + triggers.tekton.dev/trigger: catalog + triggers.tekton.dev/triggers-eventid: 5ffb52cc-ce6f-466b-8ddf-827b955cf6c5 +``` + +- pipeline.tekton.dev annotations are set by the pipeline controller +- chains.tekton.dev annotations are set by chains +- results.tekton.dev annotations are set by results +- tekton.dev labels are set by the pipeline controller or coming from the catalog +- triggers.tekton.dev labels are set by triggers +(credits: afrittoli) + +## Design Details + +Guided by the stated “Reusability” by [Tekton Design Principles](https://github.com/tektoncd/community/blob/main/design-principles.md), the added metadata will be located under the `taskRunSpecs` / `spec` field of the `PipelineRun` type. This will allow a user specify more execution-context-related metadata in `PipelineRun` rather than being limited by a static definition for a `Task`. + +So the metadata field will be added as (the addition marked with +): + +```go +// PipelineTaskRunSpec an be used to configure specific +// specs for a concrete Task +type PipelineTaskRunSpec struct { + PipelineTaskName string json:"pipelineTaskName,omitempty" + TaskServiceAccountName string json:"taskServiceAccountName,omitempty" + TaskPodTemplate *PodTemplate json:"taskPodTemplate,omitempty" + StepOverrides []TaskRunStepOverride json:"stepOverrides,omitempty" + SidecarOverrides []TaskRunSidecarOverride json:"sidecarOverrides,omitempty" + ++ // +optional ++ Metadata PipelineTaskMetadata json:"metadata,omitempty" +} +``` + +And the referenced metadata type is defined as: + +```go +// PipelineTaskMetadata contains the labels or annotations +type PipelineTaskMetadata struct { + // +optional + Labels map[string]string json:"labels,omitempty" + + // +optional + Annotations map[string]string json:"annotations,omitempty" +} +``` + +An `PipelineRun` example to show the structure (the addition marked with +): + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + name: ${pipeline-run-name} +spec: + pipelineRef: + name: ${pipeline-name} + taskRunSpecs: + - pipelineTaskName: ${task-name} ++ metadata: ++ annotations: ++ vault.hashicorp.com/agent-inject-secret-${unique-name}: ${/path/to/secret} ++ vault.hashicorp.com/role: ${role} +``` + +### Metadata Precedence + +From the point mentioned in [Notes and Caveats](#notes-and-caveats), the metadata precedence is taken into consideration for different positions which can be used to add metadata as needs. + +The proposed order will be as (the addition marked with +[]): + +```markdown ++[PipelineTaskRunSpec (of PipelineRun)] > PipelineRun (metadata field) -> TaskRun (metadata field) > TaskSpec (of PipelineTask in Pipeline type) +``` + +_(Note: `->` means the metadata will be propagated from `PipelineRun` into the corresponding `TaskRun`(s).)_ + +Here is an example (the addition marked with +): + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: Pipeline +spec: + tasks: + - name: ${pipeline-task-name} + taskSpec: + metadata: + annotations: + test: pipeline-taskSpec-annotations +--- +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + name: ${pipelineRun-name} + annotations: + test: pipelineRun-annotations +spec: + pipelineRef: + name: ${pipelineRef-name} + taskRunSpecs: + - pipelineTaskName: ${pipeline-task-name} ++ metadata: ++ annotations: ++ test: pipelineRun-taskRunSpec-annotations +``` + +So by the stated precedence order, the `test` annotation finally propagated into the `TaskRun`, then into the target `Pod`, will have a value as `pipelineRun-taskRunSpec-annotations`. + +As annotations to be used in runtime (supported by this work) will more depend on an execution context, it will be less likely to have a same key annotation in other places, like for the [vault sidecar injection](#vault-sidecar-injection). Otherwise, a user can consider placing an annotation, which possibly can be defined statically, under the `Pipeline`. + +The reason with this order is that the runtime metadata added per task will be closely related to the execution context, like enabling the hermetical mode for a task, and should be able to overwrite metadata, defined either in the "authoring time" or for all tasks in a `PipelineRun`, if have to. + +Also this addition follows the current order which gives a higher precedence for annotations specified in `PipelineRun`, so runtime > authoring time. + +## Design Evaluation + +This work is a user-facing change on API while following the `Reusability` principle to keep a loose coupling between a `Task` and a `TaskRun` definition. + +### Reusability + +A `Task` is expected to be better reused and keep flexibility while the runtime-related metadata can be independently added. + +### Simplicity + +With this work, a user is expected to avoid defining multi `Task`s which only differentiate on certain required metadata in the runtime. + +### Drawbacks + +- [ ] #TODO: to collect from feedback + +## Alternatives + +### Add Metadata under `TaskRef` in `Pipeline` + +While referring to the [`EmbeddedTask`](https://pkg.go.dev/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1#EmbeddedTask) type under the `Pipeline` type, a possible solution will be adding a metadata field under the `TaskRef` as discussed [here](https://github.com/tektoncd/pipeline/issues/4105#issuecomment-1075335509). + +But when considering that the required metadata will depend on the execution context (runtime), this solution is not chosen, because the `taskRef` under `Pipeline` belongs to the authoring time. Here the authoring time means a user will be expected to complete the configuration (authoring) for the `Task`. + +_(Note: This approach can meet use cases which require metadata specified during configuring a `Pipeline`, such as always enabling hermetic execution mode for certain referenced `Task`(s).)_ + +### Create a `PipelineTaskRef` type + +As a metadata field will be needed for the runtime, a possible solution will be creating a new type / field, under `PipelineRun` as discussed [here](https://github.com/tektoncd/pipeline/issues/4105#issuecomment-1084816779). + +While thinking that the work will be limited to adding a metadata field, this solution is not chosen, because an existing `PipelineTaskRunSpec` field can be used for this function augmentation. + +### Utilize Parameter Substitutions + +As for defining a field value based on user inputs, the parameter substitution method can be considered to concatenate the required metadata. + +However, the key of annotations will need to follow [the naming syntax](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/#syntax-and-character-set). And if using a key like `$(params.foo)`, it will cause a validation error. Moreover, parameter values can’t be populated from the `params` field for the `metadata` field due to the different scope of the fields. + +## Test Plan + +Unit tests will be added to check if the metadata was supported in the `PipelineRun`. + +## Implementation Pull Requests + +- [TEP-0106 Implementation](https://github.com/tektoncd/pipeline/pull/4834) + +## References + +- The related [Tekton Pipeline Issue #4105](https://github.com/tektoncd/pipeline/issues/4105) +- Design Doc [Support Specifying Metadata per Task in Runtime](https://docs.google.com/document/d/1JyeE_TEKDpnqr1uygxkALJyPKXMOypAwPfnEAx7HKyY/edit?usp=sharing) diff --git a/teps/0108-mapping-workspaces.md b/teps/0108-mapping-workspaces.md new file mode 100644 index 000000000..6b815c13b --- /dev/null +++ b/teps/0108-mapping-workspaces.md @@ -0,0 +1,122 @@ +--- +status: implementable +title: Mapping Workspaces +creation-date: '2022-05-03' +last-updated: '2022-05-03' +authors: +- '@jerop' +- '@bobcatfish' +see-also: +- TEP-0107 +--- + +# TEP-0108: Mapping Workspaces + + +- [Summary](#summary) +- [Motivation](#motivation) +- [Proposal](#proposal) +- [References](#references) + + +## Summary + +This proposal builds on this prior work to reduce verbosity in mapping `Workspaces` and improve usability of +*Tekton Pipelines*. + +## Motivation + +The verbosity of writing specifications in *Tekton Pipelines* is a common pain point that causes difficulties in +getting-started scenarios. `Tasks` declare `Workspaces` they need, while `Pipelines` declare `Workspaces` that are +shared among its `PipelineTasks`. The mapping of `Workspaces` from `Pipelines` to `PipelineTasks` is verbose, as +shown below: + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: Pipeline +metadata: + name: pipeline +spec: + workspaces: + - name: source + tasks: + - name: gen-code + taskRef: + name: gen-code # gen-code expects a Workspace named "source" + workspaces: + - name: source + workspace: source + - name: commit + taskRef: + name: commit # commit expects a Workspace named "source" + workspaces: + - name: source + workspace: source + runAfter: + - gen-code +``` + +## Proposal + +We propose auto-mapping `Workspaces` from `Pipelines` to `PipelineTasks` when the names of the `Workspaces` declared in +the `Pipeline` and `PipelineTask` are the same, as shown below: + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: Pipeline +metadata: + name: pipeline +spec: + workspaces: + - name: source + tasks: + - name: gen-code + taskRef: + name: gen-code # gen-code expects a Workspace named "source" + workspaces: + - name: source + - name: commit + taskRef: + name: commit # commit expects a Workspace named "source" + workspaces: + - name: source + runAfter: + - gen-code +``` + +The `Workspaces` will be bound to the `Workspaces` declared within the `Tasks`. + +To meet conformance requirements, this solution does not mutate the `Pipeline` specification at runtime. In addition, +the validation routine that confirms that `Workspaces` needed by `PipelineTasks` are provided will be expanded to +handle this proposal. + +Users can continue to explicitly map `Workspaces`, as shown below: + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: Pipeline +metadata: + name: pipeline +spec: + workspaces: + - name: source + tasks: + - name: gen-code + taskRef: + name: gen-code # gen-code expects a Workspace named "output" + workspaces: + - name: output + workspace: source + - name: commit + taskRef: + name: commit # commit expects a Workspace named "source" + workspaces: + - name: source + runAfter: + - gen-code +``` + +## References + +- [TEP-0107: Propagating `Parameters`](0107-propagating-parameters.md) +- [`Workspaces` Documentation](https://github.com/tektoncd/pipeline/blob/main/docs/workspaces.md) \ No newline at end of file diff --git a/teps/0109-better-structured-provenance-retrieval-in-tekton-chains.md b/teps/0109-better-structured-provenance-retrieval-in-tekton-chains.md index 3197917ac..9a75ef01a 100644 --- a/teps/0109-better-structured-provenance-retrieval-in-tekton-chains.md +++ b/teps/0109-better-structured-provenance-retrieval-in-tekton-chains.md @@ -10,6 +10,13 @@ authors: # TEP-0109: Better structured provenance retrieval in Tekton Chains --- +<<<<<<< HEAD +======= +<<<<<<<< HEAD:teps/0107-better-structured-provenance-retrieval-in-tekton-chains.md +# TEP-0107: Better structured provenance retrieval in Tekton Chains +======== +>>>>>>>> faa50cc (Add example for storing defined schema):teps/0109-better-structured-provenance-retrieval-in-tekton-chains.md +>>>>>>> tektoncd-main