Skip to content

Commit

Permalink
TEP-0106: Support Specifying Metadata per Task in Runtime
Browse files Browse the repository at this point in the history
Add Design Details, Clean Comments

Improve Idea Expression

Add Note for a Possible Feature

Add Section for Metadata Precedence
  • Loading branch information
austinzhao-go committed May 3, 2022
1 parent 3aa9242 commit bd6d894
Show file tree
Hide file tree
Showing 2 changed files with 262 additions and 0 deletions.
261 changes: 261 additions & 0 deletions teps/0106-support-specifying-metadata-per-task-in-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
---
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

<!-- toc -->
- [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)
- [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)
<!-- /toc -->

## 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:

- Check if possible conflicts will come from the metadata specified in the different positions, such as `Task`, `TaskSpec`, `EmbeddedTask`, `PipelineTaskRunSpec` etc. - think this can be enhanced by validation and unit tests.

## 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

- [ ] #TODO: after TEP marked as implemented

## 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)
1 change: 1 addition & 0 deletions teps/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,4 +244,5 @@ This is the complete list of Tekton teps:
|[TEP-0103](0103-skipping-reason.md) | Skipping Reason | implementable | 2022-04-06 |
|[TEP-0104](0104-tasklevel-resource-requests.md) | Task-level Resource Requests | implementable | 2022-04-08 |
|[TEP-0105](0105-remove-pipeline-v1alpha1-api.md) | Remove Pipeline v1alpha1 API | proposed | 2022-04-11 |
|[TEP-0106](0106-support-specifying-metadata-per-task-in-runtime.md) | Support Specifying Metadata per Task in Runtime | proposed | 2022-04-19 |
|[TEP-0107](0107-propagating-parameters.md) | Propagating Parameters | implementable | 2022-05-02 |

0 comments on commit bd6d894

Please sign in to comment.