Skip to content

Commit d9f2e56

Browse files
[TEP-0144] Validate PipelineRun for Param Enum
Part of [tektoncd#7270][tektoncd#7270]. In [TEP-0144][tep-0144] we proposed a new `enum` field to support built-in param input validation. This commit adds validation logic for PipelineRun against Param Enum /kind feature [tektoncd#7270]: tektoncd#7270 [tep-0144]: https://github.com/tektoncd/community/blob/main/teps/0144-param-enum.md
1 parent a106110 commit d9f2e56

File tree

11 files changed

+319
-7
lines changed

11 files changed

+319
-7
lines changed

config/config-feature-flags.yaml

-1
Original file line numberDiff line numberDiff line change
@@ -127,5 +127,4 @@ data:
127127
# This feature is in preview mode and not implemented yet. Please check #7259 for updates.
128128
enable-step-actions: "false"
129129
# Setting this flag to "true" will enable the built-in param input validation via param enum.
130-
# NOTE (#7270): this feature is still under development and not yet functional.
131130
enable-param-enum: "false"

docs/additional-configs.md

+1
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ Features currently in "alpha" are:
317317
| [Coschedule](./affinityassistants.md) | [TEP-0135](https://github.com/tektoncd/community/blob/main/teps/0135-coscheduling-pipelinerun-pods.md) | N/A |`coschedule` |
318318
| [keep pod on cancel](./taskruns.md#cancelling-a-taskrun) | N/A | v0.52 | keep-pod-on-cancel |
319319
| [CEL in WhenExpression](./taskruns.md#cancelling-a-taskrun) | [TEP-0145](https://github.com/tektoncd/community/blob/main/teps/0145-cel-in-whenexpression.md) | N/A | enable-cel-in-whenexpression |
320+
| [Param Enum](./taskruns.md#parameter-enums) | [TEP-0144](https://github.com/tektoncd/community/blob/main/teps/0144-param-enum.md) | N/A | `enable-param-enum` |
320321

321322
### Beta Features
322323

docs/pipeline-api.md

+3
Original file line numberDiff line numberDiff line change
@@ -1997,6 +1997,9 @@ associated Pipeline is an invalid graph (a.k.a wrong order, cycle, …)</p>
19971997
</tr><tr><td><p>&#34;InvalidMatrixParameterTypes&#34;</p></td>
19981998
<td><p>ReasonInvalidMatrixParameterTypes indicates a matrix contains invalid parameter types</p>
19991999
</td>
2000+
</tr><tr><td><p>&#34;InvalidParamValue&#34;</p></td>
2001+
<td><p>PipelineRunReasonInvalidParamValue indicates that the PipelineRun Param input value is not allowed.</p>
2002+
</td>
20002003
</tr><tr><td><p>&#34;InvalidTaskResultReference&#34;</p></td>
20012004
<td><p>ReasonInvalidTaskResultReference indicates a task result was declared
20022005
but was not initialized by that task</p>

docs/pipelineruns.md

+12
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,18 @@ case is when your CI system autogenerates `PipelineRuns` and it has `Parameters`
271271
provide to all `PipelineRuns`. Because you can pass in extra `Parameters`, you don't have to
272272
go through the complexity of checking each `Pipeline` and providing only the required params.
273273

274+
#### Parameter Enums
275+
276+
> :seedling: **Specifying `enum` is an [alpha](additional-configs.md#alpha-features) feature.** The `enable-param-enum` feature flag must be set to `"true"` to enable this feature.
277+
278+
If a `Parameter` is guarded by `Enum` in the `Pipeline`, you can only provide `Parameter` values in the `PipelineRun` that are predefined in the `Param.Enum` in the `Pipeline`. The `PipelineRun` will fail with reason `InvalidParamValue` otherwise.
279+
280+
Tekton will also the validate the `param` values passed to any referenced `Tasks` (vis `taskRef`) if `Enum` is specified for the `Task`. The `PipelineRun` will fail with reason `InvalidParamValue` if `Enum` validation is failed for any of the `PipelineTask`.
281+
282+
You can also specify `Enum` for `PipelineRun` with an embedded `Pipeline`. The same param validation will be executed in this scenario.
283+
284+
See more details in [Param.Enum](./pipelines.md#param-enum).
285+
274286
#### Propagated Parameters
275287

276288
When using an inlined spec, parameters from the parent `PipelineRun` will be

docs/pipelines.md

+63-2
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,70 @@ spec:
274274
#### Param enum
275275
> :seedling: **Specifying `enum` is an [alpha](additional-configs.md#alpha-features) feature.** The `enable-param-enum` feature flag must be set to `"true"` to enable this feature.
276276

277-
> :seedling: This feature is WIP and not yet supported/implemented. Documentation to be completed.
277+
Parameter declarations can include `enum` which is a predefine set of valid values that can be accepted by the `Pipeline` `Param`. For example, the valid/allowed values for `Param` "message" is bounded to `v1` and `v2`:
278278

279-
Parameter declarations can include `enum` which is a predefine set of valid values that can be accepted by the `Pipeline`.
279+
``` yaml
280+
apiVersion: tekton.dev/v1
281+
kind: Pipeline
282+
metadata:
283+
name: pipeline-param-enum
284+
spec:
285+
params:
286+
- name: message
287+
enum: ["v1", "v2"]
288+
default: "v1"
289+
tasks:
290+
- name: task1
291+
params:
292+
- name: message
293+
value: $(params.message)
294+
steps:
295+
- name: build
296+
image: bash:3.2
297+
script: |
298+
echo "$(params.message)"
299+
```
300+
301+
If the `Param` value passed in by `PipelineRun` is **NOT** in the predefined `enum` list, the `PipelineRun` will fail with reason `InvalidParamValue`.
302+
303+
If a `PipelineTask` references a `Task` with `enum`, Tekton validates the **intersection** of enum specified in the referenced `Task` and the enum specified in the Pipeline `spec.params`. In the example below, the referenced `Task` accepts `v1` and `v2` as valid values, and the `Pipeline` accepts `v2` and `v3` as valid values. Only passing `v2` in the `PipelineRun` will lead to a sucessful execution.
304+
305+
``` yaml
306+
apiVersion: tekton.dev/v1
307+
kind: Task
308+
metadata:
309+
name: param-enum-demo
310+
spec:
311+
params:
312+
- name: message
313+
type: string
314+
enum: ["v1", "v2"]
315+
steps:
316+
- name: build
317+
image: bash:latest
318+
script: |
319+
echo "$(params.message)"
320+
```
321+
322+
``` yaml
323+
apiVersion: tekton.dev/v1
324+
kind: Pipeline
325+
metadata:
326+
name: pipeline-param-enum
327+
spec:
328+
params:
329+
- name: message
330+
enum: ["v2", "v3"]
331+
tasks:
332+
- name: task1
333+
params:
334+
- name: message
335+
value: $(params.message)
336+
taskRef:
337+
name: param-enum-demo
338+
```
339+
340+
See usage in this [example](../examples/v1/pipelineruns/alpha/param-enum.yaml)
280341

281342
## Adding `Tasks` to the `Pipeline`
282343

docs/taskruns.md

-2
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,6 @@ go through the complexity of checking each `Task` and providing only the require
406406

407407
> :seedling: **Specifying `enum` is an [alpha](additional-configs.md#alpha-features) feature.** The `enable-param-enum` feature flag must be set to `"true"` to enable this feature.
408408

409-
> :seedling: This feature is WIP and not yet supported/implemented. Documentation to be completed.
410-
411409
If a `Parameter` is guarded by `Enum` in the `Task`, you can only provide `Parameter` values in the `TaskRun` that are predefined in the `Param.Enum` in the `Task`. The `TaskRun` will fail with reason `InvalidParamValue` otherwise.
412410

413411
You can also specify `Enum` for [`TaskRun` with an embedded `Task`](#example-taskrun-with-an-embedded-task). The same param validation will be executed in this scenario.

docs/tasks.md

-2
Original file line numberDiff line numberDiff line change
@@ -715,8 +715,6 @@ spec:
715715
#### Param enum
716716
> :seedling: **Specifying `enum` is an [alpha](additional-configs.md#alpha-features) feature.** The `enable-param-enum` feature flag must be set to `"true"` to enable this feature.
717717

718-
> :seedling: This feature is WIP and not yet supported/implemented. Documentation to be completed.
719-
720718
Parameter declarations can include `enum` which is a predefine set of valid values that can be accepted by the `Param`. For example, the valid/allowed values for `Param` "message" is bounded to `v1`, `v2` and `v3`:
721719

722720
``` yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
apiVersion: tekton.dev/v1
2+
kind: Pipeline
3+
metadata:
4+
name: pipeline-param-enum
5+
spec:
6+
params:
7+
- name: message
8+
enum: ["v1", "v2", "v3"]
9+
default: "v1"
10+
tasks:
11+
- name: task1
12+
params:
13+
- name: message
14+
value: $(params.message)
15+
taskSpec:
16+
params:
17+
- name: message
18+
steps:
19+
- name: build
20+
image: bash:3.2
21+
script: |
22+
echo "$(params.message)"
23+
---
24+
apiVersion: tekton.dev/v1
25+
kind: PipelineRun
26+
metadata:
27+
name: pipelinerun-param-enum
28+
spec:
29+
pipelineRef:
30+
name: pipeline-param-enum
31+
params:
32+
- name: message
33+
value: "v2"

pkg/apis/pipeline/v1/pipelinerun_types.go

+2
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,8 @@ const (
409409
PipelineRunReasonCreateRunFailed PipelineRunReason = "CreateRunFailed"
410410
// ReasonCELEvaluationFailed indicates the pipeline fails the CEL evaluation
411411
PipelineRunReasonCELEvaluationFailed PipelineRunReason = "CELEvaluationFailed"
412+
// PipelineRunReasonInvalidParamValue indicates that the PipelineRun Param input value is not allowed.
413+
PipelineRunReasonInvalidParamValue PipelineRunReason = "InvalidParamValue"
412414
)
413415

414416
func (t PipelineRunReason) String() string {

pkg/reconciler/pipelinerun/pipelinerun.go

+23
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,19 @@ func (c *Reconciler) resolvePipelineState(
387387
return nil, controller.NewPermanentError(err)
388388
}
389389
}
390+
391+
if config.FromContextOrDefaults(ctx).FeatureFlags.EnableParamEnum {
392+
for _, tr := range resolvedTask.TaskRuns {
393+
if len(tr.Status.Conditions) > 0 {
394+
cond := resolvedTask.TaskRuns[0].Status.Conditions[0]
395+
if cond.Status == corev1.ConditionFalse && cond.Reason == v1.TaskRunReasonInvalidParamValue {
396+
pr.Status.MarkFailed(v1.PipelineRunReasonInvalidParamValue.String(),
397+
"Invalid param value in the referenced Task from PipelineTask \"%s\": %s", resolvedTask.PipelineTask.Name, cond.Message)
398+
return nil, controller.NewPermanentError(err)
399+
}
400+
}
401+
}
402+
}
390403
pst = append(pst, resolvedTask)
391404
}
392405
return pst, nil
@@ -487,6 +500,16 @@ func (c *Reconciler) reconcile(ctx context.Context, pr *v1.PipelineRun, getPipel
487500
return controller.NewPermanentError(err)
488501
}
489502

503+
if config.FromContextOrDefaults(ctx).FeatureFlags.EnableParamEnum {
504+
if err := taskrun.ValidateEnumParam(ctx, pr.Spec.Params, pipelineSpec.Params); err != nil {
505+
logger.Errorf("PipelineRun %q Param Enum validation failed: %v", pr.Name, err)
506+
pr.Status.MarkFailed(v1.PipelineRunReasonInvalidParamValue.String(),
507+
"PipelineRun %s/%s parameters have invalid value: %s",
508+
pr.Namespace, pr.Name, err)
509+
return controller.NewPermanentError(err)
510+
}
511+
}
512+
490513
// Ensure that the keys of an object param declared in PipelineSpec are not missed in the PipelineRunSpec
491514
if err = resources.ValidateObjectParamRequiredKeys(pipelineSpec.Params, pr.Spec.Params); err != nil {
492515
// This Run has failed, so we need to mark it as failed and stop reconciling it

0 commit comments

Comments
 (0)