diff --git a/config/config-feature-flags.yaml b/config/config-feature-flags.yaml index 6cb5073da37..bea6994cc99 100644 --- a/config/config-feature-flags.yaml +++ b/config/config-feature-flags.yaml @@ -131,3 +131,9 @@ data: enable-artifacts: "false" # Setting this flag to "true" will enable the built-in param input validation via param enum. enable-param-enum: "false" + # Setting this flag to "pipeline,pipelinerun,taskrun" will prevent users from creating + # embedded spec Taskruns or Pipelineruns for Pipeline, Pipelinerun and taskrun + # respectively. We can specify "pipeline" to disable for Pipeline resource only. + # "pipelinerun" for Pipelinerun and "taskrun" for Taskrun. Or a combination of + # these. + disable-inline-spec: "" diff --git a/docs/additional-configs.md b/docs/additional-configs.md index 8193f333b7d..be60c6c3b2d 100644 --- a/docs/additional-configs.md +++ b/docs/additional-configs.md @@ -32,6 +32,7 @@ installation. - [Verify Tekton Resources](#verify-tekton-resources) - [Pipelinerun with Affinity Assistant](#pipelineruns-with-affinity-assistant) - [TaskRuns with `imagePullBackOff` Timeout](#taskruns-with-imagepullbackoff-timeout) + - [Disabling Inline Spec in TaskRun and PipelineRun](#disabling-inline-spec-in-taskrun-and-pipelinerun) - [Next steps](#next-steps) @@ -694,6 +695,31 @@ data: default-imagepullbackoff-timeout: "5m" ``` +## Disabling Inline Spec in Pipeline, TaskRun and PipelineRun + +Tekton users may embed the specification of a `Task` (via `taskSpec`) or a `Pipeline` (via `pipelineSpec`) as an alternative to referring to an external resource via `taskRef` and `pipelineRef` respectively. This behaviour can be selectively disabled for three Tekton resources: `TaskRun`, `PipelineRun` and `Pipeline`. + + In certain clusters and scenarios, an admin might want to disable the customisation of `Tasks` and `Pipelines` and only allow users to run pre-defined resources. To achieve that the admin should disable embedded specification via the `disable-inline-spec` flag, and remote resolvers too. + +To disable inline specification, set the `disable-inline-spec` flag to `"pipeline,pipelinerun,taskrun"` +in the `feature-flags` configmap. +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: feature-flags + namespace: tekton-pipelines + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-pipelines +data: + disable-inline-spec: "pipeline,pipelinerun,taskrun" +``` + +Inline specifications can be disabled for specific resources only. To achieve that, set the disable-inline-spec flag to a comma-separated list of the desired resources. Valid values are pipeline, pipelinerun and taskrun. + +The default value of disable-inline-spec is "", which means inline specification is enabled in all cases. + ## Next steps To get started with Tekton check the [Introductory tutorials][quickstarts], diff --git a/docs/pipeline-api.md b/docs/pipeline-api.md index e0b52e34073..c8e57271de6 100644 --- a/docs/pipeline-api.md +++ b/docs/pipeline-api.md @@ -733,6 +733,8 @@ PipelineSpec (Optional) +

Specifying PipelineSpec can be disabled by setting +disable-inline-spec feature flag..

@@ -1155,6 +1157,8 @@ TaskSpec (Optional) +

Specifying PipelineSpec can be disabled by setting +disable-inline-spec feature flag..

@@ -2349,6 +2353,8 @@ PipelineSpec (Optional) +

Specifying PipelineSpec can be disabled by setting +disable-inline-spec feature flag..

@@ -2887,7 +2893,9 @@ EmbeddedTask (Optional) -

TaskSpec is a specification of a task

+

TaskSpec is a specification of a task +Specifying TaskSpec can be disabled by setting +disable-inline-spec feature flag..

@@ -3014,7 +3022,9 @@ PipelineSpec (Optional)

PipelineSpec is a specification of a pipeline -Note: PipelineSpec is in preview mode and not yet supported

+Note: PipelineSpec is in preview mode and not yet supported +Specifying PipelineSpec can be disabled by setting +disable-inline-spec feature flag..

@@ -5530,6 +5540,8 @@ TaskSpec (Optional) +

Specifying PipelineSpec can be disabled by setting +disable-inline-spec feature flag..

@@ -9026,6 +9038,8 @@ PipelineSpec (Optional) +

Specifying PipelineSpec can be disabled by setting +disable-inline-spec feature flag..

@@ -9524,6 +9538,8 @@ TaskSpec (Optional) +

Specifying PipelineSpec can be disabled by setting +disable-inline-spec feature flag..

@@ -11197,6 +11213,8 @@ PipelineSpec (Optional) +

Specifying PipelineSpec can be disabled by setting +disable-inline-spec feature flag..

@@ -11828,7 +11846,9 @@ EmbeddedTask (Optional) -

TaskSpec is a specification of a task

+

TaskSpec is a specification of a task +Specifying TaskSpec can be disabled by setting +disable-inline-spec feature flag..

@@ -11969,7 +11989,9 @@ PipelineSpec (Optional)

PipelineSpec is a specification of a pipeline -Note: PipelineSpec is in preview mode and not yet supported

+Note: PipelineSpec is in preview mode and not yet supported +Specifying TaskSpec can be disabled by setting +disable-inline-spec feature flag..

@@ -14997,6 +15019,8 @@ TaskSpec (Optional) +

Specifying PipelineSpec can be disabled by setting +disable-inline-spec feature flag..

diff --git a/pkg/apis/config/feature_flags.go b/pkg/apis/config/feature_flags.go index deda086727f..f8c057801a0 100644 --- a/pkg/apis/config/feature_flags.go +++ b/pkg/apis/config/feature_flags.go @@ -68,6 +68,8 @@ const ( DefaultRunningInEnvWithInjectedSidecars = true // DefaultAwaitSidecarReadiness is the default value for "await-sidecar-readiness". DefaultAwaitSidecarReadiness = true + // DefaultDisableInlineSpec is the default value of "disable-inline-spec" + DefaultDisableInlineSpec = "" // DefaultRequireGitSSHSecretKnownHosts is the default value for "require-git-ssh-secret-known-hosts". DefaultRequireGitSSHSecretKnownHosts = false // DefaultEnableTektonOciBundles is the default value for "enable-tekton-oci-bundles". @@ -107,6 +109,10 @@ const ( // EnableParamEnum is the flag to enabled enum in params EnableParamEnum = "enable-param-enum" + // DisableInlineSpec is the flag to disable embedded spec + // in Taskrun or Pipelinerun + DisableInlineSpec = "disable-inline-spec" + disableAffinityAssistantKey = "disable-affinity-assistant" disableCredsInitKey = "disable-creds-init" runningInEnvWithInjectedSidecarsKey = "running-in-environment-with-injected-sidecars" @@ -193,6 +199,7 @@ type FeatureFlags struct { EnableStepActions bool EnableParamEnum bool EnableArtifacts bool + DisableInlineSpec string } // GetFeatureFlagsConfigName returns the name of the configmap containing all @@ -291,6 +298,10 @@ func NewFeatureFlagsFromMap(cfgMap map[string]string) (*FeatureFlags, error) { if err := setPerFeatureFlag(EnableArtifacts, DefaultEnableArtifacts, &tc.EnableArtifacts); err != nil { return nil, err } + if err := setFeatureInlineSpec(cfgMap, DisableInlineSpec, DefaultDisableInlineSpec, &tc.DisableInlineSpec); err != nil { + return nil, err + } + // Given that they are alpha features, Tekton Bundles and Custom Tasks should be switched on if // enable-api-fields is "alpha". If enable-api-fields is not "alpha" then fall back to the value of // each feature's individual flag. @@ -364,6 +375,15 @@ func setEnforceNonFalsifiability(cfgMap map[string]string, feature *string) erro } } +func setFeatureInlineSpec(cfgMap map[string]string, key string, defaultValue string, feature *string) error { + if cfg, ok := cfgMap[key]; ok { + *feature = cfg + return nil + } + *feature = strings.ReplaceAll(defaultValue, " ", "") + return nil +} + // setResultExtractionMethod sets the "results-from" flag based on the content of a given map. // If the feature gate is invalid or missing then an error is returned. func setResultExtractionMethod(cfgMap map[string]string, defaultValue string, feature *string) error { diff --git a/pkg/apis/config/feature_flags_test.go b/pkg/apis/config/feature_flags_test.go index 5cf208ba594..0cefc572368 100644 --- a/pkg/apis/config/feature_flags_test.go +++ b/pkg/apis/config/feature_flags_test.go @@ -57,6 +57,7 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) { EnableCELInWhenExpression: config.DefaultEnableCELInWhenExpression.Enabled, EnableStepActions: config.DefaultEnableStepActions.Enabled, EnableParamEnum: config.DefaultEnableParamEnum.Enabled, + DisableInlineSpec: config.DefaultDisableInlineSpec, }, fileName: config.GetFeatureFlagsConfigName(), }, @@ -81,6 +82,7 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) { EnableStepActions: true, EnableArtifacts: true, EnableParamEnum: true, + DisableInlineSpec: "pipeline,pipelinerun,taskrun", }, fileName: "feature-flags-all-flags-set", }, @@ -107,6 +109,7 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) { EnableCELInWhenExpression: config.DefaultEnableCELInWhenExpression.Enabled, EnableStepActions: config.DefaultEnableStepActions.Enabled, EnableParamEnum: config.DefaultEnableParamEnum.Enabled, + DisableInlineSpec: config.DefaultDisableInlineSpec, }, fileName: "feature-flags-enable-api-fields-overrides-bundles-and-custom-tasks", }, @@ -128,6 +131,7 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) { SetSecurityContext: config.DefaultSetSecurityContext, Coschedule: config.DefaultCoschedule, EnableParamEnum: config.DefaultEnableParamEnum.Enabled, + DisableInlineSpec: config.DefaultDisableInlineSpec, }, fileName: "feature-flags-bundles-and-custom-tasks", }, @@ -149,6 +153,7 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) { SetSecurityContext: config.DefaultSetSecurityContext, Coschedule: config.DefaultCoschedule, EnableParamEnum: config.DefaultEnableParamEnum.Enabled, + DisableInlineSpec: config.DefaultDisableInlineSpec, }, fileName: "feature-flags-beta-api-fields", }, @@ -169,6 +174,7 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) { EnableCELInWhenExpression: config.DefaultEnableCELInWhenExpression.Enabled, EnableStepActions: config.DefaultEnableStepActions.Enabled, EnableParamEnum: config.DefaultEnableParamEnum.Enabled, + DisableInlineSpec: config.DefaultDisableInlineSpec, }, fileName: "feature-flags-enforce-nonfalsifiability-spire", }, @@ -188,6 +194,7 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) { EnableCELInWhenExpression: config.DefaultEnableCELInWhenExpression.Enabled, EnableStepActions: config.DefaultEnableStepActions.Enabled, EnableParamEnum: config.DefaultEnableParamEnum.Enabled, + DisableInlineSpec: config.DefaultDisableInlineSpec, }, fileName: "feature-flags-results-via-sidecar-logs", }, @@ -224,6 +231,7 @@ func TestNewFeatureFlagsFromEmptyConfigMap(t *testing.T) { EnableCELInWhenExpression: config.DefaultEnableCELInWhenExpression.Enabled, EnableStepActions: config.DefaultEnableStepActions.Enabled, EnableParamEnum: config.DefaultEnableParamEnum.Enabled, + DisableInlineSpec: config.DefaultDisableInlineSpec, } verifyConfigFileWithExpectedFeatureFlagsConfig(t, FeatureFlagsConfigEmptyName, expectedConfig) } @@ -311,7 +319,9 @@ func TestNewFeatureFlagsConfigMapErrors(t *testing.T) { t.Run(tc.fileName, func(t *testing.T) { cm := test.ConfigMapFromTestFile(t, tc.fileName) _, err := config.NewFeatureFlagsFromConfigMap(cm) - if d := cmp.Diff(tc.want, err.Error()); d != "" { + if err == nil { + t.Error("failed to get:", tc.want) + } else if d := cmp.Diff(tc.want, err.Error()); d != "" { t.Errorf("failed to get expected error; diff:\n%s", diff.PrintWantGot(d)) } }) diff --git a/pkg/apis/config/testdata/feature-flags-all-flags-set.yaml b/pkg/apis/config/testdata/feature-flags-all-flags-set.yaml index 51f312c52b0..6b539bc16da 100644 --- a/pkg/apis/config/testdata/feature-flags-all-flags-set.yaml +++ b/pkg/apis/config/testdata/feature-flags-all-flags-set.yaml @@ -36,3 +36,4 @@ data: enable-step-actions: "true" enable-param-enum: "true" enable-artifacts: "true" + disable-inline-spec: "pipeline,pipelinerun,taskrun" diff --git a/pkg/apis/pipeline/v1/openapi_generated.go b/pkg/apis/pipeline/v1/openapi_generated.go index 67a9508011b..f9380013f7d 100644 --- a/pkg/apis/pipeline/v1/openapi_generated.go +++ b/pkg/apis/pipeline/v1/openapi_generated.go @@ -1349,7 +1349,8 @@ func schema_pkg_apis_pipeline_v1_PipelineRunSpec(ref common.ReferenceCallback) c }, "pipelineSpec": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.PipelineSpec"), + Description: "Specifying PipelineSpec can be disabled by setting `disable-inline-spec` feature flag..", + Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.PipelineSpec"), }, }, "params": { @@ -1923,7 +1924,7 @@ func schema_pkg_apis_pipeline_v1_PipelineTask(ref common.ReferenceCallback) comm }, "taskSpec": { SchemaProps: spec.SchemaProps{ - Description: "TaskSpec is a specification of a task", + Description: "TaskSpec is a specification of a task Specifying TaskSpec can be disabled by setting `disable-inline-spec` feature flag..", Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.EmbeddedTask"), }, }, @@ -2026,7 +2027,7 @@ func schema_pkg_apis_pipeline_v1_PipelineTask(ref common.ReferenceCallback) comm }, "pipelineSpec": { SchemaProps: spec.SchemaProps{ - Description: "PipelineSpec is a specification of a pipeline Note: PipelineSpec is in preview mode and not yet supported", + Description: "PipelineSpec is a specification of a pipeline Note: PipelineSpec is in preview mode and not yet supported Specifying PipelineSpec can be disabled by setting `disable-inline-spec` feature flag..", Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.PipelineSpec"), }, }, @@ -3941,7 +3942,8 @@ func schema_pkg_apis_pipeline_v1_TaskRunSpec(ref common.ReferenceCallback) commo }, "taskSpec": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.TaskSpec"), + Description: "Specifying PipelineSpec can be disabled by setting `disable-inline-spec` feature flag..", + Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.TaskSpec"), }, }, "status": { diff --git a/pkg/apis/pipeline/v1/pipeline_types.go b/pkg/apis/pipeline/v1/pipeline_types.go index 3cbc5295149..4d6e20d6e93 100644 --- a/pkg/apis/pipeline/v1/pipeline_types.go +++ b/pkg/apis/pipeline/v1/pipeline_types.go @@ -199,6 +199,8 @@ type PipelineTask struct { TaskRef *TaskRef `json:"taskRef,omitempty"` // TaskSpec is a specification of a task + // Specifying TaskSpec can be disabled by setting + // `disable-inline-spec` feature flag.. // +optional TaskSpec *EmbeddedTask `json:"taskSpec,omitempty"` @@ -243,6 +245,8 @@ type PipelineTask struct { // PipelineSpec is a specification of a pipeline // Note: PipelineSpec is in preview mode and not yet supported + // Specifying PipelineSpec can be disabled by setting + // `disable-inline-spec` feature flag.. // +optional PipelineSpec *PipelineSpec `json:"pipelineSpec,omitempty"` diff --git a/pkg/apis/pipeline/v1/pipeline_validation.go b/pkg/apis/pipeline/v1/pipeline_validation.go index 5ff738ad372..a0b65f7787c 100644 --- a/pkg/apis/pipeline/v1/pipeline_validation.go +++ b/pkg/apis/pipeline/v1/pipeline_validation.go @@ -19,6 +19,7 @@ package v1 import ( "context" "fmt" + "slices" "strings" "github.com/tektoncd/pipeline/pkg/apis/config" @@ -177,6 +178,8 @@ func (pt PipelineTask) ValidateName() *apis.FieldError { func (pt PipelineTask) Validate(ctx context.Context) (errs *apis.FieldError) { errs = errs.Also(pt.validateRefOrSpec(ctx)) + errs = errs.Also(pt.validateEnabledInlineSpec(ctx)) + errs = errs.Also(pt.validateEmbeddedOrType()) // taskKinds contains the kinds when the apiVersion is not set, they are not custom tasks, // if apiVersion is set they are custom tasks. @@ -271,6 +274,24 @@ func (pt *PipelineTask) validateWorkspaces(workspaceNames sets.String) (errs *ap return errs } +// validateEnabledInlineSpec validates that pipelineSpec or taskSpec is allowed by checking +// disable-inline-spec field +func (pt PipelineTask) validateEnabledInlineSpec(ctx context.Context) (errs *apis.FieldError) { + if pt.TaskSpec != nil { + if slices.Contains(strings.Split( + config.FromContextOrDefaults(ctx).FeatureFlags.DisableInlineSpec, ","), "pipeline") { + errs = errs.Also(apis.ErrDisallowedFields("taskSpec")) + } + } + if pt.PipelineSpec != nil { + if slices.Contains(strings.Split( + config.FromContextOrDefaults(ctx).FeatureFlags.DisableInlineSpec, ","), "pipeline") { + errs = errs.Also(apis.ErrDisallowedFields("pipelineSpec")) + } + } + return errs +} + // validateRefOrSpec validates at least one of taskRef or taskSpec or pipelineRef or pipelineSpec is specified func (pt PipelineTask) validateRefOrSpec(ctx context.Context) (errs *apis.FieldError) { // collect all the specified specifications diff --git a/pkg/apis/pipeline/v1/pipeline_validation_test.go b/pkg/apis/pipeline/v1/pipeline_validation_test.go index b226aad2bca..446c8177066 100644 --- a/pkg/apis/pipeline/v1/pipeline_validation_test.go +++ b/pkg/apis/pipeline/v1/pipeline_validation_test.go @@ -285,6 +285,86 @@ func TestPipeline_Validate_Failure(t *testing.T) { Message: `expected exactly one, got multiple`, Paths: []string{"spec.tasks[0].pipelineRef, spec.tasks[0].pipelineSpec"}, }, + }, { + name: "pipelineSpec when disable-inline-spec", + p: &Pipeline{ + ObjectMeta: metav1.ObjectMeta{Name: "pipeline"}, + Spec: PipelineSpec{ + Tasks: []PipelineTask{ + { + Name: "foo", + PipelineSpec: &PipelineSpec{Description: "foo-pipeline-description"}, + }, + }, + }, + }, + expectedError: *apis.ErrDisallowedFields("spec.tasks[0]" + "." + "pipelineSpec"), + wc: func(ctx context.Context) context.Context { + return cfgtesting.SetFeatureFlags(ctx, t, + map[string]string{ + "disable-inline-spec": "pipeline", + "enable-api-fields": "alpha"}) + }, + }, { + name: "pipelineSpec when disable-inline-spec all", + p: &Pipeline{ + ObjectMeta: metav1.ObjectMeta{Name: "pipeline"}, + Spec: PipelineSpec{ + Tasks: []PipelineTask{ + { + Name: "foo", + PipelineSpec: &PipelineSpec{Description: "foo-pipeline-description"}, + }, + }, + }, + }, + expectedError: *apis.ErrDisallowedFields("spec.tasks[0]" + "." + "pipelineSpec"), + wc: func(ctx context.Context) context.Context { + return cfgtesting.SetFeatureFlags(ctx, t, + map[string]string{ + "disable-inline-spec": "pipeline,taskrun,pipelinerun", + "enable-api-fields": "alpha"}) + }, + }, { + name: "taskSpec when disable-inline-spec", + p: &Pipeline{ + ObjectMeta: metav1.ObjectMeta{Name: "pipeline"}, + Spec: PipelineSpec{ + Description: "inline task", + Tasks: []PipelineTask{{ + Name: "task-spec", + TaskSpec: &EmbeddedTask{TaskSpec: getTaskSpec()}, + }}, + }, + }, + expectedError: *apis.ErrDisallowedFields("spec.tasks[0]" + "." + "taskSpec"), + wc: func(ctx context.Context) context.Context { + return config.ToContext(ctx, &config.Config{ + FeatureFlags: &config.FeatureFlags{ + DisableInlineSpec: "pipeline", + }, + }) + }, + }, { + name: "taskSpec when disable-inline-spec all", + p: &Pipeline{ + ObjectMeta: metav1.ObjectMeta{Name: "pipeline"}, + Spec: PipelineSpec{ + Description: "inline task", + Tasks: []PipelineTask{{ + Name: "task-spec", + TaskSpec: &EmbeddedTask{TaskSpec: getTaskSpec()}, + }}, + }, + }, + expectedError: *apis.ErrDisallowedFields("spec.tasks[0]" + "." + "taskSpec"), + wc: func(ctx context.Context) context.Context { + return config.ToContext(ctx, &config.Config{ + FeatureFlags: &config.FeatureFlags{ + DisableInlineSpec: "pipeline,pipelinerun,taskrun", + }, + }) + }, }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/apis/pipeline/v1/pipelinerun_types.go b/pkg/apis/pipeline/v1/pipelinerun_types.go index 9c9bcd85566..f171719d6a0 100644 --- a/pkg/apis/pipeline/v1/pipelinerun_types.go +++ b/pkg/apis/pipeline/v1/pipelinerun_types.go @@ -249,6 +249,8 @@ func (pr *PipelineRun) HasVolumeClaimTemplate() bool { type PipelineRunSpec struct { // +optional PipelineRef *PipelineRef `json:"pipelineRef,omitempty"` + // Specifying PipelineSpec can be disabled by setting + // `disable-inline-spec` feature flag.. // +optional PipelineSpec *PipelineSpec `json:"pipelineSpec,omitempty"` // Params is a list of parameter names and values. diff --git a/pkg/apis/pipeline/v1/pipelinerun_validation.go b/pkg/apis/pipeline/v1/pipelinerun_validation.go index aea583b940b..d45b00ab8e3 100644 --- a/pkg/apis/pipeline/v1/pipelinerun_validation.go +++ b/pkg/apis/pipeline/v1/pipelinerun_validation.go @@ -19,6 +19,8 @@ package v1 import ( "context" "fmt" + "slices" + "strings" "time" "github.com/tektoncd/pipeline/pkg/apis/config" @@ -68,6 +70,10 @@ func (ps *PipelineRunSpec) Validate(ctx context.Context) (errs *apis.FieldError) // Validate PipelineSpec if it's present if ps.PipelineSpec != nil { + if slices.Contains(strings.Split( + config.FromContextOrDefaults(ctx).FeatureFlags.DisableInlineSpec, ","), "pipelinerun") { + errs = errs.Also(apis.ErrDisallowedFields("pipelineSpec")) + } errs = errs.Also(ps.PipelineSpec.Validate(ctx).ViaField("pipelineSpec")) } diff --git a/pkg/apis/pipeline/v1/pipelinerun_validation_test.go b/pkg/apis/pipeline/v1/pipelinerun_validation_test.go index 825002d0a36..8e7f24a0e87 100644 --- a/pkg/apis/pipeline/v1/pipelinerun_validation_test.go +++ b/pkg/apis/pipeline/v1/pipelinerun_validation_test.go @@ -22,6 +22,7 @@ import ( "time" "github.com/google/go-cmp/cmp" + "github.com/tektoncd/pipeline/pkg/apis/config" cfgtesting "github.com/tektoncd/pipeline/pkg/apis/config/testing" "github.com/tektoncd/pipeline/pkg/apis/pipeline/pod" v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" @@ -877,6 +878,44 @@ func TestPipelineRunSpec_Invalidate(t *testing.T) { }}}, }, wantErr: apis.ErrMultipleOneOf("pipelineRef", "pipelineSpec"), + }, { + name: "pipelineSpec when inline disabled all", + spec: v1.PipelineRunSpec{ + PipelineSpec: &v1.PipelineSpec{ + Tasks: []v1.PipelineTask{{ + Name: "mytask", + TaskRef: &v1.TaskRef{ + Name: "mytask", + }, + }}}, + }, + wantErr: apis.ErrDisallowedFields("pipelineSpec"), + withContext: func(ctx context.Context) context.Context { + return config.ToContext(ctx, &config.Config{ + FeatureFlags: &config.FeatureFlags{ + DisableInlineSpec: "taskrun,pipelinerun,pipeline", + }, + }) + }, + }, { + name: "pipelineSpec when inline disabled", + spec: v1.PipelineRunSpec{ + PipelineSpec: &v1.PipelineSpec{ + Tasks: []v1.PipelineTask{{ + Name: "mytask", + TaskRef: &v1.TaskRef{ + Name: "mytask", + }, + }}}, + }, + wantErr: apis.ErrDisallowedFields("pipelineSpec"), + withContext: func(ctx context.Context) context.Context { + return config.ToContext(ctx, &config.Config{ + FeatureFlags: &config.FeatureFlags{ + DisableInlineSpec: "pipelinerun", + }, + }) + }, }, { name: "workspaces may only appear once", spec: v1.PipelineRunSpec{ diff --git a/pkg/apis/pipeline/v1/swagger.json b/pkg/apis/pipeline/v1/swagger.json index e014703014c..8993af2ffff 100644 --- a/pkg/apis/pipeline/v1/swagger.json +++ b/pkg/apis/pipeline/v1/swagger.json @@ -669,6 +669,7 @@ "$ref": "#/definitions/v1.PipelineRef" }, "pipelineSpec": { + "description": "Specifying PipelineSpec can be disabled by setting `disable-inline-spec` feature flag..", "$ref": "#/definitions/v1.PipelineSpec" }, "status": { @@ -969,7 +970,7 @@ "$ref": "#/definitions/v1.PipelineRef" }, "pipelineSpec": { - "description": "PipelineSpec is a specification of a pipeline Note: PipelineSpec is in preview mode and not yet supported", + "description": "PipelineSpec is a specification of a pipeline Note: PipelineSpec is in preview mode and not yet supported Specifying PipelineSpec can be disabled by setting `disable-inline-spec` feature flag..", "$ref": "#/definitions/v1.PipelineSpec" }, "retries": { @@ -991,7 +992,7 @@ "$ref": "#/definitions/v1.TaskRef" }, "taskSpec": { - "description": "TaskSpec is a specification of a task", + "description": "TaskSpec is a specification of a task Specifying TaskSpec can be disabled by setting `disable-inline-spec` feature flag..", "$ref": "#/definitions/v1.EmbeddedTask" }, "timeout": { @@ -2074,6 +2075,7 @@ "$ref": "#/definitions/v1.TaskRef" }, "taskSpec": { + "description": "Specifying PipelineSpec can be disabled by setting `disable-inline-spec` feature flag..", "$ref": "#/definitions/v1.TaskSpec" }, "timeout": { diff --git a/pkg/apis/pipeline/v1/taskrun_types.go b/pkg/apis/pipeline/v1/taskrun_types.go index d2d017a0f95..615eaaa788c 100644 --- a/pkg/apis/pipeline/v1/taskrun_types.go +++ b/pkg/apis/pipeline/v1/taskrun_types.go @@ -43,6 +43,8 @@ type TaskRunSpec struct { // no more than one of the TaskRef and TaskSpec may be specified. // +optional TaskRef *TaskRef `json:"taskRef,omitempty"` + // Specifying PipelineSpec can be disabled by setting + // `disable-inline-spec` feature flag.. // +optional TaskSpec *TaskSpec `json:"taskSpec,omitempty"` // Used for cancelling a TaskRun (and maybe more later on) diff --git a/pkg/apis/pipeline/v1/taskrun_validation.go b/pkg/apis/pipeline/v1/taskrun_validation.go index 9ad832ae324..771d684d40c 100644 --- a/pkg/apis/pipeline/v1/taskrun_validation.go +++ b/pkg/apis/pipeline/v1/taskrun_validation.go @@ -63,6 +63,10 @@ func (ts *TaskRunSpec) Validate(ctx context.Context) (errs *apis.FieldError) { } // Validate TaskSpec if it's present. if ts.TaskSpec != nil { + if slices.Contains(strings.Split( + config.FromContextOrDefaults(ctx).FeatureFlags.DisableInlineSpec, ","), "taskrun") { + errs = errs.Also(apis.ErrDisallowedFields("taskSpec")) + } errs = errs.Also(ts.TaskSpec.Validate(ctx).ViaField("taskSpec")) } diff --git a/pkg/apis/pipeline/v1/taskrun_validation_test.go b/pkg/apis/pipeline/v1/taskrun_validation_test.go index 9652b2d4130..978b3164a1c 100644 --- a/pkg/apis/pipeline/v1/taskrun_validation_test.go +++ b/pkg/apis/pipeline/v1/taskrun_validation_test.go @@ -548,6 +548,42 @@ func TestTaskRunSpec_Invalidate(t *testing.T) { }, }, wantErr: apis.ErrMultipleOneOf("taskRef", "taskSpec"), + }, { + name: "taskspec when inline disabled", + spec: v1.TaskRunSpec{ + TaskSpec: &v1.TaskSpec{ + Steps: []v1.Step{{ + Name: "mystep", + Image: "myimage", + }}, + }, + }, + wantErr: apis.ErrDisallowedFields("taskSpec"), + wc: func(ctx context.Context) context.Context { + return config.ToContext(ctx, &config.Config{ + FeatureFlags: &config.FeatureFlags{ + DisableInlineSpec: "taskrun", + }, + }) + }, + }, { + name: "taskspec when inline disabled all", + spec: v1.TaskRunSpec{ + TaskSpec: &v1.TaskSpec{ + Steps: []v1.Step{{ + Name: "mystep", + Image: "myimage", + }}, + }, + }, + wantErr: apis.ErrDisallowedFields("taskSpec"), + wc: func(ctx context.Context) context.Context { + return config.ToContext(ctx, &config.Config{ + FeatureFlags: &config.FeatureFlags{ + DisableInlineSpec: "taskrun,pipelinerun,pipeline", + }, + }) + }, }, { name: "negative pipeline timeout", spec: v1.TaskRunSpec{ diff --git a/pkg/apis/pipeline/v1beta1/openapi_generated.go b/pkg/apis/pipeline/v1beta1/openapi_generated.go index 72277eb914e..d938565b86d 100644 --- a/pkg/apis/pipeline/v1beta1/openapi_generated.go +++ b/pkg/apis/pipeline/v1beta1/openapi_generated.go @@ -1994,7 +1994,8 @@ func schema_pkg_apis_pipeline_v1beta1_PipelineRunSpec(ref common.ReferenceCallba }, "pipelineSpec": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1.PipelineSpec"), + Description: "Specifying PipelineSpec can be disabled by setting `disable-inline-spec` feature flag..", + Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1.PipelineSpec"), }, }, "resources": { @@ -2673,7 +2674,7 @@ func schema_pkg_apis_pipeline_v1beta1_PipelineTask(ref common.ReferenceCallback) }, "taskSpec": { SchemaProps: spec.SchemaProps{ - Description: "TaskSpec is a specification of a task", + Description: "TaskSpec is a specification of a task Specifying TaskSpec can be disabled by setting `disable-inline-spec` feature flag..", Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1.EmbeddedTask"), }, }, @@ -2782,7 +2783,7 @@ func schema_pkg_apis_pipeline_v1beta1_PipelineTask(ref common.ReferenceCallback) }, "pipelineSpec": { SchemaProps: spec.SchemaProps{ - Description: "PipelineSpec is a specification of a pipeline Note: PipelineSpec is in preview mode and not yet supported", + Description: "PipelineSpec is a specification of a pipeline Note: PipelineSpec is in preview mode and not yet supported Specifying TaskSpec can be disabled by setting `disable-inline-spec` feature flag..", Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1.PipelineSpec"), }, }, @@ -5203,7 +5204,8 @@ func schema_pkg_apis_pipeline_v1beta1_TaskRunSpec(ref common.ReferenceCallback) }, "taskSpec": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1.TaskSpec"), + Description: "Specifying PipelineSpec can be disabled by setting `disable-inline-spec` feature flag..", + Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1.TaskSpec"), }, }, "status": { diff --git a/pkg/apis/pipeline/v1beta1/pipeline_types.go b/pkg/apis/pipeline/v1beta1/pipeline_types.go index 256f24f1dcf..804bcbd34f4 100644 --- a/pkg/apis/pipeline/v1beta1/pipeline_types.go +++ b/pkg/apis/pipeline/v1beta1/pipeline_types.go @@ -209,6 +209,8 @@ type PipelineTask struct { TaskRef *TaskRef `json:"taskRef,omitempty"` // TaskSpec is a specification of a task + // Specifying TaskSpec can be disabled by setting + // `disable-inline-spec` feature flag.. // +optional TaskSpec *EmbeddedTask `json:"taskSpec,omitempty"` @@ -257,6 +259,8 @@ type PipelineTask struct { // PipelineSpec is a specification of a pipeline // Note: PipelineSpec is in preview mode and not yet supported + // Specifying TaskSpec can be disabled by setting + // `disable-inline-spec` feature flag.. // +optional PipelineSpec *PipelineSpec `json:"pipelineSpec,omitempty"` diff --git a/pkg/apis/pipeline/v1beta1/pipeline_validation.go b/pkg/apis/pipeline/v1beta1/pipeline_validation.go index ac5b5c5c797..f1c34eee5e5 100644 --- a/pkg/apis/pipeline/v1beta1/pipeline_validation.go +++ b/pkg/apis/pipeline/v1beta1/pipeline_validation.go @@ -31,6 +31,7 @@ import ( "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation" + "k8s.io/utils/strings/slices" "knative.dev/pkg/apis" "knative.dev/pkg/webhook/resourcesemantics" ) @@ -179,6 +180,8 @@ func (pt PipelineTask) ValidateName() *apis.FieldError { func (pt PipelineTask) Validate(ctx context.Context) (errs *apis.FieldError) { errs = errs.Also(pt.validateRefOrSpec(ctx)) + errs = errs.Also(pt.validateEnabledInlineSpec(ctx)) + errs = errs.Also(pt.validateEmbeddedOrType()) if pt.Resources != nil { @@ -222,6 +225,24 @@ func (pt PipelineTask) Validate(ctx context.Context) (errs *apis.FieldError) { return //nolint:nakedret } +// validateEnabledInlineSpec validates that pipelineSpec or taskSpec is allowed by checking +// disable-inline-spec field +func (pt PipelineTask) validateEnabledInlineSpec(ctx context.Context) (errs *apis.FieldError) { + if pt.TaskSpec != nil { + if slices.Contains(strings.Split( + config.FromContextOrDefaults(ctx).FeatureFlags.DisableInlineSpec, ","), "pipeline") { + errs = errs.Also(apis.ErrDisallowedFields("taskSpec")) + } + } + if pt.PipelineSpec != nil { + if slices.Contains(strings.Split( + config.FromContextOrDefaults(ctx).FeatureFlags.DisableInlineSpec, ","), "pipeline") { + errs = errs.Also(apis.ErrDisallowedFields("pipelineSpec")) + } + } + return errs +} + func (pt *PipelineTask) validateMatrix(ctx context.Context) (errs *apis.FieldError) { if pt.IsMatrixed() { // This is a beta feature and will fail validation if it's used in a pipeline spec diff --git a/pkg/apis/pipeline/v1beta1/pipeline_validation_test.go b/pkg/apis/pipeline/v1beta1/pipeline_validation_test.go index 602ea92ddd5..adb5810009b 100644 --- a/pkg/apis/pipeline/v1beta1/pipeline_validation_test.go +++ b/pkg/apis/pipeline/v1beta1/pipeline_validation_test.go @@ -287,6 +287,86 @@ func TestPipeline_Validate_Failure(t *testing.T) { Message: `expected exactly one, got multiple`, Paths: []string{"spec.tasks[0].pipelineRef, spec.tasks[0].pipelineSpec"}, }, + }, { + name: "pipelineSpec when disable-inline-spec", + p: &Pipeline{ + ObjectMeta: metav1.ObjectMeta{Name: "pipeline"}, + Spec: PipelineSpec{ + Tasks: []PipelineTask{ + { + Name: "foo", + PipelineSpec: &PipelineSpec{Description: "foo-pipeline-description"}, + }, + }, + }, + }, + expectedError: *apis.ErrDisallowedFields("spec.tasks[0]" + "." + "pipelineSpec"), + wc: func(ctx context.Context) context.Context { + return cfgtesting.SetFeatureFlags(ctx, t, + map[string]string{ + "disable-inline-spec": "pipeline", + "enable-api-fields": "alpha"}) + }, + }, { + name: "pipelineSpec when disable-inline-spec all", + p: &Pipeline{ + ObjectMeta: metav1.ObjectMeta{Name: "pipeline"}, + Spec: PipelineSpec{ + Tasks: []PipelineTask{ + { + Name: "foo", + PipelineSpec: &PipelineSpec{Description: "foo-pipeline-description"}, + }, + }, + }, + }, + expectedError: *apis.ErrDisallowedFields("spec.tasks[0]" + "." + "pipelineSpec"), + wc: func(ctx context.Context) context.Context { + return cfgtesting.SetFeatureFlags(ctx, t, + map[string]string{ + "disable-inline-spec": "pipeline,taskrun,pipelinerun", + "enable-api-fields": "alpha"}) + }, + }, { + name: "taskSpec when disable-inline-spec", + p: &Pipeline{ + ObjectMeta: metav1.ObjectMeta{Name: "pipeline"}, + Spec: PipelineSpec{ + Description: "inline task", + Tasks: []PipelineTask{{ + Name: "task-spec", + TaskSpec: &EmbeddedTask{TaskSpec: getTaskSpec()}, + }}, + }, + }, + expectedError: *apis.ErrDisallowedFields("spec.tasks[0]" + "." + "taskSpec"), + wc: func(ctx context.Context) context.Context { + return config.ToContext(ctx, &config.Config{ + FeatureFlags: &config.FeatureFlags{ + DisableInlineSpec: "pipeline", + }, + }) + }, + }, { + name: "taskSpec when disable-inline-spec all", + p: &Pipeline{ + ObjectMeta: metav1.ObjectMeta{Name: "pipeline"}, + Spec: PipelineSpec{ + Description: "inline task", + Tasks: []PipelineTask{{ + Name: "task-spec", + TaskSpec: &EmbeddedTask{TaskSpec: getTaskSpec()}, + }}, + }, + }, + expectedError: *apis.ErrDisallowedFields("spec.tasks[0]" + "." + "taskSpec"), + wc: func(ctx context.Context) context.Context { + return config.ToContext(ctx, &config.Config{ + FeatureFlags: &config.FeatureFlags{ + DisableInlineSpec: "pipeline,pipelinerun,taskrun", + }, + }) + }, }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/apis/pipeline/v1beta1/pipelinerun_types.go b/pkg/apis/pipeline/v1beta1/pipelinerun_types.go index c3a111a978b..453c3778c06 100644 --- a/pkg/apis/pipeline/v1beta1/pipelinerun_types.go +++ b/pkg/apis/pipeline/v1beta1/pipelinerun_types.go @@ -252,6 +252,8 @@ func (pr *PipelineRun) HasVolumeClaimTemplate() bool { type PipelineRunSpec struct { // +optional PipelineRef *PipelineRef `json:"pipelineRef,omitempty"` + // Specifying PipelineSpec can be disabled by setting + // `disable-inline-spec` feature flag.. // +optional PipelineSpec *PipelineSpec `json:"pipelineSpec,omitempty"` // Resources is a list of bindings specifying which actual instances of diff --git a/pkg/apis/pipeline/v1beta1/pipelinerun_validation.go b/pkg/apis/pipeline/v1beta1/pipelinerun_validation.go index f7c434eb7b4..7113b653620 100644 --- a/pkg/apis/pipeline/v1beta1/pipelinerun_validation.go +++ b/pkg/apis/pipeline/v1beta1/pipelinerun_validation.go @@ -19,6 +19,7 @@ package v1beta1 import ( "context" "fmt" + "strings" "time" "github.com/tektoncd/pipeline/pkg/apis/config" @@ -27,6 +28,7 @@ import ( admissionregistrationv1 "k8s.io/api/admissionregistration/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/utils/strings/slices" "knative.dev/pkg/apis" "knative.dev/pkg/webhook/resourcesemantics" ) @@ -73,6 +75,10 @@ func (ps *PipelineRunSpec) Validate(ctx context.Context) (errs *apis.FieldError) // Validate PipelineSpec if it's present if ps.PipelineSpec != nil { + if slices.Contains(strings.Split( + config.FromContextOrDefaults(ctx).FeatureFlags.DisableInlineSpec, ","), "pipelinerun") { + errs = errs.Also(apis.ErrDisallowedFields("pipelineSpec")) + } errs = errs.Also(ps.PipelineSpec.Validate(ctx).ViaField("pipelineSpec")) } diff --git a/pkg/apis/pipeline/v1beta1/pipelinerun_validation_test.go b/pkg/apis/pipeline/v1beta1/pipelinerun_validation_test.go index 61cdd7bfe47..15e044591a4 100644 --- a/pkg/apis/pipeline/v1beta1/pipelinerun_validation_test.go +++ b/pkg/apis/pipeline/v1beta1/pipelinerun_validation_test.go @@ -22,6 +22,7 @@ import ( "time" "github.com/google/go-cmp/cmp" + "github.com/tektoncd/pipeline/pkg/apis/config" cfgtesting "github.com/tektoncd/pipeline/pkg/apis/config/testing" "github.com/tektoncd/pipeline/pkg/apis/pipeline/pod" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" @@ -996,6 +997,44 @@ func TestPipelineRunSpec_Invalidate(t *testing.T) { }}}, }, wantErr: apis.ErrMultipleOneOf("pipelineRef", "pipelineSpec"), + }, { + name: "pipelineSpec when inline disabled all", + spec: v1beta1.PipelineRunSpec{ + PipelineSpec: &v1beta1.PipelineSpec{ + Tasks: []v1beta1.PipelineTask{{ + Name: "mytask", + TaskRef: &v1beta1.TaskRef{ + Name: "mytask", + }, + }}}, + }, + wantErr: apis.ErrDisallowedFields("pipelineSpec"), + withContext: func(ctx context.Context) context.Context { + return config.ToContext(ctx, &config.Config{ + FeatureFlags: &config.FeatureFlags{ + DisableInlineSpec: "taskrun,pipelinerun,pipeline", + }, + }) + }, + }, { + name: "pipelineSpec when inline disabled", + spec: v1beta1.PipelineRunSpec{ + PipelineSpec: &v1beta1.PipelineSpec{ + Tasks: []v1beta1.PipelineTask{{ + Name: "mytask", + TaskRef: &v1beta1.TaskRef{ + Name: "mytask", + }, + }}}, + }, + wantErr: apis.ErrDisallowedFields("pipelineSpec"), + withContext: func(ctx context.Context) context.Context { + return config.ToContext(ctx, &config.Config{ + FeatureFlags: &config.FeatureFlags{ + DisableInlineSpec: "pipelinerun", + }, + }) + }, }, { name: "workspaces may only appear once", spec: v1beta1.PipelineRunSpec{ diff --git a/pkg/apis/pipeline/v1beta1/swagger.json b/pkg/apis/pipeline/v1beta1/swagger.json index 4fd2b41fd3f..622b1d680c3 100644 --- a/pkg/apis/pipeline/v1beta1/swagger.json +++ b/pkg/apis/pipeline/v1beta1/swagger.json @@ -1010,6 +1010,7 @@ "$ref": "#/definitions/v1beta1.PipelineRef" }, "pipelineSpec": { + "description": "Specifying PipelineSpec can be disabled by setting `disable-inline-spec` feature flag..", "$ref": "#/definitions/v1beta1.PipelineSpec" }, "podTemplate": { @@ -1362,7 +1363,7 @@ "$ref": "#/definitions/v1beta1.PipelineRef" }, "pipelineSpec": { - "description": "PipelineSpec is a specification of a pipeline Note: PipelineSpec is in preview mode and not yet supported", + "description": "PipelineSpec is a specification of a pipeline Note: PipelineSpec is in preview mode and not yet supported Specifying TaskSpec can be disabled by setting `disable-inline-spec` feature flag..", "$ref": "#/definitions/v1beta1.PipelineSpec" }, "resources": { @@ -1388,7 +1389,7 @@ "$ref": "#/definitions/v1beta1.TaskRef" }, "taskSpec": { - "description": "TaskSpec is a specification of a task", + "description": "TaskSpec is a specification of a task Specifying TaskSpec can be disabled by setting `disable-inline-spec` feature flag..", "$ref": "#/definitions/v1beta1.EmbeddedTask" }, "timeout": { @@ -2892,6 +2893,7 @@ "$ref": "#/definitions/v1beta1.TaskRef" }, "taskSpec": { + "description": "Specifying PipelineSpec can be disabled by setting `disable-inline-spec` feature flag..", "$ref": "#/definitions/v1beta1.TaskSpec" }, "timeout": { diff --git a/pkg/apis/pipeline/v1beta1/taskrun_types.go b/pkg/apis/pipeline/v1beta1/taskrun_types.go index 4d6e13ee544..551a5856ed6 100644 --- a/pkg/apis/pipeline/v1beta1/taskrun_types.go +++ b/pkg/apis/pipeline/v1beta1/taskrun_types.go @@ -48,6 +48,8 @@ type TaskRunSpec struct { // no more than one of the TaskRef and TaskSpec may be specified. // +optional TaskRef *TaskRef `json:"taskRef,omitempty"` + // Specifying PipelineSpec can be disabled by setting + // `disable-inline-spec` feature flag.. // +optional TaskSpec *TaskSpec `json:"taskSpec,omitempty"` // Used for cancelling a TaskRun (and maybe more later on) diff --git a/pkg/apis/pipeline/v1beta1/taskrun_validation.go b/pkg/apis/pipeline/v1beta1/taskrun_validation.go index 8dd96f0ef99..b44b3d42e2c 100644 --- a/pkg/apis/pipeline/v1beta1/taskrun_validation.go +++ b/pkg/apis/pipeline/v1beta1/taskrun_validation.go @@ -63,6 +63,10 @@ func (ts *TaskRunSpec) Validate(ctx context.Context) (errs *apis.FieldError) { } // Validate TaskSpec if it's present. if ts.TaskSpec != nil { + if slices.Contains(strings.Split( + config.FromContextOrDefaults(ctx).FeatureFlags.DisableInlineSpec, ","), "taskrun") { + errs = errs.Also(apis.ErrDisallowedFields("taskSpec")) + } errs = errs.Also(ts.TaskSpec.Validate(ctx).ViaField("taskSpec")) } diff --git a/pkg/apis/pipeline/v1beta1/taskrun_validation_test.go b/pkg/apis/pipeline/v1beta1/taskrun_validation_test.go index 3005c14c357..3bab6c0e77c 100644 --- a/pkg/apis/pipeline/v1beta1/taskrun_validation_test.go +++ b/pkg/apis/pipeline/v1beta1/taskrun_validation_test.go @@ -565,6 +565,42 @@ func TestTaskRunSpec_Invalidate(t *testing.T) { StatusMessage: v1beta1.TaskRunSpecStatusMessage(invalidStatusMessage), }, wantErr: apis.ErrInvalidValue("statusMessage should not be set if status is not set, but it is currently set to "+invalidStatusMessage, "statusMessage"), + }, { + name: "taskspec when inline disabled", + spec: v1beta1.TaskRunSpec{ + TaskSpec: &v1beta1.TaskSpec{ + Steps: []v1beta1.Step{{ + Name: "mystep", + Image: "myimage", + }}, + }, + }, + wantErr: apis.ErrDisallowedFields("taskSpec"), + wc: func(ctx context.Context) context.Context { + return config.ToContext(ctx, &config.Config{ + FeatureFlags: &config.FeatureFlags{ + DisableInlineSpec: "taskrun", + }, + }) + }, + }, { + name: "taskspec when inline disabled all", + spec: v1beta1.TaskRunSpec{ + TaskSpec: &v1beta1.TaskSpec{ + Steps: []v1beta1.Step{{ + Name: "mystep", + Image: "myimage", + }}, + }, + }, + wantErr: apis.ErrDisallowedFields("taskSpec"), + wc: func(ctx context.Context) context.Context { + return config.ToContext(ctx, &config.Config{ + FeatureFlags: &config.FeatureFlags{ + DisableInlineSpec: "taskrun,pipelinerun,pipeline", + }, + }) + }, }, { name: "invalid taskspec", spec: v1beta1.TaskRunSpec{ diff --git a/pkg/reconciler/taskrun/taskrun_test.go b/pkg/reconciler/taskrun/taskrun_test.go index 6f9fbd919c4..31f2ba22d1e 100644 --- a/pkg/reconciler/taskrun/taskrun_test.go +++ b/pkg/reconciler/taskrun/taskrun_test.go @@ -1704,6 +1704,7 @@ status: ResultExtractionMethod: "termination-message" MaxResultSize: 4096 Coschedule: "workspaces" + DisableInlineSpec: "" provenance: featureFlags: RunningInEnvWithInjectedSidecars: true @@ -1716,6 +1717,7 @@ status: ResultExtractionMethod: "termination-message" MaxResultSize: 4096 Coschedule: "workspaces" + DisableInlineSpec: "" `, pipelineErrors.UserErrorLabel, pipelineErrors.UserErrorLabel)) reconciliatonError = errors.New("1 error occurred:\n\t* Provided results don't match declared results; may be invalid JSON or missing result declaration: \"aResult\": task result is expected to be \"array\" type but was initialized to a different type \"string\"") toBeRetriedTaskRun = parse.MustParseV1TaskRun(t, ` @@ -1769,6 +1771,7 @@ status: ResultExtractionMethod: "termination-message" MaxResultSize: 4096 Coschedule: "workspaces" + DisableInlineSpec: "" `) toBeRetriedWithResultsTaskRun = parse.MustParseV1TaskRun(t, ` metadata: