Repository: tektoncd/operator
Pull request #1475 (2023-05-08 02:06:11)

[bot] bump payload versions
Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action

tekton-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **vdemeester** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @vdemeester` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://prow.tekton.dev/command-help?repo=tektoncd%2Foperator).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/tektoncd/operator/blob/main/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["vdemeester"]} -->
tekton-robot: Hi @github-actions[bot]. Thanks for your PR.

I'm waiting for a [tektoncd](https://github.com/orgs/tektoncd/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://github.com/orgs/tektoncd/people) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=tektoncd%2Foperator).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>


Patch:
diff --git a/components.yaml b/components.yaml
index 41c9bd5f6..54e96eb20 100644
--- a/components.yaml
+++ b/components.yaml
@@ -1,6 +1,6 @@
 chains:
   github: tektoncd/chains
-  version: v0.15.0
+  version: v0.16.0
 dashboard:
   github: tektoncd/dashboard
   version: v0.35.0
diff --git a/docs/TektonConfig.md b/docs/TektonConfig.md
index fa2f0fc46..25cd24de5 100644
--- a/docs/TektonConfig.md
+++ b/docs/TektonConfig.md
@@ -58,6 +58,7 @@ The TektonConfig CR provides the following features
         kube-api-qps: 5.0
         kube-api-burst: 10
     pruner:
+      disabled: false
       resources:
       - taskrun
       - pipelinerun
@@ -155,6 +156,7 @@ Pruner provides auto clean up feature for the Tekton resources.
 Example:
 ```yaml
 pruner:
+  disabled: false
   resources:
     - taskrun
     - pipelinerun
@@ -162,14 +164,31 @@ pruner:
   keep-since: 1440
   schedule: "* * * * *"
 ```
+- `disabled` : if the value set as `true`, pruner feature will be disabled (default: `false`)
 - `prune-per-resource`: if the value set as `true` (default value `false`), the `keep` and `keep-since` applied to each resource. example: `tkn pipelinerun delete --pipeline=my-pipeline --keep=10`
 - `resources`: supported resources for auto prune are `taskrun` and `pipelinerun`
 - `keep`: maximum number of resources to keep while deleting or removing resources
 - `keep-since`: retain the resources younger than the specified value in minutes
 - `schedule`: how often to clean up resources. User can understand the schedule syntax [here][schedule].
 
-This is an `Optional` section.
-
+> ### Note:
+> if `disabled: false` and `schedule: ` with empty value, global pruner job will be disabled.
+> however, if there is a prune schedule (`operator.tekton.dev/prune.schedule`) annotation present with a value in a namespace. a namespace wide pruner jobs will be created
+
+#### Pruner Namespace annotations
+By default pruner job will be created from the global pruner config (`spec.pruner`), though user can customize a pruner config to a specific namespace with the following annotations. If some of the annotations are not present or has invalid value, for that value, falls back to global value or skipped the namespace.
+- `operator.tekton.dev/prune.skip` - pruner job will be skipped to a namespace, if the value set as `true`
+- `operator.tekton.dev/prune.schedule` - pruner job will be created on a specific schedule
+- `operator.tekton.dev/prune.keep` - maximum number of resources will be kept
+- `operator.tekton.dev/prune.keep-since` - retain the resources younger than the specified value in minutes
+- `operator.tekton.dev/prune.prune-per-resource` - the `keep` and `keep-since` applied to each resource
+- `operator.tekton.dev/prune.resources` - can be `taskrun` and/or `pipelinerun`, both value can be specified with comma separated. example: `taskrun,pipelinerun`
+- `operator.tekton.dev/prune.strategy` - allowed values: either `keep` or `keep-since`
+
+> ### Note: 
+> if a global value is not present the following values will be consider as default value <br> 
+> `resources: pipelinerun` <br>
+> `keep: 100` <br>
 ### Addon
 
 TektonAddon install some resources along with Tekton Pipelines on the cluster. This provides few ClusterTasks, PipelineTemplates.
diff --git a/pkg/apis/operator/v1alpha1/const.go b/pkg/apis/operator/v1alpha1/const.go
index cb012d421..8b2bb5193 100644
--- a/pkg/apis/operator/v1alpha1/const.go
+++ b/pkg/apis/operator/v1alpha1/const.go
@@ -54,6 +54,10 @@ const (
 	Reinstalling   = "reinstalling"
 
 	RequeueDelay = 10 * time.Second
+
+	// pruner default schedule, used in auto generate tektonConfig
+	PrunerDefaultSchedule = "0 8 * * *"
+	PrunerDefaultKeep     = uint(100)
 )
 
 var (
@@ -90,6 +94,11 @@ var (
 		"pipelinerun",
 	}
 
+	// pruner default resource, used in auto generate tektonConfig
+	PruningDefaultResources = []string{
+		"pipelinerun",
+	}
+
 	AddonParams = map[string]ParamValue{
 		ClusterTasksParam:      defaultParamValue,
 		PipelineTemplatesParam: defaultParamValue,
diff --git a/pkg/apis/operator/v1alpha1/tektonconfig_defaults.go b/pkg/apis/operator/v1alpha1/tektonconfig_defaults.go
index 5e51739ea..173d20123 100644
--- a/pkg/apis/operator/v1alpha1/tektonconfig_defaults.go
+++ b/pkg/apis/operator/v1alpha1/tektonconfig_defaults.go
@@ -18,6 +18,7 @@ package v1alpha1
 
 import (
 	"context"
+	"strings"
 
 	"knative.dev/pkg/ptr"
 )
@@ -59,19 +60,28 @@ func (tc *TektonConfig) SetDefaults(ctx context.Context) {
 		tc.Spec.Platforms.OpenShift = OpenShift{}
 	}
 
-	// before adding webhook we had default value for pruner's keep as 1
-	// but we expect user to define all values now otherwise webhook reject
-	// request so if a user has installed prev version and has not enabled
-	// pruner then `keep` will have a value 1 and after upgrading
-	// to newer version webhook will fail if keep has a value and
-	// other fields are not defined
-	// this handles that case by removing the default for keep if
-	// other pruner fields are not defined
-	if len(tc.Spec.Pruner.Resources) == 0 {
-		tc.Spec.Pruner.Keep = nil
-		tc.Spec.Pruner.Schedule = ""
-	} else if tc.Spec.Pruner.Schedule == "" {
-		tc.Spec.Pruner.Keep = nil
-		tc.Spec.Pruner.Resources = []string{}
+	// earlier pruner was disabled with empty schedule or empty resources
+	// now empty schedule, disables only the global cron job,
+	// if a namespace has prune schedule annotation, a cron job will be created for that
+	// to disable the pruner feature, "disabled" should be set as "true"
+	if !tc.Spec.Pruner.Disabled {
+		// if keep and keep-since is nil, update default keep value
+		if tc.Spec.Pruner.Keep == nil && tc.Spec.Pruner.KeepSince == nil {
+			keep := PrunerDefaultKeep
+			tc.Spec.Pruner.Keep = &keep
+		}
+
+		// if empty resources, update default resources
+		if len(tc.Spec.Pruner.Resources) == 0 {
+			tc.Spec.Pruner.Resources = PruningDefaultResources
+		}
+
+		// trim space and to lower case resource names
+		for index := range tc.Spec.Pruner.Resources {
+			value := tc.Spec.Pruner.Resources[index]
+			value = strings.TrimSpace(value)
+			value = strings.ToLower(value)
+			tc.Spec.Pruner.Resources[index] = value
+		}
 	}
 }
diff --git a/pkg/apis/operator/v1alpha1/tektonconfig_types.go b/pkg/apis/operator/v1alpha1/tektonconfig_types.go
index 391605090..70f14b048 100644
--- a/pkg/apis/operator/v1alpha1/tektonconfig_types.go
+++ b/pkg/apis/operator/v1alpha1/tektonconfig_types.go
@@ -49,6 +49,8 @@ func (tp *TektonConfig) GetStatus() TektonComponentStatus {
 
 // Prune defines the pruner
 type Prune struct {
+	// enable or disable pruner feature
+	Disabled bool `json:"disabled"`
 	// apply the prune job to the individual resources
 	// +optional
 	PrunePerResource bool `json:"prune-per-resource,omitempty"`
diff --git a/pkg/apis/operator/v1alpha1/tektonconfig_validation.go b/pkg/apis/operator/v1alpha1/tektonconfig_validation.go
index 261475eee..739e5630c 100644
--- a/pkg/apis/operator/v1alpha1/tektonconfig_validation.go
+++ b/pkg/apis/operator/v1alpha1/tektonconfig_validation.go
@@ -44,9 +44,8 @@ func (tc *TektonConfig) Validate(ctx context.Context) (errs *apis.FieldError) {
 		}
 	}
 
-	if !tc.Spec.Pruner.IsEmpty() {
-		errs = errs.Also(tc.Spec.Pruner.validate())
-	}
+	// validate pruner specifications
+	errs = errs.Also(tc.Spec.Pruner.validate())
 
 	if !tc.Spec.Addon.IsEmpty() {
 		errs = errs.Also(validateAddonParams(tc.Spec.Addon.Params, "spec.addon.params"))
@@ -64,6 +63,11 @@ func (tc *TektonConfig) Validate(ctx context.Context) (errs *apis.FieldError) {
 func (p Prune) validate() *apis.FieldError {
 	var errs *apis.FieldError
 
+	// if pruner job disable no validation required
+	if p.Disabled {
+		return errs
+	}
+
 	if len(p.Resources) != 0 {
 		for i, r := range p.Resources {
 			if !isValueInArray(PruningResource, r) {
@@ -84,10 +88,6 @@ func (p Prune) validate() *apis.FieldError {
 		errs = errs.Also(apis.ErrInvalidValue(*p.KeepSince, "spec.pruner.keep-since"))
 	}
 
-	if p.Schedule == "" {
-		errs = errs.Also(apis.ErrMissingField("spec.pruner.schedule"))
-	}
-
 	return errs
 }
 
diff --git a/pkg/reconciler/common/prune.go b/pkg/reconciler/common/prune.go
index 29b2b8ac3..73961ff71 100644
--- a/pkg/reconciler/common/prune.go
+++ b/pkg/reconciler/common/prune.go
@@ -192,7 +192,7 @@ func (pr *Pruner) reconcileCronJobs() error {
 	pruneConfigsMap := make(map[string][]pruneConfig)
 
 	// verify prune job enabled in TektonConfig CR
-	if pr.tektonConfig.Spec.Pruner.Schedule != "" && len(pr.tektonConfig.Spec.Pruner.Resources) != 0 {
+	if !pr.tektonConfig.Spec.Pruner.Disabled {
 		// collect namespace details
 		namespaceList, err := pr.kubeClientset.CoreV1().Namespaces().List(pr.ctx, metav1.ListOptions{})
 		if err != nil {
@@ -297,6 +297,21 @@ func (pr *Pruner) getPruneConfig(namespace *corev1.Namespace) *pruneConfig {
 		return nil
 	}
 
+	// if the global schedule is disabled and there is no prune schedule annotation present in a namespace
+	// skip that namespace
+	if defaultPruneConfig.Schedule == "" && pr.getMapString(annotations, pruneAnnotationSchedule, "") == "" {
+		return nil
+	}
+
+	// update missing values from defaults
+	if defaultPruneConfig.Keep == nil && defaultPruneConfig.KeepSince == nil {
+		keep := v1alpha1.PrunerDefaultKeep
+		defaultPruneConfig.Keep = &keep
+	}
+	if len(defaultPruneConfig.Resources) == 0 {
+		defaultPruneConfig.Resources = v1alpha1.PruningDefaultResources
+	}
+
 	// update keep and keep-since based on the strategy
 	pruneStrategy := pr.getMapString(annotations, pruneAnnotationStrategy, "")
 	// update keep value
diff --git a/pkg/reconciler/shared/tektonconfig/instance.go b/pkg/reconciler/shared/tektonconfig/instance.go
index 52e3d8ed7..1534fd5c9 100644
--- a/pkg/reconciler/shared/tektonconfig/instance.go
+++ b/pkg/reconciler/shared/tektonconfig/instance.go
@@ -99,7 +99,7 @@ func (tc tektonConfig) ensureInstance(ctx context.Context) {
 }
 
 func (tc tektonConfig) createInstance(ctx context.Context) error {
-	pruneKeep := uint(100)
+	pruneKeep := v1alpha1.PrunerDefaultKeep
 	tcCR := &v1alpha1.TektonConfig{
 		ObjectMeta: metav1.ObjectMeta{
 			Name: v1alpha1.ConfigResourceName,
@@ -110,10 +110,11 @@ func (tc tektonConfig) createInstance(ctx context.Context) error {
 				TargetNamespace: tc.namespace,
 			},
 			Pruner: v1alpha1.Prune{
-				Resources: []string{"pipelinerun"},
+				Disabled:  false,
+				Resources: v1alpha1.PruningDefaultResources,
 				Keep:      &pruneKeep,
 				KeepSince: nil,
-				Schedule:  "0 8 * * *",
+				Schedule:  v1alpha1.PrunerDefaultSchedule,
 			},
 		},
 	}
diff --git a/pkg/reconciler/shared/tektonconfig/tektonconfig.go b/pkg/reconciler/shared/tektonconfig/tektonconfig.go
index a001dcbc8..5a23ddfbb 100644
--- a/pkg/reconciler/shared/tektonconfig/tektonconfig.go
+++ b/pkg/reconciler/shared/tektonconfig/tektonconfig.go
@@ -169,7 +169,7 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, tc *v1alpha1.TektonConfi
 	}
 
 	// reconcile pruner installerSet
-	if !tc.Spec.Pruner.IsEmpty() {
+	if !tc.Spec.Pruner.Disabled {
 		err := r.reconcilePrunerInstallerSet(ctx, tc)
 		if err != nil {
 			return err


Test patch:
diff --git a/pkg/apis/operator/v1alpha1/tektonconfig_validation_test.go b/pkg/apis/operator/v1alpha1/tektonconfig_validation_test.go
index 30f9529ba..7fb1f6b26 100644
--- a/pkg/apis/operator/v1alpha1/tektonconfig_validation_test.go
+++ b/pkg/apis/operator/v1alpha1/tektonconfig_validation_test.go
@@ -53,7 +53,9 @@ func Test_ValidateTektonConfig_MissingTargetNamespace(t *testing.T) {
 			Name:      "config",
 			Namespace: "namespace",
 		},
-		Spec: TektonConfigSpec{},
+		Spec: TektonConfigSpec{
+			Pruner: Prune{Disabled: true},
+		},
 	}
 
 	err := tc.Validate(context.TODO())
@@ -72,6 +74,7 @@ func Test_ValidateTektonConfig_InvalidProfile(t *testing.T) {
 				TargetNamespace: "namespace",
 			},
 			Profile: "test",
+			Pruner:  Prune{Disabled: true},
 		},
 	}
 
@@ -80,7 +83,6 @@ func Test_ValidateTektonConfig_InvalidProfile(t *testing.T) {
 }
 
 func Test_ValidateTektonConfig_InvalidPruningResource(t *testing.T) {
-
 	tc := &TektonConfig{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      "config",
@@ -99,7 +101,7 @@ func Test_ValidateTektonConfig_InvalidPruningResource(t *testing.T) {
 	}
 
 	err := tc.Validate(context.TODO())
-	assert.Equal(t, "expected exactly one, got neither: spec.pruner.keep, spec.pruner.keep-since\ninvalid value: task: spec.pruner.resources[0]\nmissing field(s): spec.pruner.schedule", err.Error())
+	assert.Equal(t, "expected exactly one, got neither: spec.pruner.keep, spec.pruner.keep-since\ninvalid value: task: spec.pruner.resources[0]", err.Error())
 }
 
 func Test_ValidateTektonConfig_MissingKeepKeepsinceSchedule(t *testing.T) {
@@ -121,30 +123,7 @@ func Test_ValidateTektonConfig_MissingKeepKeepsinceSchedule(t *testing.T) {
 	}
 
 	err := tc.Validate(context.TODO())
-	assert.Equal(t, "expected exactly one, got neither: spec.pruner.keep, spec.pruner.keep-since\nmissing field(s): spec.pruner.schedule", err.Error())
-}
-
-func Test_ValidateTektonConfig_MissingSchedule(t *testing.T) {
-	keep := uint(2)
-	tc := &TektonConfig{
-		ObjectMeta: metav1.ObjectMeta{
-			Name:      "config",
-			Namespace: "namespace",
-		},
-		Spec: TektonConfigSpec{
-			CommonSpec: CommonSpec{
-				TargetNamespace: "namespace",
-			},
-			Profile: "all",
-			Pruner: Prune{
-				Keep:      &keep,
-				Resources: []string{"taskrun"},
-			},
-		},
-	}
-
-	err := tc.Validate(context.TODO())
-	assert.Equal(t, "missing field(s): spec.pruner.schedule", err.Error())
+	assert.Equal(t, "expected exactly one, got neither: spec.pruner.keep, spec.pruner.keep-since", err.Error())
 }
 
 func Test_ValidateTektonConfig_InvalidAddonParam(t *testing.T) {
@@ -167,6 +146,7 @@ func Test_ValidateTektonConfig_InvalidAddonParam(t *testing.T) {
 					},
 				},
 			},
+			Pruner: Prune{Disabled: true},
 		},
 	}
 
@@ -194,6 +174,7 @@ func Test_ValidateTektonConfig_InvalidAddonParamValue(t *testing.T) {
 					},
 				},
 			},
+			Pruner: Prune{Disabled: true},
 		},
 	}
 
@@ -218,6 +199,7 @@ func Test_ValidateTektonConfig_InvalidPipelineProperties(t *testing.T) {
 					EnableApiFields: "test",
 				},
 			},
+			Pruner: Prune{Disabled: true},
 		},
 	}
 
@@ -242,6 +224,7 @@ func Test_ValidateTektonConfig_InvalidTriggerProperties(t *testing.T) {
 					EnableApiFields: "test",
 				},
 			},
+			Pruner: Prune{Disabled: true},
 		},
 	}
 
diff --git a/pkg/apis/operator/v1alpha1/tektonhub_validation_test.go b/pkg/apis/operator/v1alpha1/tektonhub_validation_test.go
index 9e457ec17..83bd96278 100644
--- a/pkg/apis/operator/v1alpha1/tektonhub_validation_test.go
+++ b/pkg/apis/operator/v1alpha1/tektonhub_validation_test.go
@@ -44,6 +44,7 @@ func Test_ValidateTektonConfig_InvalidHubParam(t *testing.T) {
 					},
 				},
 			},
+			Pruner: Prune{Disabled: true},
 		},
 	}
 
@@ -71,6 +72,7 @@ func Test_ValidateTektonConfig_InvalidHubParamValue(t *testing.T) {
 					},
 				},
 			},
+			Pruner: Prune{Disabled: true},
 		},
 	}
 
diff --git a/pkg/reconciler/common/prune_test.go b/pkg/reconciler/common/prune_test.go
index 0a0300298..16f63d9f0 100644
--- a/pkg/reconciler/common/prune_test.go
+++ b/pkg/reconciler/common/prune_test.go
@@ -601,6 +601,7 @@ func TestPrunerReconcile(t *testing.T) {
 					name: "TestPrunerEnabled",
 					applyChanges: func(tektonConfig *v1alpha1.TektonConfig, client *fake.Clientset, t *testing.T) func() {
 						tektonConfig.Spec.Pruner = v1alpha1.Prune{
+							Disabled:         false,
 							Keep:             getUintWithReference(20),
 							KeepSince:        nil,
 							Resources:        []string{"pipelinerun", "taskrun"},
@@ -628,14 +629,18 @@ func TestPrunerReconcile(t *testing.T) {
 					},
 				},
 				{ // reconcile #2
-					name: "TestPrunerDisabledWithEmptySchedule",
+					// only global schedule will be disable, if a namespace has prune schedule annotation, there will be a job for that
+					name: "TestPrunerGlobalScheduleDisabledWithEmptySchedule",
 					applyChanges: func(tektonConfig *v1alpha1.TektonConfig, client *fake.Clientset, t *testing.T) func() {
 						tektonConfig.Spec.Pruner.Schedule = ""
 						return nil
 					},
-					scheduleAndArgs: map[string]string{},
+					scheduleAndArgs: map[string]string{
+						"*/12 * * * *": "ns-seven;--keep=20,--keep-since=42;pipelinerun,taskrun;true",
+					},
 				},
 				{ // reconcile #3
+					// re-enables global schedule
 					name: "TestPrunerReEnabledSchedule",
 					applyChanges: func(tektonConfig *v1alpha1.TektonConfig, client *fake.Clientset, t *testing.T) func() {
 						tektonConfig.Spec.Pruner.Schedule = "*/5 * * * *"
@@ -647,15 +652,21 @@ func TestPrunerReconcile(t *testing.T) {
 					},
 				},
 				{ // reconcile #4
-					name: "TestPrunerDisabledWithEmptyResources",
+					// removes global resources
+					name: "TestPrunerWithGlobalEmptyResources",
 					applyChanges: func(tektonConfig *v1alpha1.TektonConfig, client *fake.Clientset, t *testing.T) func() {
 						tektonConfig.Spec.Pruner.Resources = []string{}
 						return nil
 					},
-					scheduleAndArgs: map[string]string{},
+					// default prune resources will be taken
+					scheduleAndArgs: map[string]string{
+						"*/5 * * * *":  "ns-one;--keep=20;pipelinerun;false ns-two;--keep=20;pipelinerun;false",
+						"*/12 * * * *": "ns-seven;--keep=20,--keep-since=42;pipelinerun;true",
+					},
 				},
 				{ // reconcile #5
-					name: "TestPrunerReEnabledWithAResource",
+					// adds global resources
+					name: "TestPrunerWithGlobalResources",
 					applyChanges: func(tektonConfig *v1alpha1.TektonConfig, client *fake.Clientset, t *testing.T) func() {
 						tektonConfig.Spec.Pruner.Resources = []string{"pipelinerun"}
 						return nil
@@ -666,7 +677,8 @@ func TestPrunerReconcile(t *testing.T) {
 					},
 				},
 				{ // reconcile #6
-					name: "TestPrunerReEnabledWithResources",
+					// modifies global resources
+					name: "TestPrunerUpdateGlobalResources",
 					applyChanges: func(tektonConfig *v1alpha1.TektonConfig, client *fake.Clientset, t *testing.T) func() {
 						tektonConfig.Spec.Pruner.Resources = []string{"pipelinerun", "taskrun"}
 						return nil
@@ -677,32 +689,63 @@ func TestPrunerReconcile(t *testing.T) {
 					},
 				},
 				{ // reconcile #7
+					// removes global keep and keepSince
 					name: "TestPrunerWithNilArguments",
 					applyChanges: func(tektonConfig *v1alpha1.TektonConfig, client *fake.Clientset, t *testing.T) func() {
 						tektonConfig.Spec.Pruner.Keep = nil
 						tektonConfig.Spec.Pruner.KeepSince = nil
 						return nil
 					},
+					// uses default keep value
 					scheduleAndArgs: map[string]string{
-						"*/12 * * * *": "ns-seven;--keep-since=42;pipelinerun,taskrun;true",
+						"*/5 * * * *":  "ns-one;--keep=100;pipelinerun,taskrun;false ns-two;--keep=100;pipelinerun,taskrun;false",
+						"*/12 * * * *": "ns-seven;--keep=100,--keep-since=42;pipelinerun,taskrun;true",
 					},
 				},
 				{ // reconcile #9
+					// removes global resources
 					name: "TestPrunerWithWithEmptyResources",
 					applyChanges: func(tektonConfig *v1alpha1.TektonConfig, client *fake.Clientset, t *testing.T) func() {
 						tektonConfig.Spec.Pruner.Resources = nil
 						return nil
 					},
-					scheduleAndArgs: map[string]string{},
+					// takes default resources
+					scheduleAndArgs: map[string]string{
+						"*/5 * * * *":  "ns-one;--keep=100;pipelinerun;false ns-two;--keep=100;pipelinerun;false",
+						"*/12 * * * *": "ns-seven;--keep=100,--keep-since=42;pipelinerun;true",
+					},
 				},
 				{ // reconcile #10
+					// adds global resources
 					name: "TestPrunerWithWithResources",
 					applyChanges: func(tektonConfig *v1alpha1.TektonConfig, client *fake.Clientset, t *testing.T) func() {
 						tektonConfig.Spec.Pruner.Resources = []string{"pipelinerun", "taskrun"}
 						return nil
 					},
 					scheduleAndArgs: map[string]string{
-						"*/12 * * * *": "ns-seven;--keep-since=42;pipelinerun,taskrun;true",
+						"*/5 * * * *":  "ns-one;--keep=100;pipelinerun,taskrun;false ns-two;--keep=100;pipelinerun,taskrun;false",
+						"*/12 * * * *": "ns-seven;--keep=100,--keep-since=42;pipelinerun,taskrun;true",
+					},
+				},
+				{ // reconcile #11
+					name: "TestPrunerDisableAll",
+					// disables pruner feature
+					applyChanges: func(tektonConfig *v1alpha1.TektonConfig, client *fake.Clientset, t *testing.T) func() {
+						tektonConfig.Spec.Pruner.Disabled = true
+						return nil
+					},
+					scheduleAndArgs: map[string]string{},
+				},
+				{ // reconcile #12
+					// re enables pruner feature
+					name: "TestPrunerReEnable",
+					applyChanges: func(tektonConfig *v1alpha1.TektonConfig, client *fake.Clientset, t *testing.T) func() {
+						tektonConfig.Spec.Pruner.Disabled = false
+						return nil
+					},
+					scheduleAndArgs: map[string]string{
+						"*/5 * * * *":  "ns-one;--keep=100;pipelinerun,taskrun;false ns-two;--keep=100;pipelinerun,taskrun;false",
+						"*/12 * * * *": "ns-seven;--keep=100,--keep-since=42;pipelinerun,taskrun;true",
 					},
 				},
 			},