Repository: tektoncd/operator
Pull request #1150 (2022-11-09 03:09:16)

[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 **nikhil-thomas** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @nikhil-thomas` 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":["nikhil-thomas"]} -->
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>

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

Approval requirements bypassed by manually added approval.

This pull-request has been approved by:

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

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
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":["nikhil-thomas"]} -->
tekton-robot: @github-actions[bot]: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-tekton-operator-integration-tests | b5badfcbf65dfcf76c424aa9a5938b8c3fb600ea | [link](https://prow.tekton.dev/view/gs/tekton-prow/pr-logs/pull/tektoncd_operator/1150/pull-tekton-operator-integration-tests/1590194068762136576) | true | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://prow.tekton.dev/pr-history?org=tektoncd&repo=operator&pr=1150). [Your PR dashboard](https://prow.tekton.dev/pr?query=is%3Apr%20state%3Aopen%20author%3Agithub-actions[bot]).

<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. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/components.yaml b/components.yaml
index 8695df4a6..6028a706f 100644
--- a/components.yaml
+++ b/components.yaml
@@ -1,6 +1,6 @@
 chains:
   github: tektoncd/chains
-  version: v0.12.0
+  version: v0.13.0
 dashboard:
   github: tektoncd/dashboard
   version: v0.30.0
@@ -12,7 +12,7 @@ pipeline:
   version: v0.41.0
 pipelines-as-code:
   github: openshift-pipelines/pipelines-as-code
-  version: v0.12.0
+  version: v0.13.0
 results:
   github: tektoncd/results
   version: v0.4.0
diff --git a/config/base/300-operator_v1alpha1_chain_crd.yaml b/config/base/300-operator_v1alpha1_chain_crd.yaml
index 6308212d6..8e5297fbf 100644
--- a/config/base/300-operator_v1alpha1_chain_crd.yaml
+++ b/config/base/300-operator_v1alpha1_chain_crd.yaml
@@ -41,7 +41,7 @@ spec:
     - jsonPath: .status.conditions[?(@.type=="Ready")].status
       name: Ready
       type: string
-    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].reason"
+    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].message"
       name: Reason
       type: string
     schema:
diff --git a/config/base/300-operator_v1alpha1_config_crd.yaml b/config/base/300-operator_v1alpha1_config_crd.yaml
index a9388e59a..e1a5823a2 100644
--- a/config/base/300-operator_v1alpha1_config_crd.yaml
+++ b/config/base/300-operator_v1alpha1_config_crd.yaml
@@ -41,7 +41,7 @@ spec:
     - jsonPath: .status.conditions[?(@.type=="Ready")].status
       name: Ready
       type: string
-    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].reason"
+    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].message"
       name: Reason
       type: string
     schema:
diff --git a/config/base/300-operator_v1alpha1_hub_crd.yaml b/config/base/300-operator_v1alpha1_hub_crd.yaml
index 7729ba8b3..e143cf3a0 100644
--- a/config/base/300-operator_v1alpha1_hub_crd.yaml
+++ b/config/base/300-operator_v1alpha1_hub_crd.yaml
@@ -41,7 +41,7 @@ spec:
         - jsonPath: .status.conditions[?(@.type=="Ready")].status
           name: Ready
           type: string
-        - jsonPath: '.status.conditions[?(@.type=="Ready")].reason'
+        - jsonPath: '.status.conditions[?(@.type=="Ready")].message'
           name: Reason
           type: string
         - jsonPath: .status.apiUrl
diff --git a/config/base/300-operator_v1alpha1_installer_set_crd.yaml b/config/base/300-operator_v1alpha1_installer_set_crd.yaml
index 0dd14f350..c9be91874 100644
--- a/config/base/300-operator_v1alpha1_installer_set_crd.yaml
+++ b/config/base/300-operator_v1alpha1_installer_set_crd.yaml
@@ -38,7 +38,7 @@ spec:
         - jsonPath: .status.conditions[?(@.type=="Ready")].status
           name: Ready
           type: string
-        - jsonPath: ".status.conditions[?(@.type==\"Ready\")].reason"
+        - jsonPath: ".status.conditions[?(@.type==\"Ready\")].message"
           name: Reason
           type: string
       schema:
diff --git a/config/base/300-operator_v1alpha1_pipeline_crd.yaml b/config/base/300-operator_v1alpha1_pipeline_crd.yaml
index f82d63233..8a029f7eb 100644
--- a/config/base/300-operator_v1alpha1_pipeline_crd.yaml
+++ b/config/base/300-operator_v1alpha1_pipeline_crd.yaml
@@ -41,7 +41,7 @@ spec:
     - jsonPath: .status.conditions[?(@.type=="Ready")].status
       name: Ready
       type: string
-    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].reason"
+    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].message"
       name: Reason
       type: string
     schema:
diff --git a/config/base/300-operator_v1alpha1_trigger_crd.yaml b/config/base/300-operator_v1alpha1_trigger_crd.yaml
index 73361619e..d5c49f595 100644
--- a/config/base/300-operator_v1alpha1_trigger_crd.yaml
+++ b/config/base/300-operator_v1alpha1_trigger_crd.yaml
@@ -41,7 +41,7 @@ spec:
       - jsonPath: .status.conditions[?(@.type=="Ready")].status
         name: Ready
         type: string
-      - jsonPath: ".status.conditions[?(@.type==\"Ready\")].reason"
+      - jsonPath: ".status.conditions[?(@.type==\"Ready\")].message"
         name: Reason
         type: string
     schema:
diff --git a/config/kubernetes/base/300-operator_v1alpha1_dashboard_crd.yaml b/config/kubernetes/base/300-operator_v1alpha1_dashboard_crd.yaml
index 3b224dd6b..0828e4f3b 100644
--- a/config/kubernetes/base/300-operator_v1alpha1_dashboard_crd.yaml
+++ b/config/kubernetes/base/300-operator_v1alpha1_dashboard_crd.yaml
@@ -41,7 +41,7 @@ spec:
     - jsonPath: .status.conditions[?(@.type=="Ready")].status
       name: Ready
       type: string
-    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].reason"
+    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].message"
       name: Reason
       type: string
     schema:
diff --git a/config/kubernetes/base/300-operator_v1alpha1_result_crd.yaml b/config/kubernetes/base/300-operator_v1alpha1_result_crd.yaml
index 859a8b9e6..67600701f 100644
--- a/config/kubernetes/base/300-operator_v1alpha1_result_crd.yaml
+++ b/config/kubernetes/base/300-operator_v1alpha1_result_crd.yaml
@@ -41,7 +41,7 @@ spec:
     - jsonPath: .status.conditions[?(@.type=="Ready")].status
       name: Ready
       type: string
-    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].reason"
+    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].message"
       name: Reason
       type: string
     schema:
diff --git a/config/openshift/base/300-operator_v1alpha1_addon_crd.yaml b/config/openshift/base/300-operator_v1alpha1_addon_crd.yaml
index 9309979be..b3bcbc7ae 100644
--- a/config/openshift/base/300-operator_v1alpha1_addon_crd.yaml
+++ b/config/openshift/base/300-operator_v1alpha1_addon_crd.yaml
@@ -41,7 +41,7 @@ spec:
     - jsonPath: .status.conditions[?(@.type=="Ready")].status
       name: Ready
       type: string
-    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].reason"
+    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].message"
       name: Reason
       type: string
     schema:
diff --git a/config/openshift/base/300-operator_v1alpha1_openshiftpipelinesascode_crd.yaml b/config/openshift/base/300-operator_v1alpha1_openshiftpipelinesascode_crd.yaml
index 741452d92..4be4d8909 100644
--- a/config/openshift/base/300-operator_v1alpha1_openshiftpipelinesascode_crd.yaml
+++ b/config/openshift/base/300-operator_v1alpha1_openshiftpipelinesascode_crd.yaml
@@ -44,7 +44,7 @@ spec:
     - jsonPath: .status.conditions[?(@.type=="Ready")].status
       name: Ready
       type: string
-    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].reason"
+    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].message"
       name: Reason
       type: string
     schema:
diff --git a/pkg/apis/operator/v1alpha1/tektonpipeline_defaults.go b/pkg/apis/operator/v1alpha1/tektonpipeline_defaults.go
index 919888119..093ea582a 100644
--- a/pkg/apis/operator/v1alpha1/tektonpipeline_defaults.go
+++ b/pkg/apis/operator/v1alpha1/tektonpipeline_defaults.go
@@ -80,6 +80,20 @@ func (p *Pipeline) setDefaults() {
 		p.MetricsTaskrunLevel = config.DefaultTaskrunLevel
 	}
 
+	// Resolvers
+	if p.EnableBundlesResolver == nil {
+		p.EnableBundlesResolver = ptr.Bool(true)
+	}
+	if p.EnableClusterResolver == nil {
+		p.EnableClusterResolver = ptr.Bool(true)
+	}
+	if p.EnableHubResolver == nil {
+		p.EnableHubResolver = ptr.Bool(true)
+	}
+	if p.EnableGitResolver == nil {
+		p.EnableGitResolver = ptr.Bool(true)
+	}
+
 	// run platform specific defaulting
 	if IsOpenShiftPlatform() {
 		p.openshiftDefaulting()
diff --git a/pkg/apis/operator/v1alpha1/tektonpipeline_types.go b/pkg/apis/operator/v1alpha1/tektonpipeline_types.go
index 125bf509b..8bc0cf3e6 100644
--- a/pkg/apis/operator/v1alpha1/tektonpipeline_types.go
+++ b/pkg/apis/operator/v1alpha1/tektonpipeline_types.go
@@ -101,6 +101,8 @@ type PipelineProperties struct {
 	PipelineMetricsProperties  `json:",inline"`
 	// +optional
 	OptionalPipelineProperties `json:",inline"`
+	// +optional
+	Resolvers `json:",inline"`
 }
 
 // OptionalPipelineProperties defines the fields which are to be
@@ -124,3 +126,20 @@ type PipelineMetricsProperties struct {
 	MetricsPipelinerunLevel        string `json:"metrics.pipelinerun.level,omitempty"`
 	MetricsPipelinerunDurationType string `json:"metrics.pipelinerun.duration-type,omitempty"`
 }
+
+// Resolvers defines the fields to configure resolvers
+type Resolvers struct {
+	EnableBundlesResolver *bool `json:"enable-bundles-resolver,omitempty"`
+	EnableHubResolver     *bool `json:"enable-hub-resolver,omitempty"`
+	EnableGitResolver     *bool `json:"enable-git-resolver,omitempty"`
+	EnableClusterResolver *bool `json:"enable-cluster-resolver,omitempty"`
+	ResolversConfig       `json:",inline"`
+}
+
+// ResolversConfig defines the fields to configure each of the resolver
+type ResolversConfig struct {
+	BundlesResolverConfig map[string]string `json:"bundles-resolver-config,omitempty"`
+	HubResolverConfig     map[string]string `json:"hub-resolver-config,omitempty"`
+	GitResolverConfig     map[string]string `json:"git-resolver-config,omitempty"`
+	ClusterResolverConfig map[string]string `json:"cluster-resolver-config,omitempty"`
+}
diff --git a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go
index c01836ed5..856bf6092 100644
--- a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go
@@ -495,6 +495,7 @@ func (in *PipelineProperties) DeepCopyInto(out *PipelineProperties) {
 	}
 	out.PipelineMetricsProperties = in.PipelineMetricsProperties
 	in.OptionalPipelineProperties.DeepCopyInto(&out.OptionalPipelineProperties)
+	in.Resolvers.DeepCopyInto(&out.Resolvers)
 	return
 }
 
@@ -577,6 +578,87 @@ func (in *Prune) DeepCopy() *Prune {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Resolvers) DeepCopyInto(out *Resolvers) {
+	*out = *in
+	if in.EnableBundlesResolver != nil {
+		in, out := &in.EnableBundlesResolver, &out.EnableBundlesResolver
+		*out = new(bool)
+		**out = **in
+	}
+	if in.EnableHubResolver != nil {
+		in, out := &in.EnableHubResolver, &out.EnableHubResolver
+		*out = new(bool)
+		**out = **in
+	}
+	if in.EnableGitResolver != nil {
+		in, out := &in.EnableGitResolver, &out.EnableGitResolver
+		*out = new(bool)
+		**out = **in
+	}
+	if in.EnableClusterResolver != nil {
+		in, out := &in.EnableClusterResolver, &out.EnableClusterResolver
+		*out = new(bool)
+		**out = **in
+	}
+	in.ResolversConfig.DeepCopyInto(&out.ResolversConfig)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resolvers.
+func (in *Resolvers) DeepCopy() *Resolvers {
+	if in == nil {
+		return nil
+	}
+	out := new(Resolvers)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ResolversConfig) DeepCopyInto(out *ResolversConfig) {
+	*out = *in
+	if in.BundlesResolverConfig != nil {
+		in, out := &in.BundlesResolverConfig, &out.BundlesResolverConfig
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.HubResolverConfig != nil {
+		in, out := &in.HubResolverConfig, &out.HubResolverConfig
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.GitResolverConfig != nil {
+		in, out := &in.GitResolverConfig, &out.GitResolverConfig
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.ClusterResolverConfig != nil {
+		in, out := &in.ClusterResolverConfig, &out.ClusterResolverConfig
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResolversConfig.
+func (in *ResolversConfig) DeepCopy() *ResolversConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(ResolversConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *TektonAddon) DeepCopyInto(out *TektonAddon) {
 	*out = *in
diff --git a/pkg/reconciler/common/transformers.go b/pkg/reconciler/common/transformers.go
index 529628f83..ea580601d 100644
--- a/pkg/reconciler/common/transformers.go
+++ b/pkg/reconciler/common/transformers.go
@@ -643,6 +643,51 @@ func AddDeploymentRestrictedPSA() mf.Transformer {
 	}
 }
 
+// AddStatefulSetRestrictedPSA will add the default restricted spec on StatefulSet to remove errors/warning
+func AddStatefulSetRestrictedPSA() mf.Transformer {
+	return func(u *unstructured.Unstructured) error {
+		if strings.ToLower(u.GetKind()) != "statefulset" {
+			return nil
+		}
+
+		s := &appsv1.StatefulSet{}
+		err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, s)
+		if err != nil {
+			return err
+		}
+
+		if s.Spec.Template.Spec.SecurityContext == nil {
+			s.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{}
+		}
+
+		if s.Spec.Template.Spec.SecurityContext.RunAsNonRoot == nil {
+			s.Spec.Template.Spec.SecurityContext.RunAsNonRoot = ptr.Bool(runAsNonRootValue)
+		}
+
+		if s.Spec.Template.Spec.SecurityContext.SeccompProfile == nil {
+			s.Spec.Template.Spec.SecurityContext.SeccompProfile = &corev1.SeccompProfile{
+				Type: corev1.SeccompProfileTypeRuntimeDefault,
+			}
+		}
+
+		for i := range s.Spec.Template.Spec.Containers {
+			c := &s.Spec.Template.Spec.Containers[i]
+			if c.SecurityContext == nil {
+				c.SecurityContext = &corev1.SecurityContext{}
+			}
+			c.SecurityContext.AllowPrivilegeEscalation = ptr.Bool(allowPrivilegedEscalationValue)
+			c.SecurityContext.Capabilities = &corev1.Capabilities{Drop: []corev1.Capability{"ALL"}}
+		}
+
+		unstrObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(s)
+		if err != nil {
+			return err
+		}
+		u.SetUnstructuredContent(unstrObj)
+		return nil
+	}
+}
+
 // AddJobRestrictedPSA will add the default restricted spec on Job to remove errors/warning
 func AddJobRestrictedPSA() mf.Transformer {
 	return func(u *unstructured.Unstructured) error {
@@ -690,3 +735,45 @@ func AddJobRestrictedPSA() mf.Transformer {
 		return nil
 	}
 }
+
+// CopyConfigMap will copy all the values from the passed configmap to the configmap
+// in the manifest, the fields which are in manifest configmap will only be copied
+// any extra field will be ignored
+func CopyConfigMap(configMapName string, expectedValues map[string]string) mf.Transformer {
+	return func(u *unstructured.Unstructured) error {
+		kind := strings.ToLower(u.GetKind())
+		if kind != "configmap" {
+			return nil
+		}
+		if u.GetName() != configMapName {
+			return nil
+		}
+
+		cm := &corev1.ConfigMap{}
+		err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, cm)
+		if err != nil {
+			return err
+		}
+		if cm.Data == nil {
+			// we don't add any field in the manifest configmap
+			// we will copy any value if defined by user
+			return nil
+		}
+
+		for key := range cm.Data {
+			// check if the key is defined in the expected map
+			value, ok := expectedValues[key]
+			if ok {
+				// if yes then copy the value
+				cm.Data[key] = value
+			}
+		}
+		unstrObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(cm)
+		if err != nil {
+			return err
+		}
+
+		u.SetUnstructuredContent(unstrObj)
+		return nil
+	}
+}
diff --git a/pkg/reconciler/kubernetes/tektonchain/tektonchain.go b/pkg/reconciler/kubernetes/tektonchain/tektonchain.go
index d5a8c63ca..4c9de4b1e 100644
--- a/pkg/reconciler/kubernetes/tektonchain/tektonchain.go
+++ b/pkg/reconciler/kubernetes/tektonchain/tektonchain.go
@@ -393,6 +393,7 @@ func (r *Reconciler) transform(ctx context.Context, manifest *mf.Manifest, comp
 		common.DeploymentImages(chainImages),
 		common.AddConfiguration(instance.Spec.Config),
 		common.AddConfigMapValues(ChainsConfig, instance.Spec.Chain),
+		common.AddDeploymentRestrictedPSA(),
 	}
 	extra = append(extra, r.extension.Transformers(instance)...)
 	return common.Transform(ctx, manifest, instance, extra...)
diff --git a/pkg/reconciler/kubernetes/tektonconfig/extension.go b/pkg/reconciler/kubernetes/tektonconfig/extension.go
index f6b1f759c..0a7361fdb 100644
--- a/pkg/reconciler/kubernetes/tektonconfig/extension.go
+++ b/pkg/reconciler/kubernetes/tektonconfig/extension.go
@@ -49,7 +49,7 @@ func (oe kubernetesExtension) PostReconcile(ctx context.Context, comp v1alpha1.T
 
 	if configInstance.Spec.Profile == v1alpha1.ProfileAll {
 		if _, err := extension.EnsureTektonDashboardExists(ctx, oe.operatorClientSet.OperatorV1alpha1().TektonDashboards(), configInstance); err != nil {
-			configInstance.Status.MarkComponentNotReady(fmt.Sprintf("TektonDashboard: %s", err.Error()))
+			configInstance.Status.MarkPostInstallFailed(fmt.Sprintf("TektonDashboard: %s", err.Error()))
 			return v1alpha1.REQUEUE_EVENT_AFTER
 		}
 	}
diff --git a/pkg/reconciler/kubernetes/tektondashboard/tektondashboard.go b/pkg/reconciler/kubernetes/tektondashboard/tektondashboard.go
index a7f253f05..24261ca95 100644
--- a/pkg/reconciler/kubernetes/tektondashboard/tektondashboard.go
+++ b/pkg/reconciler/kubernetes/tektondashboard/tektondashboard.go
@@ -112,10 +112,10 @@ func (r *Reconciler) FinalizeKind(ctx context.Context, original *v1alpha1.Tekton
 // ReconcileKind compares the actual state with the desired, and attempts to
 // converge the two.
 func (r *Reconciler) ReconcileKind(ctx context.Context, td *v1alpha1.TektonDashboard) pkgreconciler.Event {
-
 	logger := logging.FromContext(ctx)
 	td.Status.InitializeConditions()
 	td.Status.ObservedGeneration = td.Generation
+	td.Status.SetVersion(r.dashboardVersion)
 
 	logger.Infow("Reconciling TektonDashboards", "status", td.Status)
 
@@ -311,6 +311,7 @@ func (r *Reconciler) transform(ctx context.Context, manifest *mf.Manifest, comp
 		common.InjectOperandNameLabelOverwriteExisting(v1alpha1.OperandTektoncdDashboard),
 		common.ApplyProxySettings,
 		common.AddConfiguration(instance.Spec.Config),
+		common.AddDeploymentRestrictedPSA(),
 	}
 	extra = append(extra, r.extension.Transformers(instance)...)
 	return common.Transform(ctx, manifest, instance, extra...)
diff --git a/pkg/reconciler/kubernetes/tektoninstallerset/client/check.go b/pkg/reconciler/kubernetes/tektoninstallerset/client/check.go
index 56a25a657..a2b7ee364 100644
--- a/pkg/reconciler/kubernetes/tektoninstallerset/client/check.go
+++ b/pkg/reconciler/kubernetes/tektoninstallerset/client/check.go
@@ -69,10 +69,14 @@ func (i *InstallerSetClient) checkSet(ctx context.Context, comp v1alpha1.TektonC
 			logger.Errorf("%v/%v: found multiple sets, expected one", i.resourceKind, isType)
 			return iSets, ErrInvalidState
 		}
-	case InstallerTypeCustom:
-		// TODO
 	default:
-		return nil, fmt.Errorf("invalid installerSet type")
+		if !strings.HasPrefix(isType, InstallerTypeCustom) {
+			return nil, fmt.Errorf("invalid installerSet type")
+		}
+		if len(iSets) != 1 {
+			logger.Errorf("%v/%v: found multiple sets, expected one", i.resourceKind, isType)
+			return iSets, ErrInvalidState
+		}
 	}
 
 	if err := verifyMeta(i.resourceKind, isType, logger, iSets[0], comp, i.releaseVersion); err != nil {
diff --git a/pkg/reconciler/kubernetes/tektoninstallerset/client/cleanup.go b/pkg/reconciler/kubernetes/tektoninstallerset/client/cleanup.go
index 7c9c056d8..05d465109 100644
--- a/pkg/reconciler/kubernetes/tektoninstallerset/client/cleanup.go
+++ b/pkg/reconciler/kubernetes/tektoninstallerset/client/cleanup.go
@@ -21,8 +21,11 @@ import (
 	"fmt"
 	"strings"
 
+	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/apimachinery/pkg/selection"
 	"knative.dev/pkg/logging"
 )
 
@@ -80,6 +83,26 @@ func (i *InstallerSetClient) CleanupPostSet(ctx context.Context) error {
 	return i.cleanup(ctx, InstallerTypePost)
 }
 
+func (i *InstallerSetClient) CleanupCustomSet(ctx context.Context, customName string) error {
+	setType := InstallerTypeCustom + "-" + strings.ToLower(customName)
+	return i.cleanup(ctx, setType)
+}
+
+func (i *InstallerSetClient) CleanupAllCustomSet(ctx context.Context) error {
+	labelSelector := labels.NewSelector()
+	createdReq, _ := labels.NewRequirement(v1alpha1.CreatedByKey, selection.Equals, []string{i.resourceKind})
+	if createdReq != nil {
+		labelSelector = labelSelector.Add(*createdReq)
+	}
+	err := i.clientSet.DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{
+		LabelSelector: labelSelector.String(),
+	})
+	if err != nil {
+		return fmt.Errorf("failed to delete %s custom sets: %v", i.resourceKind, err)
+	}
+	return nil
+}
+
 func (i *InstallerSetClient) cleanup(ctx context.Context, isType string) error {
 	logger := logging.FromContext(ctx).With("kind", i.resourceKind, "type", isType)
 
diff --git a/pkg/reconciler/kubernetes/tektoninstallerset/client/create.go b/pkg/reconciler/kubernetes/tektoninstallerset/client/create.go
index beb4b616d..7f59d9ad5 100644
--- a/pkg/reconciler/kubernetes/tektoninstallerset/client/create.go
+++ b/pkg/reconciler/kubernetes/tektoninstallerset/client/create.go
@@ -33,38 +33,28 @@ import (
 func (i *InstallerSetClient) create(ctx context.Context, comp v1alpha1.TektonComponent, manifest *mf.Manifest, filterAndTransform FilterAndTransform, isType string) ([]v1alpha1.TektonInstallerSet, error) {
 	logger := logging.FromContext(ctx).With("kind", i.resourceKind, "type", isType)
 
-	switch isType {
-	case InstallerTypeMain:
+	if isType == InstallerTypeMain {
 		sets, err := i.makeMainSets(ctx, comp, manifest, filterAndTransform)
 		if err != nil {
 			logger.Errorf("installer set creation failed for main type: %v", err)
 			return sets, err
 		}
 		return sets, nil
+	}
 
-	case InstallerTypePre, InstallerTypePost:
-		kind := strings.ToLower(strings.TrimPrefix(i.resourceKind, "Tekton"))
-		isName := fmt.Sprintf("%s-%s-", kind, isType)
-
-		iS, err := i.makeInstallerSet(ctx, comp, manifest, filterAndTransform, isName, isType)
-		if err != nil {
-			return nil, err
-		}
-
-		iS, err = i.clientSet.Create(ctx, iS, metav1.CreateOptions{})
-		if err != nil {
-			return nil, err
-		}
-		return []v1alpha1.TektonInstallerSet{*iS}, nil
-
-	case InstallerTypeCustom:
-	// TODO
+	kind := strings.ToLower(strings.TrimPrefix(i.resourceKind, "Tekton"))
+	isName := fmt.Sprintf("%s-%s-", kind, isType)
 
-	default:
-		return nil, fmt.Errorf("invalid installer set type")
+	iS, err := i.makeInstallerSet(ctx, comp, manifest, filterAndTransform, isName, isType)
+	if err != nil {
+		return nil, err
 	}
 
-	return nil, nil
+	iS, err = i.clientSet.Create(ctx, iS, metav1.CreateOptions{})
+	if err != nil {
+		return nil, err
+	}
+	return []v1alpha1.TektonInstallerSet{*iS}, nil
 }
 
 func (i *InstallerSetClient) makeMainSets(ctx context.Context, comp v1alpha1.TektonComponent, manifest *mf.Manifest, filterAndTransform FilterAndTransform) ([]v1alpha1.TektonInstallerSet, error) {
@@ -100,6 +90,25 @@ func (i *InstallerSetClient) makeMainSets(ctx context.Context, comp v1alpha1.Tek
 	return []v1alpha1.TektonInstallerSet{*staticIS, *deploymentIS}, nil
 }
 
+func (i *InstallerSetClient) waitForStatus(ctx context.Context, set *v1alpha1.TektonInstallerSet) error {
+	for cnt := 0; cnt < 3; cnt++ {
+		onClusterSet, err := i.clientSet.Get(ctx, set.GetName(), metav1.GetOptions{})
+		if err != nil {
+			return err
+		}
+		// once status is initialised for static set we can create deployment set
+		ready := onClusterSet.Status.GetCondition(apis.ConditionReady)
+		if ready != nil {
+			return nil
+		}
+		// if status is not initialised then wait
+		time.Sleep(3 * time.Second)
+	}
+	// if still the status is not initialised then create the next set and let it fail
+	// there may be something else wrong
+	return nil
+}
+
 func (i *InstallerSetClient) makeInstallerSet(ctx context.Context, comp v1alpha1.TektonComponent, manifest *mf.Manifest, filterAndTransform FilterAndTransform, isName, isType string) (*v1alpha1.TektonInstallerSet, error) {
 	specHash, err := hash.Compute(comp.GetSpec())
 	if err != nil {
@@ -131,22 +140,3 @@ func (i *InstallerSetClient) makeInstallerSet(ctx context.Context, comp v1alpha1
 		},
 	}, nil
 }
-
-func (i *InstallerSetClient) waitForStatus(ctx context.Context, set *v1alpha1.TektonInstallerSet) error {
-	for cnt := 0; cnt < 3; cnt++ {
-		onClusterSet, err := i.clientSet.Get(ctx, set.GetName(), metav1.GetOptions{})
-		if err != nil {
-			return err
-		}
-		// once status is initialised for static set we can create deployment set
-		ready := onClusterSet.Status.GetCondition(apis.ConditionReady)
-		if ready != nil {
-			return nil
-		}
-		// if status is not initialised then wait
-		time.Sleep(3 * time.Second)
-	}
-	// if still the status is not initialised then create the next set and let it fail
-	// there may be something else wrong
-	return nil
-}
diff --git a/pkg/reconciler/kubernetes/tektoninstallerset/client/custom_versioned_clustertask.go b/pkg/reconciler/kubernetes/tektoninstallerset/client/custom_versioned_clustertask.go
new file mode 100644
index 000000000..d4553f23e
--- /dev/null
+++ b/pkg/reconciler/kubernetes/tektoninstallerset/client/custom_versioned_clustertask.go
@@ -0,0 +1,84 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    hcompp://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package client
+
+import (
+	"context"
+	"strings"
+
+	mf "github.com/manifestival/manifestival"
+	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	"github.com/tektoncd/operator/pkg/reconciler/common"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"knative.dev/pkg/logging"
+)
+
+var (
+	versionedClusterTaskInstallerSet = "VersionedClusterTask"
+)
+
+// VersionedClusterTaskSet this is an exception case where we create one installer set for one minor version
+// not for patch version and we don't remove older installer sets on upgrade, hence keeping it different
+// from custom set otherwise code becomes unnecessarily complex to handle this case
+func (i *InstallerSetClient) VersionedClusterTaskSet(ctx context.Context, comp v1alpha1.TektonComponent, customName string, manifest *mf.Manifest, filterAndTransform FilterAndTransform) error {
+	logger := logging.FromContext(ctx)
+
+	setType := InstallerTypeCustom + "-" + strings.ToLower(versionedClusterTaskInstallerSet)
+	versionedClusterTaskLS := v1.LabelSelector{
+		MatchLabels: map[string]string{
+			v1alpha1.InstallerSetType:       setType,
+			v1alpha1.ReleaseMinorVersionKey: getPatchVersionTrimmed(i.releaseVersion),
+		},
+	}
+	versionedClusterTaskLabelSelector, err := common.LabelSelector(versionedClusterTaskLS)
+	if err != nil {
+		return err
+	}
+	is, err := i.clientSet.List(ctx, v1.ListOptions{LabelSelector: versionedClusterTaskLabelSelector})
+	if err != nil {
+		return err
+	}
+
+	if len(is.Items) == 0 {
+		vctSet, err := i.makeInstallerSet(ctx, comp, manifest, filterAndTransform, "addon-versioned-clustertasks", setType)
+		if err != nil {
+			return err
+		}
+		vctSet.Labels[v1alpha1.ReleaseMinorVersionKey] = getPatchVersionTrimmed(i.releaseVersion)
+		vctSet.GenerateName = "addon-versioned-clustertasks" + "-" + getPatchVersionTrimmed(i.releaseVersion) + "-"
+
+		_, err = i.clientSet.Create(ctx, vctSet, metav1.CreateOptions{})
+		if err != nil {
+			return err
+		}
+		return v1alpha1.REQUEUE_EVENT_AFTER
+	}
+
+	if err := i.statusCheck(logger, setType, is.Items); err != nil {
+		return err
+	}
+	return nil
+}
+
+func getPatchVersionTrimmed(version string) string {
+	endIndex := strings.LastIndex(version, ".")
+	if endIndex != -1 {
+		version = version[:endIndex]
+	}
+	return version
+}
diff --git a/pkg/reconciler/kubernetes/tektoninstallerset/client/obsolete_sets.go b/pkg/reconciler/kubernetes/tektoninstallerset/client/obsolete_sets.go
index 6e374c15c..70c505bc2 100644
--- a/pkg/reconciler/kubernetes/tektoninstallerset/client/obsolete_sets.go
+++ b/pkg/reconciler/kubernetes/tektoninstallerset/client/obsolete_sets.go
@@ -31,6 +31,9 @@ func (i *InstallerSetClient) RemoveObsoleteSets(ctx context.Context) error {
 		sets = []string{"pipeline", "PrePipeline", "PostPipeline"}
 	} else if i.resourceKind == v1alpha1.KindTektonTrigger {
 		sets = []string{"trigger"}
+	} else if i.resourceKind == v1alpha1.KindTektonAddon {
+		// not adding VersionedClusterTask here, as we keep versioned clustertasks on upgrade
+		sets = []string{"ClusterTask", "CommunityClusterTask", "PipelinesTemplate", "TriggersResources", "ConsoleCLI", "MiscellaneousResources", "PipelinesAsCode"}
 	}
 	labelSelector := labels.NewSelector()
 	createdReq, _ := labels.NewRequirement(v1alpha1.CreatedByKey, selection.Equals, []string{i.resourceKind})
diff --git a/pkg/reconciler/kubernetes/tektoninstallerset/client/pre_post_custom_set.go b/pkg/reconciler/kubernetes/tektoninstallerset/client/pre_post_custom_set.go
index 4baff046f..25e13c877 100644
--- a/pkg/reconciler/kubernetes/tektoninstallerset/client/pre_post_custom_set.go
+++ b/pkg/reconciler/kubernetes/tektoninstallerset/client/pre_post_custom_set.go
@@ -18,18 +18,24 @@ package client
 
 import (
 	"context"
+	"strings"
 
 	mf "github.com/manifestival/manifestival"
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
 	"knative.dev/pkg/logging"
 )
 
+func (i *InstallerSetClient) PostSet(ctx context.Context, comp v1alpha1.TektonComponent, manifest *mf.Manifest, filterAndTransform FilterAndTransform) error {
+	return i.createSet(ctx, comp, InstallerTypePost, manifest, filterAndTransform)
+}
+
 func (i *InstallerSetClient) PreSet(ctx context.Context, comp v1alpha1.TektonComponent, manifest *mf.Manifest, filterAndTransform FilterAndTransform) error {
 	return i.createSet(ctx, comp, InstallerTypePre, manifest, filterAndTransform)
 }
 
-func (i *InstallerSetClient) PostSet(ctx context.Context, comp v1alpha1.TektonComponent, manifest *mf.Manifest, filterAndTransform FilterAndTransform) error {
-	return i.createSet(ctx, comp, InstallerTypePost, manifest, filterAndTransform)
+func (i *InstallerSetClient) CustomSet(ctx context.Context, comp v1alpha1.TektonComponent, customName string, manifest *mf.Manifest, filterAndTransform FilterAndTransform) error {
+	setType := InstallerTypeCustom + "-" + strings.ToLower(customName)
+	return i.createSet(ctx, comp, setType, manifest, filterAndTransform)
 }
 
 func (i *InstallerSetClient) createSet(ctx context.Context, comp v1alpha1.TektonComponent, setType string, manifest *mf.Manifest, filterAndTransform FilterAndTransform) error {
diff --git a/pkg/reconciler/kubernetes/tektonpipeline/transform.go b/pkg/reconciler/kubernetes/tektonpipeline/transform.go
index 89c23be20..8e65c1ce4 100644
--- a/pkg/reconciler/kubernetes/tektonpipeline/transform.go
+++ b/pkg/reconciler/kubernetes/tektonpipeline/transform.go
@@ -27,9 +27,14 @@ import (
 
 const (
 	// Pipelines ConfigMap
-	FeatureFlag    = "feature-flags"
-	ConfigDefaults = "config-defaults"
-	ConfigMetrics  = "config-observability"
+	FeatureFlag           = "feature-flags"
+	ConfigDefaults        = "config-defaults"
+	ConfigMetrics         = "config-observability"
+	ResolverFeatureFlag   = "resolvers-feature-flags"
+	bundleResolverConfig  = "bundleresolver-config"
+	clusterResolverConfig = "cluster-resolver-config"
+	hubResolverConfig     = "hubresolver-config"
+	gitResolverConfig     = "git-resolver-config"
 )
 
 func filterAndTransform(extension common.Extension) client.FilterAndTransform {
@@ -47,10 +52,15 @@ func filterAndTransform(extension common.Extension) client.FilterAndTransform {
 			common.AddConfigMapValues(FeatureFlag, pipeline.Spec.PipelineProperties),
 			common.AddConfigMapValues(ConfigDefaults, pipeline.Spec.OptionalPipelineProperties),
 			common.AddConfigMapValues(ConfigMetrics, pipeline.Spec.PipelineMetricsProperties),
+			common.AddConfigMapValues(ResolverFeatureFlag, pipeline.Spec.Resolvers),
 			common.ApplyProxySettings,
 			common.DeploymentImages(images),
 			common.InjectLabelOnNamespace(proxyLabel),
 			common.AddConfiguration(pipeline.Spec.Config),
+			common.CopyConfigMap(bundleResolverConfig, pipeline.Spec.BundlesResolverConfig),
+			common.CopyConfigMap(hubResolverConfig, pipeline.Spec.HubResolverConfig),
+			common.CopyConfigMap(clusterResolverConfig, pipeline.Spec.ClusterResolverConfig),
+			common.CopyConfigMap(gitResolverConfig, pipeline.Spec.GitResolverConfig),
 		}
 		trns = append(trns, extra...)
 
diff --git a/pkg/reconciler/kubernetes/tektonresult/tektonresult.go b/pkg/reconciler/kubernetes/tektonresult/tektonresult.go
index 8f72f5af6..3be345609 100644
--- a/pkg/reconciler/kubernetes/tektonresult/tektonresult.go
+++ b/pkg/reconciler/kubernetes/tektonresult/tektonresult.go
@@ -311,6 +311,8 @@ func (r *Reconciler) transform(ctx context.Context, manifest *mf.Manifest, comp
 		common.ApplyProxySettings,
 		common.ReplaceNamespaceInDeploymentArgs(targetNs),
 		common.ReplaceNamespaceInDeploymentEnv(targetNs),
+		common.AddDeploymentRestrictedPSA(),
+		common.AddStatefulSetRestrictedPSA(),
 	}
 	extra = append(extra, r.extension.Transformers(instance)...)
 	return common.Transform(ctx, manifest, instance, extra...)
diff --git a/pkg/reconciler/openshift/tektonaddon/clustertTask.go b/pkg/reconciler/openshift/tektonaddon/clustertTask.go
index a9d80413b..4cef22521 100644
--- a/pkg/reconciler/openshift/tektonaddon/clustertTask.go
+++ b/pkg/reconciler/openshift/tektonaddon/clustertTask.go
@@ -23,73 +23,34 @@ import (
 
 	mf "github.com/manifestival/manifestival"
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
-	"github.com/tektoncd/operator/pkg/reconciler/common"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client"
 )
 
-var clusterTaskLS = metav1.LabelSelector{
-	MatchLabels: map[string]string{
-		v1alpha1.InstallerSetType: ClusterTaskInstallerSet,
-	},
-}
-
 func (r *Reconciler) EnsureClusterTask(ctx context.Context, enable string, ta *v1alpha1.TektonAddon) error {
-
-	clusterTaskLabelSelector, err := common.LabelSelector(clusterTaskLS)
-	if err != nil {
-		return err
-	}
-
 	if enable == "true" {
-
-		exist, _, err := checkIfInstallerSetExist(ctx, r.operatorClientSet, r.operatorVersion, clusterTaskLabelSelector)
-		if err != nil {
+		if err := r.installerSetClient.CustomSet(ctx, ta, ClusterTaskInstallerSet, r.clusterTaskManifest, filterAndTransformClusterTask()); err != nil {
 			return err
 		}
-
-		if !exist {
-			msg := fmt.Sprintf("%s being created/upgraded", ClusterTaskInstallerSet)
-			ta.Status.MarkInstallerSetNotReady(msg)
-			return r.ensureClusterTasks(ctx, ta)
-		}
-
-		if err := r.checkComponentStatus(ctx, clusterTaskLabelSelector); err != nil {
-			ta.Status.MarkInstallerSetNotReady(err.Error())
-			return nil
-		}
-
 	} else {
-		// if disabled then delete the installer Set if exist
-		if err := r.deleteInstallerSet(ctx, clusterTaskLabelSelector); err != nil {
+		if err := r.installerSetClient.CleanupCustomSet(ctx, ClusterTaskInstallerSet); err != nil {
 			return err
 		}
 	}
-
 	return nil
 }
 
-// installerset for non versioned clustertask like buildah and community clustertask
-func (r *Reconciler) ensureClusterTasks(ctx context.Context, ta *v1alpha1.TektonAddon) error {
-	clusterTaskManifest := mf.Manifest{}
-	// Read clusterTasks from ko data
-	if err := applyAddons(&clusterTaskManifest, "02-clustertasks"); err != nil {
-		return err
-	}
-	// Run transformers
-	tfs := []mf.Transformer{
-		replaceKind(KindTask, KindClusterTask),
-		injectLabel(labelProviderType, providerTypeRedHat, overwrite, "ClusterTask"),
-	}
-	if err := r.addonTransform(ctx, &clusterTaskManifest, ta, tfs...); err != nil {
-		return err
-	}
-
-	if err := createInstallerSet(ctx, r.operatorClientSet, ta, clusterTaskManifest,
-		r.operatorVersion, ClusterTaskInstallerSet, "addon-clustertasks"); err != nil {
-		return err
+func filterAndTransformClusterTask() client.FilterAndTransform {
+	return func(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent) (*mf.Manifest, error) {
+		addon := comp.(*v1alpha1.TektonAddon)
+		tfs := []mf.Transformer{
+			replaceKind(KindTask, KindClusterTask),
+			injectLabel(labelProviderType, providerTypeRedHat, overwrite, "ClusterTask"),
+		}
+		if err := transformers(ctx, manifest, addon, tfs...); err != nil {
+			return nil, err
+		}
+		return manifest, nil
 	}
-
-	return nil
 }
 
 func formattedVersionMajorMinorX(version, x string) string {
@@ -98,11 +59,6 @@ func formattedVersionMajorMinorX(version, x string) string {
 	return formattedVersionSnake(ver)
 }
 
-func formattedVersionMajorMinor(version string) string {
-	ver := getPatchVersionTrimmed(version)
-	return formattedVersionSnake(ver)
-}
-
 func formattedVersionSnake(version string) string {
 	ver := strings.TrimPrefix(version, "v")
 	return strings.Replace(ver, ".", "-", -1)
diff --git a/pkg/reconciler/openshift/tektonaddon/clustertTaskVersioned.go b/pkg/reconciler/openshift/tektonaddon/clustertTaskVersioned.go
index b04883d86..c7e204efb 100644
--- a/pkg/reconciler/openshift/tektonaddon/clustertTaskVersioned.go
+++ b/pkg/reconciler/openshift/tektonaddon/clustertTaskVersioned.go
@@ -18,89 +18,36 @@ package tektonaddon
 
 import (
 	"context"
-	"fmt"
 
 	mf "github.com/manifestival/manifestival"
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
-	"github.com/tektoncd/operator/pkg/reconciler/common"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client"
 )
 
 func (r *Reconciler) EnsureVersionedClusterTask(ctx context.Context, enable string, ta *v1alpha1.TektonAddon) error {
-
-	versionedClusterTaskLS := metav1.LabelSelector{
-		MatchLabels: map[string]string{
-			v1alpha1.InstallerSetType:       VersionedClusterTaskInstallerSet,
-			v1alpha1.ReleaseMinorVersionKey: getPatchVersionTrimmed(r.operatorVersion),
-		},
-	}
-
-	versionedClusterTaskLabelSelector, err := common.LabelSelector(versionedClusterTaskLS)
-	if err != nil {
-		return err
-	}
-
 	if enable == "true" {
-
-		// here pass two labels one for type and other for minor release version to remove the previous minor release installerset only not all
-		exist, _, err := checkIfInstallerSetExist(ctx, r.operatorClientSet, r.operatorVersion, versionedClusterTaskLabelSelector)
-		if err != nil {
-			return err
-		}
-
-		if !exist {
-			msg := fmt.Sprintf("%s being created/upgraded", VersionedClusterTaskInstallerSet)
-			ta.Status.MarkInstallerSetNotReady(msg)
-			return r.ensureVersionedClusterTasks(ctx, ta)
-		}
-
-		// here pass two labels one for type and other for operator release version to get the latest installerset of current version
-		vClusterTaskLS := metav1.LabelSelector{
-			MatchLabels: map[string]string{
-				v1alpha1.InstallerSetType:  VersionedClusterTaskInstallerSet,
-				v1alpha1.ReleaseVersionKey: r.operatorVersion,
-			},
-		}
-		vClusterTaskLabelSelector, err := common.LabelSelector(vClusterTaskLS)
-		if err != nil {
+		if err := r.installerSetClient.VersionedClusterTaskSet(ctx, ta, VersionedClusterTaskInstallerSet, r.clusterTaskManifest, filterAndTransformVersionedClusterTask(r.operatorVersion)); err != nil {
 			return err
 		}
-		if err := r.checkComponentStatus(ctx, vClusterTaskLabelSelector); err != nil {
-			ta.Status.MarkInstallerSetNotReady(err.Error())
-			return nil
-		}
-
 	} else {
-		// if disabled then delete the installer Set if exist
-		if err := r.deleteInstallerSet(ctx, versionedClusterTaskLabelSelector); err != nil {
+		if err := r.installerSetClient.CleanupCustomSet(ctx, VersionedClusterTaskInstallerSet); err != nil {
 			return err
 		}
 	}
-
 	return nil
 }
 
-// installerset for versioned clustertask like buildah-1-6-0
-func (r *Reconciler) ensureVersionedClusterTasks(ctx context.Context, ta *v1alpha1.TektonAddon) error {
-	clusterTaskManifest := mf.Manifest{}
-	// Read clusterTasks from ko data
-	if err := applyAddons(&clusterTaskManifest, "02-clustertasks"); err != nil {
-		return err
-	}
-	// Run transformers
-	tfs := []mf.Transformer{
-		replaceKind(KindTask, KindClusterTask),
-		injectLabel(labelProviderType, providerTypeRedHat, overwrite, "ClusterTask"),
-		setVersionedNames(r.operatorVersion),
-	}
-	if err := r.addonTransform(ctx, &clusterTaskManifest, ta, tfs...); err != nil {
-		return err
-	}
-
-	if err := createInstallerSet(ctx, r.operatorClientSet, ta, clusterTaskManifest,
-		r.operatorVersion, VersionedClusterTaskInstallerSet, "addon-versioned-clustertasks"); err != nil {
-		return err
+func filterAndTransformVersionedClusterTask(version string) client.FilterAndTransform {
+	return func(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent) (*mf.Manifest, error) {
+		addon := comp.(*v1alpha1.TektonAddon)
+		tfs := []mf.Transformer{
+			replaceKind(KindTask, KindClusterTask),
+			injectLabel(labelProviderType, providerTypeRedHat, overwrite, "ClusterTask"),
+			setVersionedNames(version),
+		}
+		if err := transformers(ctx, manifest, addon, tfs...); err != nil {
+			return nil, err
+		}
+		return manifest, nil
 	}
-
-	return nil
 }
diff --git a/pkg/reconciler/openshift/tektonaddon/communityClusterTasks.go b/pkg/reconciler/openshift/tektonaddon/communityClusterTasks.go
index bd63df24a..2d22f4bf4 100644
--- a/pkg/reconciler/openshift/tektonaddon/communityClusterTasks.go
+++ b/pkg/reconciler/openshift/tektonaddon/communityClusterTasks.go
@@ -18,30 +18,12 @@ package tektonaddon
 
 import (
 	"context"
-	"fmt"
 	"strings"
-	"time"
 
 	mf "github.com/manifestival/manifestival"
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
 	"github.com/tektoncd/operator/pkg/reconciler/common"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"knative.dev/pkg/logging"
-)
-
-var communityClusterTaskLS = metav1.LabelSelector{
-	MatchLabels: map[string]string{
-		v1alpha1.InstallerSetType: CommunityClusterTaskInstallerSet,
-	},
-}
-
-// retryWaitTime holds value until the pod lives.
-// ones the pod restart resets the value back to ""
-// this is useful if the pod is not restarted and community task urls are not reachable
-// we see comparable less forbidden events
-var (
-	layout        = "2006-01-02 15:04:05"
-	retryWaitTime = ""
+	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client"
 )
 
 var communityResourceURLs = []string{
@@ -56,73 +38,39 @@ var communityResourceURLs = []string{
 }
 
 func (r *Reconciler) EnsureCommunityClusterTask(ctx context.Context, enable string, ta *v1alpha1.TektonAddon) error {
-
-	communityClusterTaskLabelSelector, err := common.LabelSelector(communityClusterTaskLS)
-	if err != nil {
-		return err
+	if len(r.communityClusterTaskManifest.Resources()) == 0 {
+		return nil
 	}
-
 	if enable == "true" {
-
-		exist, _, err := checkIfInstallerSetExist(ctx, r.operatorClientSet, r.operatorVersion, communityClusterTaskLabelSelector)
-		if err != nil {
+		if err := r.installerSetClient.CustomSet(ctx, ta, CommunityClusterTaskInstallerSet, r.communityClusterTaskManifest, filterAndTransformCommunityClusterTask()); err != nil {
 			return err
 		}
-
-		if !exist {
-			msg := fmt.Sprintf("%s being created/upgraded", CommunityClusterTaskInstallerSet)
-			ta.Status.MarkInstallerSetNotReady(msg)
-			return r.ensureCommunityClusterTasks(ctx, ta)
-		}
-
-		if err := r.checkComponentStatus(ctx, communityClusterTaskLabelSelector); err != nil {
-			ta.Status.MarkInstallerSetNotReady(err.Error())
-			return nil
-		}
-
 	} else {
-		// if disabled then delete the installer Set if exist
-		if err := r.deleteInstallerSet(ctx, communityClusterTaskLabelSelector); err != nil {
+		if err := r.installerSetClient.CleanupCustomSet(ctx, CommunityClusterTaskInstallerSet); err != nil {
 			return err
 		}
 	}
-
 	return nil
 }
 
-// installerset for communityclustertask
-func (r *Reconciler) ensureCommunityClusterTasks(ctx context.Context, ta *v1alpha1.TektonAddon) error {
-
-	if SkipCommunityTaskFetch(retryWaitTime) {
-		return nil
-	}
-
-	communityClusterTaskManifest := mf.Manifest{}
-	if err := r.appendCommunityTarget(ctx, &communityClusterTaskManifest, ta); err != nil {
-		retryWaitTime = time.Now().Add(15 * time.Minute).Format(layout)
-
-		// Continue if failed to resolve community task URL.
-		// (Ex: on disconnected cluster community tasks won't be reachable because of proxy).
-		logging.FromContext(ctx).Error("Failed to get community task: Skipping community tasks installation  ", err)
-		return v1alpha1.REQUEUE_EVENT_AFTER
-	}
-
-	if err := r.communityTransform(ctx, &communityClusterTaskManifest, ta); err != nil {
-		return err
-	}
-
-	communityClusterTaskManifest = communityClusterTaskManifest.Append(communityClusterTaskManifest)
+func filterAndTransformCommunityClusterTask() client.FilterAndTransform {
+	return func(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent) (*mf.Manifest, error) {
+		instance := comp.(*v1alpha1.TektonAddon)
+		addonImages := common.ToLowerCaseKeys(common.ImagesFromEnv(common.AddonsImagePrefix))
 
-	if err := createInstallerSet(ctx, r.operatorClientSet, ta, communityClusterTaskManifest, r.operatorVersion, CommunityClusterTaskInstallerSet, "addon-communityclustertasks"); err != nil {
-		return err
+		extra := []mf.Transformer{
+			replaceKind("Task", "ClusterTask"),
+			injectLabel(labelProviderType, providerTypeCommunity, overwrite, "ClusterTask"),
+			common.TaskImages(addonImages),
+		}
+		if err := common.Transform(ctx, manifest, instance, extra...); err != nil {
+			return nil, err
+		}
+		return manifest, nil
 	}
-
-	return nil
 }
 
-// appendCommunityTarget mutates the passed manifest by appending one
-// appropriate for the passed TektonComponent
-func (r *Reconciler) appendCommunityTarget(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent) error {
+func appendCommunityTasks(manifest *mf.Manifest) error {
 	urls := strings.Join(communityResourceURLs, ",")
 	m, err := mf.ManifestFrom(mf.Path(urls))
 	if err != nil {
@@ -132,31 +80,9 @@ func (r *Reconciler) appendCommunityTarget(ctx context.Context, manifest *mf.Man
 	return nil
 }
 
-// communityTransform mutates the passed manifest to one with common component
-// and platform transformations applied
-func (r *Reconciler) communityTransform(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent) error {
-	instance := comp.(*v1alpha1.TektonAddon)
-	extra := []mf.Transformer{
-		replaceKind("Task", "ClusterTask"),
-		injectLabel(labelProviderType, providerTypeCommunity, overwrite, "ClusterTask"),
-	}
-	extra = append(extra, r.extension.Transformers(instance)...)
-	return common.Transform(ctx, manifest, instance, extra...)
-}
-
-// SkipCommunityTaskFetch skips community task fetch until retryWaitTime has passed
-// if there is no value int retryWaitTime that means no error occurred prior to the call
-// if there is some value that means error has occurred earlier and must try after 15 minutes
-func SkipCommunityTaskFetch(until string) bool {
-	skip := false
-	if until != "" {
-		t, err := time.Parse(layout, until)
-		if err != nil {
-			return false
-		}
-		if t.After(time.Now()) {
-			skip = true
-		}
+func fetchCommunityTasks(manifest *mf.Manifest) error {
+	if err := appendCommunityTasks(manifest); err != nil {
+		return err
 	}
-	return skip
+	return nil
 }
diff --git a/pkg/reconciler/openshift/tektonaddon/consolecli.go b/pkg/reconciler/openshift/tektonaddon/consolecli.go
new file mode 100644
index 000000000..31e6e4650
--- /dev/null
+++ b/pkg/reconciler/openshift/tektonaddon/consolecli.go
@@ -0,0 +1,87 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package tektonaddon
+
+import (
+	"context"
+	"fmt"
+
+	mf "github.com/manifestival/manifestival"
+	routev1 "github.com/openshift/api/route/v1"
+	"github.com/openshift/client-go/route/clientset/versioned/scheme"
+	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	"github.com/tektoncd/operator/pkg/reconciler/common"
+	"knative.dev/pkg/logging"
+)
+
+func (r *Reconciler) EnsureConsoleCLI(ctx context.Context, ta *v1alpha1.TektonAddon) error {
+	tknservecliManifest := r.openShiftConsoleManifest
+	if err := common.Transform(ctx, tknservecliManifest, ta); err != nil {
+		return err
+	}
+	routeHost, err := getRouteHost(tknservecliManifest)
+	if err != nil {
+		return err
+	}
+	if err := consoleCLITransform(ctx, r.consoleCLIManifest, routeHost); err != nil {
+		return err
+	}
+	if err := r.installerSetClient.CustomSet(ctx, ta, ConsoleCLIInstallerSet, r.consoleCLIManifest, filterAndTransformOCPResources()); err != nil {
+		return err
+	}
+	return nil
+}
+
+func getRouteHost(manifest *mf.Manifest) (string, error) {
+	var hostUrl string
+	for _, r := range manifest.Filter(mf.ByKind("Route")).Resources() {
+		u, err := manifest.Client.Get(&r)
+		if err != nil {
+			return "", err
+		}
+		if u.GetName() == "tkn-cli-serve" {
+			route := &routev1.Route{}
+			if err := scheme.Scheme.Convert(u, route, nil); err != nil {
+				return "", err
+			}
+			hostUrl = route.Spec.Host
+		}
+	}
+	return hostUrl, nil
+}
+
+func consoleCLITransform(ctx context.Context, manifest *mf.Manifest, baseURL string) error {
+	tknVersion := "0.24.0"
+
+	if baseURL == "" {
+		return fmt.Errorf("route url should not be empty")
+	}
+	logger := logging.FromContext(ctx)
+	logger.Debug("Transforming manifest")
+
+	transformers := []mf.Transformer{
+		replaceURLCCD(baseURL, tknVersion),
+	}
+
+	transformManifest, err := manifest.Transform(transformers...)
+	if err != nil {
+		return err
+	}
+
+	*manifest = transformManifest
+	return nil
+}
diff --git a/pkg/reconciler/openshift/tektonaddon/const.go b/pkg/reconciler/openshift/tektonaddon/const.go
index 2fbe97f13..07717caa3 100644
--- a/pkg/reconciler/openshift/tektonaddon/const.go
+++ b/pkg/reconciler/openshift/tektonaddon/const.go
@@ -18,6 +18,7 @@ package tektonaddon
 
 const (
 	ClusterTaskInstallerSet            = "ClusterTask"
+	OpenShiftConsoleInstallerSet       = "OpenShiftConsole"
 	CommunityClusterTaskInstallerSet   = "CommunityClusterTask"
 	VersionedClusterTaskInstallerSet   = "VersionedClusterTask"
 	versionedClusterTaskPatchChar      = "0"
diff --git a/pkg/reconciler/openshift/tektonaddon/controller.go b/pkg/reconciler/openshift/tektonaddon/controller.go
index cc04b5420..0e88ecf83 100644
--- a/pkg/reconciler/openshift/tektonaddon/controller.go
+++ b/pkg/reconciler/openshift/tektonaddon/controller.go
@@ -31,6 +31,7 @@ import (
 	tektonTriggerinformer "github.com/tektoncd/operator/pkg/client/injection/informers/operator/v1alpha1/tektontrigger"
 	tektonAddonreconciler "github.com/tektoncd/operator/pkg/client/injection/reconciler/operator/v1alpha1/tektonaddon"
 	"github.com/tektoncd/operator/pkg/reconciler/common"
+	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client"
 	"go.uber.org/zap"
 	"k8s.io/client-go/tools/cache"
 	"knative.dev/pkg/configmap"
@@ -46,7 +47,7 @@ const (
 // NewController initializes the controller and is called by the generated code
 // Registers eventhandlers to enqueue events
 func NewController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
-	return NewExtendedController(OpenShiftExtension)(ctx, cmw)
+	return NewExtendedController(common.NoExtension)(ctx, cmw)
 }
 
 // NewExtendedController returns a controller extended to a specific platform
@@ -69,13 +70,60 @@ func NewExtendedController(generator common.ExtensionGenerator) injection.Contro
 			logger.Fatal("Failed to find version from env")
 		}
 
+		tisClient := operatorclient.Get(ctx).OperatorV1alpha1().TektonInstallerSets()
+		metrics, _ := NewRecorder()
+
+		clusterTaskManifest := &mf.Manifest{}
+		if err := applyAddons(clusterTaskManifest, "02-clustertasks"); err != nil {
+			logger.Fatalf("failed to read clustertask from kodata: %v", err)
+		}
+
+		communityClusterTaskManifest := &mf.Manifest{}
+		if err := fetchCommunityTasks(communityClusterTaskManifest); err != nil {
+			// if unable to fetch community task, don't fail
+			logger.Errorf("failed to read community task: %v", err)
+		}
+
+		triggersResourcesManifest := &mf.Manifest{}
+		if err := applyAddons(triggersResourcesManifest, "01-clustertriggerbindings"); err != nil {
+			logger.Fatalf("failed to read trigger Resources from kodata: %v", err)
+		}
+
+		pipelineTemplateManifest := &mf.Manifest{}
+		if err := applyAddons(pipelineTemplateManifest, "03-pipelines"); err != nil {
+			logger.Fatalf("failed to read pipeline template from kodata: %v", err)
+		}
+		if err := addPipelineTemplates(pipelineTemplateManifest); err != nil {
+			logger.Fatalf("failed to add pipeline templates: %v", err)
+		}
+
+		openShiftConsoleManifest := &mf.Manifest{Client: mfclient}
+		if err := applyAddons(openShiftConsoleManifest, "05-tkncliserve"); err != nil {
+			logger.Fatalf("failed to read openshift console resources from kodata: %v", err)
+		}
+		if err := getOptionalAddons(openShiftConsoleManifest); err != nil {
+			logger.Fatalf("failed to read optional addon resources from kodata: %v", err)
+		}
+
+		consoleCLIManifest := &mf.Manifest{}
+		if err := applyAddons(consoleCLIManifest, "04-consolecli"); err != nil {
+			logger.Fatalf("failed to read console cli from kodata: %v", err)
+		}
+
 		c := &Reconciler{
-			operatorClientSet: operatorclient.Get(ctx),
-			extension:         generator(ctx),
-			pipelineInformer:  tektonPipelineinformer.Get(ctx),
-			triggerInformer:   tektonTriggerinformer.Get(ctx),
-			manifest:          manifest,
-			operatorVersion:   version,
+			installerSetClient:           client.NewInstallerSetClient(tisClient, version, "addon", v1alpha1.KindTektonAddon, metrics),
+			operatorClientSet:            operatorclient.Get(ctx),
+			extension:                    generator(ctx),
+			pipelineInformer:             tektonPipelineinformer.Get(ctx),
+			triggerInformer:              tektonTriggerinformer.Get(ctx),
+			manifest:                     manifest,
+			operatorVersion:              version,
+			clusterTaskManifest:          clusterTaskManifest,
+			triggersResourcesManifest:    triggersResourcesManifest,
+			pipelineTemplateManifest:     pipelineTemplateManifest,
+			communityClusterTaskManifest: communityClusterTaskManifest,
+			openShiftConsoleManifest:     openShiftConsoleManifest,
+			consoleCLIManifest:           consoleCLIManifest,
 		}
 		impl := tektonAddonreconciler.NewImpl(ctx, c)
 
diff --git a/pkg/reconciler/openshift/tektonaddon/extension.go b/pkg/reconciler/openshift/tektonaddon/extension.go
deleted file mode 100644
index bdc38215d..000000000
--- a/pkg/reconciler/openshift/tektonaddon/extension.go
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
-Copyright 2020 The Tekton Authors
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package tektonaddon
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"path/filepath"
-
-	"github.com/go-logr/zapr"
-	mfc "github.com/manifestival/client-go-client"
-	mf "github.com/manifestival/manifestival"
-	routev1 "github.com/openshift/api/route/v1"
-	"github.com/openshift/client-go/route/clientset/versioned/scheme"
-	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
-	"github.com/tektoncd/operator/pkg/client/clientset/versioned"
-	operatorclient "github.com/tektoncd/operator/pkg/client/injection/client"
-	"github.com/tektoncd/operator/pkg/reconciler/common"
-	"github.com/tektoncd/operator/pkg/reconciler/shared/hash"
-	"go.uber.org/zap"
-	corev1 "k8s.io/api/core/v1"
-	apierrors "k8s.io/apimachinery/pkg/api/errors"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"knative.dev/pkg/apis"
-	"knative.dev/pkg/injection"
-	"knative.dev/pkg/logging"
-)
-
-func OpenShiftExtension(ctx context.Context) common.Extension {
-	logger := logging.FromContext(ctx)
-
-	mfclient, err := mfc.NewClient(injection.GetConfig(ctx))
-	if err != nil {
-		logger.Fatalw("error creating client from injected config", zap.Error(err))
-	}
-	mflogger := zapr.NewLogger(logger.Named("manifestival").Desugar())
-	manifest, err := mf.ManifestFrom(mf.Slice{}, mf.UseClient(mfclient), mf.UseLogger(mflogger))
-	if err != nil {
-		logger.Fatalw("error creating initial manifest", zap.Error(err))
-	}
-
-	version := os.Getenv(versionKey)
-	if version == "" {
-		logger.Fatal("Failed to find version from env")
-	}
-
-	ext := openshiftExtension{
-		operatorClientSet: operatorclient.Get(ctx),
-		manifest:          manifest,
-		version:           version,
-	}
-	return ext
-}
-
-type openshiftExtension struct {
-	operatorClientSet versioned.Interface
-	manifest          mf.Manifest
-	version           string
-}
-
-func (oe openshiftExtension) Transformers(comp v1alpha1.TektonComponent) []mf.Transformer {
-	addonImages := common.ToLowerCaseKeys(common.ImagesFromEnv(common.AddonsImagePrefix))
-	return []mf.Transformer{
-		common.TaskImages(addonImages),
-	}
-}
-func (oe openshiftExtension) PreReconcile(context.Context, v1alpha1.TektonComponent) error {
-	return nil
-}
-func (oe openshiftExtension) PostReconcile(ctx context.Context, comp v1alpha1.TektonComponent) error {
-	logger := logging.FromContext(ctx)
-	addon := comp.(*v1alpha1.TektonAddon)
-
-	miscellaneousLS := metav1.LabelSelector{
-		MatchLabels: map[string]string{
-			v1alpha1.InstallerSetType: MiscellaneousResourcesInstallerSet,
-		},
-	}
-	miscellaneousLabelSelector, err := common.LabelSelector(miscellaneousLS)
-	if err != nil {
-		return err
-	}
-	exist, _, err := checkIfInstallerSetExist(ctx, oe.operatorClientSet, oe.version, miscellaneousLabelSelector)
-	if err != nil {
-		return err
-	}
-	if !exist {
-		manifest, err := getMiscellaneousManifest(ctx, addon, oe.manifest, comp)
-		if err != nil {
-			return err
-		}
-
-		if err := createInstallerSet(ctx, oe.operatorClientSet, addon, manifest, oe.version,
-			MiscellaneousResourcesInstallerSet, "addon-openshift"); err != nil {
-			return err
-		}
-		return v1alpha1.RECONCILE_AGAIN_ERR
-	}
-
-	// Check if installer set is already created
-	installedTIS, err := oe.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
-		List(ctx, metav1.ListOptions{
-			LabelSelector: miscellaneousLabelSelector,
-		})
-	if err != nil {
-		if apierrors.IsNotFound(err) {
-			manifest, err := getMiscellaneousManifest(ctx, addon, oe.manifest, comp)
-			if err != nil {
-				return err
-			}
-
-			if err := createInstallerSet(ctx, oe.operatorClientSet, addon, manifest, oe.version,
-				MiscellaneousResourcesInstallerSet, "addon-openshift"); err != nil {
-				return err
-			}
-			return v1alpha1.RECONCILE_AGAIN_ERR
-		}
-		logger.Error("failed to get InstallerSet: %s", err)
-		return err
-	}
-
-	expectedSpecHash, err := hash.Compute(addon.Spec)
-	if err != nil {
-		return err
-	}
-
-	// spec hash stored on installerSet
-	lastAppliedHash := installedTIS.Items[0].GetAnnotations()[v1alpha1.LastAppliedHashKey]
-
-	if lastAppliedHash != expectedSpecHash {
-
-		manifest, err := getMiscellaneousManifest(ctx, addon, oe.manifest, comp)
-		if err != nil {
-			return err
-		}
-
-		// Update the spec hash
-		current := installedTIS.Items[0].GetAnnotations()
-		current[v1alpha1.LastAppliedHashKey] = expectedSpecHash
-		installedTIS.Items[0].SetAnnotations(current)
-
-		// Update the manifests
-		installedTIS.Items[0].Spec.Manifests = manifest.Resources()
-
-		if _, err = oe.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
-			Update(ctx, &installedTIS.Items[0], metav1.UpdateOptions{}); err != nil {
-			return err
-		}
-
-		return v1alpha1.RECONCILE_AGAIN_ERR
-	}
-
-	installedAddonIS, err := oe.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
-		List(ctx, metav1.ListOptions{
-			LabelSelector: miscellaneousLabelSelector,
-		})
-	if err != nil {
-		logger.Error("failed to get InstallerSet: %s", err)
-		return err
-	}
-
-	ready := installedAddonIS.Items[0].Status.GetCondition(apis.ConditionReady)
-	if ready == nil {
-		return v1alpha1.RECONCILE_AGAIN_ERR
-	}
-
-	if ready.Status != corev1.ConditionTrue {
-		return v1alpha1.RECONCILE_AGAIN_ERR
-	}
-
-	consolecliManifest := oe.manifest
-
-	consoleCLILS := metav1.LabelSelector{
-		MatchLabels: map[string]string{
-			v1alpha1.InstallerSetType: ConsoleCLIInstallerSet,
-		},
-	}
-	consoleCLILabelSelector, err := common.LabelSelector(consoleCLILS)
-	if err != nil {
-		return err
-	}
-	exist, _, err = checkIfInstallerSetExist(ctx, oe.operatorClientSet, oe.version, consoleCLILabelSelector)
-	if err != nil {
-		return err
-	}
-	if !exist {
-		tknservecliManifest := oe.manifest
-		if err := applyAddons(&tknservecliManifest, "05-tkncliserve"); err != nil {
-			return err
-		}
-		if err := addonTransform(ctx, &tknservecliManifest, addon); err != nil {
-			return err
-		}
-
-		routeHost, err := getRouteHost(&tknservecliManifest)
-		if err != nil {
-			return err
-		}
-
-		if err := applyAddons(&consolecliManifest, "04-consolecli"); err != nil {
-			return err
-		}
-
-		if err := consoleCLITransform(ctx, &consolecliManifest, routeHost); err != nil {
-			return err
-		}
-
-		if err := createInstallerSet(ctx, oe.operatorClientSet, addon, consolecliManifest, oe.version,
-			ConsoleCLIInstallerSet, "addon-consolecli"); err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-func (oe openshiftExtension) Finalize(context.Context, v1alpha1.TektonComponent) error {
-	return nil
-}
-
-func getOptionalAddons(manifest *mf.Manifest, comp v1alpha1.TektonComponent) error {
-	koDataDir := os.Getenv(common.KoEnvKey)
-
-	optionalLocation := filepath.Join(koDataDir, "tekton-addon", "optional", "samples")
-	if err := common.AppendManifest(manifest, optionalLocation); err != nil {
-		return err
-	}
-
-	optionalLocation = filepath.Join(koDataDir, "tekton-addon", "optional", "quickstarts")
-	return common.AppendManifest(manifest, optionalLocation)
-}
-
-func addonTransform(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent, extra ...mf.Transformer) error {
-	return common.Transform(ctx, manifest, comp, extra...)
-}
-
-func consoleCLITransform(ctx context.Context, manifest *mf.Manifest, baseURL string) error {
-	tknVersion := "0.24.0"
-
-	if baseURL == "" {
-		return fmt.Errorf("route url should not be empty")
-	}
-	logger := logging.FromContext(ctx)
-	logger.Debug("Transforming manifest")
-
-	transformers := []mf.Transformer{
-		replaceURLCCD(baseURL, tknVersion),
-	}
-
-	transformManifest, err := manifest.Transform(transformers...)
-	if err != nil {
-		return err
-	}
-
-	*manifest = transformManifest
-	return nil
-}
-
-func getRouteHost(manifest *mf.Manifest) (string, error) {
-	var hostUrl string
-	for _, r := range manifest.Filter(mf.ByKind("Route")).Resources() {
-		u, err := manifest.Client.Get(&r)
-		if err != nil {
-			return "", err
-		}
-		if u.GetName() == "tkn-cli-serve" {
-			route := &routev1.Route{}
-			if err := scheme.Scheme.Convert(u, route, nil); err != nil {
-				return "", err
-			}
-			hostUrl = route.Spec.Host
-		}
-	}
-	return hostUrl, nil
-}
-
-func getMiscellaneousManifest(ctx context.Context, addon *v1alpha1.TektonAddon, miscellaneousManifest mf.Manifest, comp v1alpha1.TektonComponent) (mf.Manifest, error) {
-	if err := applyAddons(&miscellaneousManifest, "05-tkncliserve"); err != nil {
-		return mf.Manifest{}, err
-	}
-
-	if err := getOptionalAddons(&miscellaneousManifest, comp); err != nil {
-		return mf.Manifest{}, err
-	}
-
-	images := common.ToLowerCaseKeys(common.ImagesFromEnv(common.AddonsImagePrefix))
-	extraTranformers := []mf.Transformer{
-		common.DeploymentImages(images),
-		common.AddConfiguration(addon.Spec.Config),
-	}
-	if err := addonTransform(ctx, &miscellaneousManifest, addon, extraTranformers...); err != nil {
-		return mf.Manifest{}, err
-	}
-	return miscellaneousManifest, nil
-}
diff --git a/pkg/reconciler/openshift/tektonaddon/installerset.go b/pkg/reconciler/openshift/tektonaddon/installerset.go
deleted file mode 100644
index c02fe6f23..000000000
--- a/pkg/reconciler/openshift/tektonaddon/installerset.go
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
-Copyright 2022 The Tekton Authors
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package tektonaddon
-
-import (
-	"context"
-	"fmt"
-
-	mf "github.com/manifestival/manifestival"
-	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
-	clientset "github.com/tektoncd/operator/pkg/client/clientset/versioned"
-	"github.com/tektoncd/operator/pkg/reconciler/shared/hash"
-	corev1 "k8s.io/api/core/v1"
-	"k8s.io/apimachinery/pkg/api/errors"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"knative.dev/pkg/apis"
-)
-
-// checkIfInstallerSetExist checks if installer set exists for a component and return true/false based on it
-// and if installer set which already exist is of older version then it deletes and return false to create a new
-// installer set
-func checkIfInstallerSetExist(ctx context.Context, oc clientset.Interface, relVersion string,
-	labelSelector string) (bool, *v1alpha1.TektonInstallerSet, error) {
-
-	installerSets, err := oc.OperatorV1alpha1().TektonInstallerSets().
-		List(ctx, metav1.ListOptions{
-			LabelSelector: labelSelector,
-		})
-	if err != nil {
-		return false, nil, err
-	}
-
-	if len(installerSets.Items) == 0 {
-		return false, nil, nil
-	}
-
-	if len(installerSets.Items) == 1 {
-		// if already created then check which version it is
-		version, ok := installerSets.Items[0].Labels[v1alpha1.ReleaseVersionKey]
-		if ok && version == relVersion {
-			// if installer set already exist and release version is same
-			// then ignore and move on
-			return true, &installerSets.Items[0], nil
-		}
-	}
-
-	// release version doesn't exist or is different from expected
-	// deleted existing InstallerSet and create a new one
-	// or there is more than one installerset (unexpected)
-	if err = oc.OperatorV1alpha1().TektonInstallerSets().
-		DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{
-			LabelSelector: labelSelector,
-		}); err != nil {
-		return false, nil, err
-	}
-
-	return false, nil, v1alpha1.RECONCILE_AGAIN_ERR
-}
-
-func createInstallerSet(ctx context.Context, oc clientset.Interface, ta *v1alpha1.TektonAddon,
-	manifest mf.Manifest, releaseVersion, component, installerSetPrefix string) error {
-
-	specHash, err := hash.Compute(ta.Spec)
-	if err != nil {
-		return err
-	}
-
-	is := makeInstallerSet(ta, manifest, installerSetPrefix, releaseVersion, component, specHash)
-
-	if _, err := oc.OperatorV1alpha1().TektonInstallerSets().
-		Create(ctx, is, metav1.CreateOptions{}); err != nil {
-		return err
-	}
-
-	return v1alpha1.RECONCILE_AGAIN_ERR
-}
-
-func makeInstallerSet(ta *v1alpha1.TektonAddon, manifest mf.Manifest, prefix, releaseVersion, component, specHash string) *v1alpha1.TektonInstallerSet {
-	ownerRef := *metav1.NewControllerRef(ta, ta.GetGroupVersionKind())
-	labels := map[string]string{
-		v1alpha1.CreatedByKey:      CreatedByValue,
-		v1alpha1.InstallerSetType:  component,
-		v1alpha1.ReleaseVersionKey: releaseVersion,
-	}
-	namePrefix := fmt.Sprintf("%s-", prefix)
-	// special label to make sure no two versioned clustertask installerset exist
-	// for all patch releases
-	if component == VersionedClusterTaskInstallerSet {
-		labels[v1alpha1.ReleaseMinorVersionKey] = getPatchVersionTrimmed(releaseVersion)
-		namePrefix = fmt.Sprintf("%s%s-", namePrefix, formattedVersionMajorMinor(releaseVersion))
-	}
-	return &v1alpha1.TektonInstallerSet{
-		ObjectMeta: metav1.ObjectMeta{
-			GenerateName: namePrefix,
-			Labels:       labels,
-			Annotations: map[string]string{
-				v1alpha1.TargetNamespaceKey: ta.Spec.TargetNamespace,
-				v1alpha1.LastAppliedHashKey: specHash,
-			},
-			OwnerReferences: []metav1.OwnerReference{ownerRef},
-		},
-		Spec: v1alpha1.TektonInstallerSetSpec{
-			Manifests: manifest.Resources(),
-		},
-	}
-}
-
-func (r *Reconciler) checkComponentStatus(ctx context.Context, labelSelector string) error {
-
-	// Check if installer set is already created
-	installerSets, err := r.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
-		List(ctx, metav1.ListOptions{
-			LabelSelector: labelSelector,
-		})
-
-	if err != nil {
-		if errors.IsNotFound(err) {
-			return nil
-		}
-		return err
-	}
-
-	// To make sure there won't be duplicate installersets.
-	if len(installerSets.Items) == 1 {
-		ready := installerSets.Items[0].Status.GetCondition(apis.ConditionReady)
-		if ready == nil || ready.Status == corev1.ConditionUnknown {
-			return fmt.Errorf("InstallerSet %s: waiting for installation", installerSets.Items[0].Name)
-		} else if ready.Status == corev1.ConditionFalse {
-			return fmt.Errorf("InstallerSet %s: ", ready.Message)
-		}
-	}
-	return nil
-}
-
-func (r *Reconciler) deleteInstallerSet(ctx context.Context, labelSelector string) error {
-
-	err := r.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
-		DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{
-			LabelSelector: labelSelector,
-		})
-	if err != nil && !errors.IsNotFound(err) {
-		return err
-	}
-
-	return nil
-}
diff --git a/pkg/reconciler/openshift/tektonaddon/pipelinesascode.go b/pkg/reconciler/openshift/tektonaddon/metrics.go
similarity index 50%
rename from pkg/reconciler/openshift/tektonaddon/pipelinesascode.go
rename to pkg/reconciler/openshift/tektonaddon/metrics.go
index 339b9d2ab..9ba1c2fff 100644
--- a/pkg/reconciler/openshift/tektonaddon/pipelinesascode.go
+++ b/pkg/reconciler/openshift/tektonaddon/metrics.go
@@ -16,27 +16,15 @@ limitations under the License.
 
 package tektonaddon
 
-import (
-	"context"
-
-	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
-	"github.com/tektoncd/operator/pkg/reconciler/common"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-)
-
-var pacLS = metav1.LabelSelector{
-	MatchLabels: map[string]string{
-		v1alpha1.InstallerSetType: PACInstallerSet,
-	},
+import "go.uber.org/zap"
+
+type Recorder struct {
+}
+
+func NewRecorder() (*Recorder, error) {
+	return &Recorder{}, nil
 }
 
-func (r *Reconciler) CleanupPipelinesAsCode(ctx context.Context, ta *v1alpha1.TektonAddon) error {
-	pacLabelSelector, err := common.LabelSelector(pacLS)
-	if err != nil {
-		return err
-	}
-	if err := r.deleteInstallerSet(ctx, pacLabelSelector); err != nil {
-		return err
-	}
-	return nil
+func (m *Recorder) LogMetrics(status, version string, logger *zap.SugaredLogger) {
+	// TODO
 }
diff --git a/pkg/reconciler/openshift/tektonaddon/openshiftConsole.go b/pkg/reconciler/openshift/tektonaddon/openshiftConsole.go
new file mode 100644
index 000000000..f7a1171ca
--- /dev/null
+++ b/pkg/reconciler/openshift/tektonaddon/openshiftConsole.go
@@ -0,0 +1,62 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package tektonaddon
+
+import (
+	"context"
+	"os"
+	"path/filepath"
+
+	mf "github.com/manifestival/manifestival"
+	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	"github.com/tektoncd/operator/pkg/reconciler/common"
+	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client"
+)
+
+func (r *Reconciler) EnsureOpenShiftConsoleResources(ctx context.Context, ta *v1alpha1.TektonAddon) error {
+	if err := r.installerSetClient.CustomSet(ctx, ta, OpenShiftConsoleInstallerSet, r.openShiftConsoleManifest, filterAndTransformOCPResources()); err != nil {
+		return err
+	}
+	return nil
+}
+
+func filterAndTransformOCPResources() client.FilterAndTransform {
+	return func(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent) (*mf.Manifest, error) {
+		addon := comp.(*v1alpha1.TektonAddon)
+		images := common.ToLowerCaseKeys(common.ImagesFromEnv(common.AddonsImagePrefix))
+		tfs := []mf.Transformer{
+			common.DeploymentImages(images),
+			common.AddConfiguration(addon.Spec.Config),
+		}
+		if err := transformers(ctx, manifest, addon, tfs...); err != nil {
+			return nil, err
+		}
+		return manifest, nil
+	}
+}
+
+func getOptionalAddons(manifest *mf.Manifest) error {
+	koDataDir := os.Getenv(common.KoEnvKey)
+
+	optionalLocation := filepath.Join(koDataDir, "tekton-addon", "optional", "samples")
+	if err := common.AppendManifest(manifest, optionalLocation); err != nil {
+		return err
+	}
+
+	optionalLocation = filepath.Join(koDataDir, "tekton-addon", "optional", "quickstarts")
+	return common.AppendManifest(manifest, optionalLocation)
+}
diff --git a/pkg/reconciler/openshift/tektonaddon/pipelinetemplate.go b/pkg/reconciler/openshift/tektonaddon/pipelinetemplate.go
index 2d5f0e23a..3ed26e07b 100644
--- a/pkg/reconciler/openshift/tektonaddon/pipelinetemplate.go
+++ b/pkg/reconciler/openshift/tektonaddon/pipelinetemplate.go
@@ -18,7 +18,6 @@ package tektonaddon
 
 import (
 	"context"
-	"fmt"
 	"os"
 	"path/filepath"
 
@@ -26,71 +25,18 @@ import (
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
 	"github.com/tektoncd/operator/pkg/reconciler/common"
 	tektonaddon "github.com/tektoncd/operator/pkg/reconciler/openshift/tektonaddon/pipelinetemplates"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-var pipelineTemplateLS = metav1.LabelSelector{
-	MatchLabels: map[string]string{
-		v1alpha1.InstallerSetType: PipelinesTemplateInstallerSet,
-	},
-}
-
 func (r *Reconciler) EnsurePipelineTemplates(ctx context.Context, enable string, ta *v1alpha1.TektonAddon) error {
-
-	pipelineTemplateLSLabelSelector, err := common.LabelSelector(pipelineTemplateLS)
-	if err != nil {
-		return err
-	}
 	if enable == "true" {
-
-		exist, _, err := checkIfInstallerSetExist(ctx, r.operatorClientSet, r.operatorVersion, pipelineTemplateLSLabelSelector)
-		if err != nil {
+		if err := r.installerSetClient.CustomSet(ctx, ta, PipelinesTemplateInstallerSet, r.pipelineTemplateManifest, filterAndTransformCommon()); err != nil {
 			return err
 		}
-		if !exist {
-			msg := fmt.Sprintf("%s being created/upgraded", PipelinesTemplateInstallerSet)
-			ta.Status.MarkInstallerSetNotReady(msg)
-			return r.ensurePipelineTemplates(ctx, ta)
-		}
-
-		if err := r.checkComponentStatus(ctx, pipelineTemplateLSLabelSelector); err != nil {
-			ta.Status.MarkInstallerSetNotReady(err.Error())
-			return nil
-		}
-
 	} else {
-		// if disabled then delete the installer Set if exist
-		if err := r.deleteInstallerSet(ctx, pipelineTemplateLSLabelSelector); err != nil {
+		if err := r.installerSetClient.CleanupCustomSet(ctx, PipelinesTemplateInstallerSet); err != nil {
 			return err
 		}
 	}
-
-	return nil
-}
-
-func (r *Reconciler) ensurePipelineTemplates(ctx context.Context, ta *v1alpha1.TektonAddon) error {
-	pipelineTemplateManifest := mf.Manifest{}
-
-	// Read pipeline template manifest from kodata
-	if err := applyAddons(&pipelineTemplateManifest, "03-pipelines"); err != nil {
-		return err
-	}
-
-	// generate pipeline templates
-	if err := addPipelineTemplates(&pipelineTemplateManifest); err != nil {
-		return err
-	}
-
-	// Run transformers
-	if err := r.addonTransform(ctx, &pipelineTemplateManifest, ta); err != nil {
-		return err
-	}
-
-	if err := createInstallerSet(ctx, r.operatorClientSet, ta, pipelineTemplateManifest, r.operatorVersion,
-		PipelinesTemplateInstallerSet, "addon-pipelines"); err != nil {
-		return err
-	}
-
 	return nil
 }
 
diff --git a/pkg/reconciler/openshift/tektonaddon/tektonaddon.go b/pkg/reconciler/openshift/tektonaddon/tektonaddon.go
index 24a9eaa79..d7eb50239 100644
--- a/pkg/reconciler/openshift/tektonaddon/tektonaddon.go
+++ b/pkg/reconciler/openshift/tektonaddon/tektonaddon.go
@@ -30,23 +30,27 @@ import (
 	informer "github.com/tektoncd/operator/pkg/client/informers/externalversions/operator/v1alpha1"
 	tektonaddonreconciler "github.com/tektoncd/operator/pkg/client/injection/reconciler/operator/v1alpha1/tektonaddon"
 	"github.com/tektoncd/operator/pkg/reconciler/common"
-	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset"
-	"github.com/tektoncd/operator/pkg/reconciler/openshift"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client"
 	"knative.dev/pkg/logging"
 	pkgreconciler "knative.dev/pkg/reconciler"
 )
 
 // Reconciler implements controller.Reconciler for TektonAddon resources.
 type Reconciler struct {
-	manifest          mf.Manifest
-	operatorClientSet clientset.Interface
-	extension         common.Extension
-
-	pipelineInformer informer.TektonPipelineInformer
-	triggerInformer  informer.TektonTriggerInformer
-
-	operatorVersion string
+	// installer Set client to do CRUD operations for components
+	installerSetClient           *client.InstallerSetClient
+	manifest                     mf.Manifest
+	operatorClientSet            clientset.Interface
+	extension                    common.Extension
+	pipelineInformer             informer.TektonPipelineInformer
+	triggerInformer              informer.TektonTriggerInformer
+	operatorVersion              string
+	clusterTaskManifest          *mf.Manifest
+	triggersResourcesManifest    *mf.Manifest
+	pipelineTemplateManifest     *mf.Manifest
+	communityClusterTaskManifest *mf.Manifest
+	openShiftConsoleManifest     *mf.Manifest
+	consoleCLIManifest           *mf.Manifest
 }
 
 const (
@@ -62,32 +66,13 @@ const (
 var _ tektonaddonreconciler.Interface = (*Reconciler)(nil)
 var _ tektonaddonreconciler.Finalizer = (*Reconciler)(nil)
 
-var ls = metav1.LabelSelector{
-	MatchLabels: map[string]string{
-		v1alpha1.CreatedByKey: CreatedByValue,
-	},
-}
-
 // FinalizeKind removes all resources after deletion of a TektonTriggers.
 func (r *Reconciler) FinalizeKind(ctx context.Context, original *v1alpha1.TektonAddon) pkgreconciler.Event {
 	logger := logging.FromContext(ctx)
-
-	labelSelector, err := common.LabelSelector(ls)
-	if err != nil {
+	if err := r.installerSetClient.CleanupAllCustomSet(ctx); err != nil {
+		logger.Errorf("failed to cleanup custom set: %v", err)
 		return err
 	}
-	if err := r.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
-		DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{
-			LabelSelector: labelSelector,
-		}); err != nil {
-		logger.Error("Failed to delete installer set created by TektonAddon", err)
-		return err
-	}
-
-	if err := r.extension.Finalize(ctx, original); err != nil {
-		logger.Error("Failed to finalize platform resources", err)
-	}
-
 	return nil
 }
 
@@ -96,6 +81,7 @@ func (r *Reconciler) FinalizeKind(ctx context.Context, original *v1alpha1.Tekton
 func (r *Reconciler) ReconcileKind(ctx context.Context, ta *v1alpha1.TektonAddon) pkgreconciler.Event {
 	logger := logging.FromContext(ctx)
 	ta.Status.InitializeConditions()
+	ta.Status.SetVersion(r.operatorVersion)
 
 	if ta.GetName() != v1alpha1.AddonResourceName {
 		msg := fmt.Sprintf("Resource ignored, Expected Name: %s, Got Name: %s",
@@ -110,16 +96,11 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, ta *v1alpha1.TektonAddon
 	// Pass the object through defaulting
 	ta.SetDefaults(ctx)
 
-	// Mark TektonAddon Instance as Not Ready if an upgrade is needed
-	if err := r.markUpgrade(ctx, ta); err != nil {
-		return err
-	}
-
 	// Make sure TektonPipeline & TektonTrigger is installed before proceeding with
 	// TektonAddons
 
 	if _, err := common.PipelineReady(r.pipelineInformer); err != nil {
-		if err.Error() == common.PipelineNotReady {
+		if err.Error() == common.PipelineNotReady || err == v1alpha1.DEPENDENCY_UPGRADE_PENDING_ERR {
 			ta.Status.MarkDependencyInstalling("tekton-pipelines is still installing")
 			// wait for pipeline status to change
 			return v1alpha1.REQUEUE_EVENT_AFTER
@@ -130,7 +111,7 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, ta *v1alpha1.TektonAddon
 	}
 
 	if _, err := common.TriggerReady(r.triggerInformer); err != nil {
-		if err.Error() == common.TriggerNotReady {
+		if err.Error() == common.TriggerNotReady || err == v1alpha1.DEPENDENCY_UPGRADE_PENDING_ERR {
 			ta.Status.MarkDependencyInstalling("tekton-triggers is still installing")
 			// wait for trigger status to change
 			return v1alpha1.REQUEUE_EVENT_AFTER
@@ -142,10 +123,6 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, ta *v1alpha1.TektonAddon
 
 	ta.Status.MarkDependenciesInstalled()
 
-	if err := tektoninstallerset.CleanUpObsoleteResources(ctx, r.operatorClientSet, CreatedByValue); err != nil {
-		return err
-	}
-
 	// validate the params
 	ptVal, _ := findValue(ta.Spec.Params, v1alpha1.PipelineTemplatesParam)
 	ctVal, _ := findValue(ta.Spec.Params, v1alpha1.ClusterTasksParam)
@@ -156,6 +133,10 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, ta *v1alpha1.TektonAddon
 		return nil
 	}
 
+	if err := r.installerSetClient.RemoveObsoleteSets(ctx); err != nil {
+		return err
+	}
+
 	if err := r.extension.PreReconcile(ctx, ta); err != nil {
 		ta.Status.MarkPreReconcilerFailed(err.Error())
 		return err
@@ -163,47 +144,65 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, ta *v1alpha1.TektonAddon
 
 	ta.Status.MarkPreReconcilerComplete()
 
+	// this to check if all sets are in ready set
+	ready := true
+	var errorMsg string
+
 	if err := r.EnsureClusterTask(ctx, ctVal, ta); err != nil {
-		return err
+		ready = false
+		errorMsg = fmt.Sprintf("cluster tasks not yet ready: %v", err)
+		logger.Error(errorMsg)
 	}
 
 	if err := r.EnsureVersionedClusterTask(ctx, ctVal, ta); err != nil {
-		return err
+		ready = false
+		errorMsg = fmt.Sprintf("versioned cluster tasks not yet ready:  %v", err)
+		logger.Error(errorMsg)
 	}
 
 	if err := r.EnsureCommunityClusterTask(ctx, cctVal, ta); err != nil {
-		return err
+		ready = false
+		errorMsg = fmt.Sprintf("community cluster tasks not yet ready:  %v", err)
+		logger.Error(errorMsg)
 	}
 
 	if err := r.EnsurePipelineTemplates(ctx, ptVal, ta); err != nil {
-		return err
+		ready = false
+		errorMsg = fmt.Sprintf("pipelines templates not yet ready:  %v", err)
+		logger.Error(errorMsg)
 	}
 
 	if err := r.EnsureTriggersResources(ctx, ta); err != nil {
-		return err
+		ready = false
+		errorMsg = fmt.Sprintf("triggers resources not yet ready:  %v", err)
+		logger.Error(errorMsg)
 	}
 
-	// Pipelines As Code is installed as a separate component now, so
-	// cleanup any of its installer set created previously
-	// this can be removed in future release
-	if err := r.CleanupPipelinesAsCode(ctx, ta); err != nil {
-		return err
+	if err := r.EnsureOpenShiftConsoleResources(ctx, ta); err != nil {
+		ready = false
+		errorMsg = fmt.Sprintf("openshift console resources not yet ready:  %v", err)
+		logger.Error(errorMsg)
+	}
+
+	if err := r.EnsureConsoleCLI(ctx, ta); err != nil {
+		ready = false
+		errorMsg = fmt.Sprintf("console cli not yet ready:  %v", err)
+		logger.Error(errorMsg)
+	}
+
+	if !ready {
+		ta.Status.MarkInstallerSetNotReady(errorMsg)
+		return nil
 	}
 
 	ta.Status.MarkInstallerSetReady()
 
 	if err := r.extension.PostReconcile(ctx, ta); err != nil {
-		if err == v1alpha1.RECONCILE_AGAIN_ERR {
-			return v1alpha1.REQUEUE_EVENT_AFTER
-		}
 		ta.Status.MarkPostReconcilerFailed(err.Error())
 		return err
 	}
 
 	ta.Status.MarkPostReconcilerComplete()
-
-	ta.Status.SetVersion(r.operatorVersion)
-
 	return nil
 }
 
@@ -232,25 +231,6 @@ func applyAddons(manifest *mf.Manifest, subpath string) error {
 	return nil
 }
 
-// addonTransform mutates the passed manifest to one with common, component
-// and platform transformations applied
-func (r *Reconciler) addonTransform(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent, addnTfs ...mf.Transformer) error {
-	instance := comp.(*v1alpha1.TektonAddon)
-	addonTfs := []mf.Transformer{
-		// using common.InjectOperandNameLabelPreserveExisting instead of common.InjectLabelOverwriteExisting
-		// to highlight that TektonAddon is a basket of various operands(components)
-		// note: using common.InjectLabelOverwriteExisting here  doesnot affect the ability to
-		// use InjectOperandNameLabelPreserveExisting or InjectLabelOverwriteExisting again in the transformer chain
-		// However, it is recomended to use InjectOperandNameLabelPreserveExisting here (in Addons) as we cannot be sure
-		// about order of future addition of transformers in this reconciler or in sub functions which take care of various addons
-		common.InjectOperandNameLabelPreserveExisting(openshift.OperandOpenShiftPipelinesAddons),
-		injectLabel(labelProviderType, providerTypeRedHat, overwrite, "ClusterTask"),
-	}
-	addonTfs = append(addonTfs, addnTfs...)
-	addonTfs = append(addonTfs, r.extension.Transformers(instance)...)
-	return common.Transform(ctx, manifest, instance, addonTfs...)
-}
-
 func findValue(params []v1alpha1.Param, name string) (string, bool) {
 	for _, p := range params {
 		if p.Name == name {
@@ -259,28 +239,3 @@ func findValue(params []v1alpha1.Param, name string) (string, bool) {
 	}
 	return "", false
 }
-
-func (r *Reconciler) markUpgrade(ctx context.Context, ta *v1alpha1.TektonAddon) error {
-	labels := ta.GetLabels()
-	ver, ok := labels[v1alpha1.ReleaseVersionKey]
-	if ok && ver == r.operatorVersion {
-		return nil
-	}
-	if ok && ver != r.operatorVersion {
-		ta.Status.MarkInstallerSetNotReady(v1alpha1.UpgradePending)
-		ta.Status.MarkPreReconcilerFailed(v1alpha1.UpgradePending)
-		ta.Status.MarkPostReconcilerFailed(v1alpha1.UpgradePending)
-		ta.Status.MarkNotReady(v1alpha1.UpgradePending)
-	}
-	if labels == nil {
-		labels = map[string]string{}
-	}
-	labels[v1alpha1.ReleaseVersionKey] = r.operatorVersion
-	ta.SetLabels(labels)
-
-	if _, err := r.operatorClientSet.OperatorV1alpha1().TektonAddons().Update(ctx,
-		ta, metav1.UpdateOptions{}); err != nil {
-		return err
-	}
-	return v1alpha1.RECONCILE_AGAIN_ERR
-}
diff --git a/pkg/reconciler/openshift/tektonaddon/transform.go b/pkg/reconciler/openshift/tektonaddon/transform.go
new file mode 100644
index 000000000..bf6cbdae3
--- /dev/null
+++ b/pkg/reconciler/openshift/tektonaddon/transform.go
@@ -0,0 +1,45 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package tektonaddon
+
+import (
+	"context"
+
+	mf "github.com/manifestival/manifestival"
+	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	"github.com/tektoncd/operator/pkg/reconciler/common"
+	"github.com/tektoncd/operator/pkg/reconciler/openshift"
+)
+
+func transformers(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent, addnTfs ...mf.Transformer) error {
+	instance := comp.(*v1alpha1.TektonAddon)
+	addonImages := common.ToLowerCaseKeys(common.ImagesFromEnv(common.AddonsImagePrefix))
+
+	addonTfs := []mf.Transformer{
+		// using common.InjectOperandNameLabelPreserveExisting instead of common.InjectLabelOverwriteExisting
+		// to highlight that TektonAddon is a basket of various operands(components)
+		// note: using common.InjectLabelOverwriteExisting here  doesnot affect the ability to
+		// use InjectOperandNameLabelPreserveExisting or InjectLabelOverwriteExisting again in the transformer chain
+		// However, it is recomended to use InjectOperandNameLabelPreserveExisting here (in Addons) as we cannot be sure
+		// about order of future addition of transformers in this reconciler or in sub functions which take care of various addons
+		common.InjectOperandNameLabelPreserveExisting(openshift.OperandOpenShiftPipelinesAddons),
+		injectLabel(labelProviderType, providerTypeRedHat, overwrite, "ClusterTask"),
+		common.TaskImages(addonImages),
+	}
+	addonTfs = append(addonTfs, addnTfs...)
+	return common.Transform(ctx, manifest, instance, addonTfs...)
+}
diff --git a/pkg/reconciler/openshift/tektonaddon/triggers.go b/pkg/reconciler/openshift/tektonaddon/triggers.go
index c7130c133..37415a1dc 100644
--- a/pkg/reconciler/openshift/tektonaddon/triggers.go
+++ b/pkg/reconciler/openshift/tektonaddon/triggers.go
@@ -18,60 +18,25 @@ package tektonaddon
 
 import (
 	"context"
-	"fmt"
 
 	mf "github.com/manifestival/manifestival"
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
-	"github.com/tektoncd/operator/pkg/reconciler/common"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client"
 )
 
-var triggerResourceLS = metav1.LabelSelector{
-	MatchLabels: map[string]string{
-		v1alpha1.InstallerSetType: TriggersResourcesInstallerSet,
-	},
-}
-
 func (r *Reconciler) EnsureTriggersResources(ctx context.Context, ta *v1alpha1.TektonAddon) error {
-
-	triggerResourceLabelSelector, err := common.LabelSelector(triggerResourceLS)
-	if err != nil {
-		return err
-	}
-	exist, _, err := checkIfInstallerSetExist(ctx, r.operatorClientSet, r.operatorVersion, triggerResourceLabelSelector)
-	if err != nil {
+	if err := r.installerSetClient.CustomSet(ctx, ta, TriggersResourcesInstallerSet, r.triggersResourcesManifest, filterAndTransformCommon()); err != nil {
 		return err
 	}
-	if !exist {
-		msg := fmt.Sprintf("%s being created/upgraded", TriggersResourcesInstallerSet)
-		ta.Status.MarkInstallerSetNotReady(msg)
-		return r.ensureTriggerResources(ctx, ta)
-	}
-
-	err = r.checkComponentStatus(ctx, triggerResourceLabelSelector)
-	if err != nil {
-		ta.Status.MarkInstallerSetNotReady(err.Error())
-		return nil
-	}
-
 	return nil
 }
 
-func (r *Reconciler) ensureTriggerResources(ctx context.Context, ta *v1alpha1.TektonAddon) error {
-	triggerResourcesManifest := mf.Manifest{}
-
-	if err := applyAddons(&triggerResourcesManifest, "01-clustertriggerbindings"); err != nil {
-		return err
+func filterAndTransformCommon() client.FilterAndTransform {
+	return func(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent) (*mf.Manifest, error) {
+		addon := comp.(*v1alpha1.TektonAddon)
+		if err := transformers(ctx, manifest, addon); err != nil {
+			return nil, err
+		}
+		return manifest, nil
 	}
-	// Run transformers
-	if err := r.addonTransform(ctx, &triggerResourcesManifest, ta); err != nil {
-		return err
-	}
-
-	if err := createInstallerSet(ctx, r.operatorClientSet, ta, triggerResourcesManifest, r.operatorVersion,
-		TriggersResourcesInstallerSet, "addon-triggers"); err != nil {
-		return err
-	}
-
-	return nil
 }
diff --git a/pkg/reconciler/openshift/tektonconfig/extension.go b/pkg/reconciler/openshift/tektonconfig/extension.go
index 4af60365b..7bae935f5 100644
--- a/pkg/reconciler/openshift/tektonconfig/extension.go
+++ b/pkg/reconciler/openshift/tektonconfig/extension.go
@@ -123,7 +123,7 @@ func (oe openshiftExtension) PostReconcile(ctx context.Context, comp v1alpha1.Te
 
 	if configInstance.Spec.Profile == v1alpha1.ProfileAll {
 		if _, err := extension.EnsureTektonAddonExists(ctx, oe.operatorClientSet.OperatorV1alpha1().TektonAddons(), configInstance); err != nil {
-			configInstance.Status.MarkComponentNotReady(fmt.Sprintf("TektonAddon: %s", err.Error()))
+			configInstance.Status.MarkPostInstallFailed(fmt.Sprintf("TektonAddon not ready: %s", err.Error()))
 			return v1alpha1.REQUEUE_EVENT_AFTER
 		}
 	}
diff --git a/pkg/reconciler/openshift/tektonconfig/extension/addon.go b/pkg/reconciler/openshift/tektonconfig/extension/addon.go
index 02f25042e..58d58073b 100644
--- a/pkg/reconciler/openshift/tektonconfig/extension/addon.go
+++ b/pkg/reconciler/openshift/tektonconfig/extension/addon.go
@@ -20,12 +20,13 @@ import (
 	"context"
 	"fmt"
 	"reflect"
+	"strings"
 
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
 	op "github.com/tektoncd/operator/pkg/client/clientset/versioned/typed/operator/v1alpha1"
-	"github.com/tektoncd/operator/pkg/reconciler/common"
 	apierrs "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"knative.dev/pkg/apis"
 )
 
 func EnsureTektonAddonExists(ctx context.Context, clients op.TektonAddonInterface, config *v1alpha1.TektonConfig) (*v1alpha1.TektonAddon, error) {
@@ -124,14 +125,12 @@ func updateAddon(ctx context.Context, taCR *v1alpha1.TektonAddon, config *v1alph
 
 // isTektonAddonReady will check the status conditions of the TektonAddon and return true if the TektonAddon is ready.
 func isTektonAddonReady(s *v1alpha1.TektonAddon, err error) (bool, error) {
-	upgradePending, errInternal := common.CheckUpgradePending(s)
-	if err != nil {
-		return false, errInternal
-	}
-	if upgradePending {
-		return false, v1alpha1.DEPENDENCY_UPGRADE_PENDING_ERR
+	if s.GetStatus() != nil && s.GetStatus().GetCondition(apis.ConditionReady) != nil {
+		if strings.Contains(s.GetStatus().GetCondition(apis.ConditionReady).Message, v1alpha1.UpgradePending) {
+			return false, v1alpha1.DEPENDENCY_UPGRADE_PENDING_ERR
+		}
 	}
-	return s.Status.IsReady(), err
+	return s.Status.IsReady(), nil
 }
 
 func EnsureTektonAddonCRNotExists(ctx context.Context, clients op.TektonAddonInterface) error {
diff --git a/pkg/reconciler/shared/tektonconfig/tektonconfig.go b/pkg/reconciler/shared/tektonconfig/tektonconfig.go
index e9a54e286..8b44043f6 100644
--- a/pkg/reconciler/shared/tektonconfig/tektonconfig.go
+++ b/pkg/reconciler/shared/tektonconfig/tektonconfig.go
@@ -145,8 +145,7 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, tc *v1alpha1.TektonConfi
 	tc.Status.MarkComponentsReady()
 
 	if err := r.extension.PostReconcile(ctx, tc); err != nil {
-		tc.Status.MarkPostInstallFailed(err.Error())
-		return v1alpha1.REQUEUE_EVENT_AFTER
+		return err
 	}
 
 	tc.Status.MarkPostInstallComplete()


Test patch:
diff --git a/pkg/apis/operator/v1alpha1/tektonpipeline_defaults_test.go b/pkg/apis/operator/v1alpha1/tektonpipeline_defaults_test.go
index 487b7343f..d5eeec86e 100644
--- a/pkg/apis/operator/v1alpha1/tektonpipeline_defaults_test.go
+++ b/pkg/apis/operator/v1alpha1/tektonpipeline_defaults_test.go
@@ -57,6 +57,12 @@ func Test_SetDefaults_PipelineProperties(t *testing.T) {
 			MetricsTaskrunDurationType:     "histogram",
 			MetricsTaskrunLevel:            "task",
 		},
+		Resolvers: Resolvers{
+			EnableBundlesResolver: ptr.Bool(true),
+			EnableHubResolver:     ptr.Bool(true),
+			EnableGitResolver:     ptr.Bool(true),
+			EnableClusterResolver: ptr.Bool(true),
+		},
 	}
 
 	tp.SetDefaults(context.TODO())
diff --git a/pkg/reconciler/common/testdata/test-add-psa-expected-statefulset.yaml b/pkg/reconciler/common/testdata/test-add-psa-expected-statefulset.yaml
new file mode 100644
index 000000000..7c1baf91e
--- /dev/null
+++ b/pkg/reconciler/common/testdata/test-add-psa-expected-statefulset.yaml
@@ -0,0 +1,65 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/name: tekton-results-postgres
+    app.kubernetes.io/part-of: tekton-results
+    app.kubernetes.io/version: v0.4.0
+  name: tekton-results-postgres
+  namespace: tekton-pipelines
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: tekton-results-postgres
+      app.kubernetes.io/part-of: tekton-results
+      app.kubernetes.io/version: v0.4.0
+  serviceName: postgres
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: tekton-results-postgres
+        app.kubernetes.io/part-of: tekton-results
+        app.kubernetes.io/version: v0.4.0
+    spec:
+      securityContext:
+        runAsNonRoot: true
+        seccompProfile:
+          type: RuntimeDefault
+      containers:
+        - envFrom:
+            - configMapRef:
+                name: tekton-results-postgres
+            - secretRef:
+                name: tekton-results-postgres
+          image: postgres@sha256:6647385dd9ae11aa2216bf55c54d126b0a85637b3cf4039ef24e3234113588e3
+          name: postgres
+          ports:
+            - containerPort: 5432
+              name: postgredb
+          volumeMounts:
+            - mountPath: /var/data
+              name: postgredb
+            - mountPath: /docker-entrypoint-initdb.d
+              name: sql-initdb
+          securityContext:
+            allowPrivilegeEscalation: false
+            capabilities:
+              drop:
+                - ALL
+      volumes:
+        - configMap:
+            name: tekton-results-sql-initdb-config
+          name: sql-initdb
+  volumeClaimTemplates:
+    - metadata:
+        labels:
+          app.kubernetes.io/part-of: tekton-results
+          app.kubernetes.io/version: v0.4.0
+        name: postgredb
+      spec:
+        accessModes:
+          - ReadWriteOnce
+        resources:
+          requests:
+            storage: 1Gi
diff --git a/pkg/reconciler/common/testdata/test-add-psa-statefulset.yaml b/pkg/reconciler/common/testdata/test-add-psa-statefulset.yaml
new file mode 100644
index 000000000..4b9f62244
--- /dev/null
+++ b/pkg/reconciler/common/testdata/test-add-psa-statefulset.yaml
@@ -0,0 +1,56 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/name: tekton-results-postgres
+    app.kubernetes.io/part-of: tekton-results
+    app.kubernetes.io/version: v0.4.0
+  name: tekton-results-postgres
+  namespace: tekton-pipelines
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: tekton-results-postgres
+      app.kubernetes.io/part-of: tekton-results
+      app.kubernetes.io/version: v0.4.0
+  serviceName: postgres
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: tekton-results-postgres
+        app.kubernetes.io/part-of: tekton-results
+        app.kubernetes.io/version: v0.4.0
+    spec:
+      containers:
+        - envFrom:
+            - configMapRef:
+                name: tekton-results-postgres
+            - secretRef:
+                name: tekton-results-postgres
+          image: postgres@sha256:6647385dd9ae11aa2216bf55c54d126b0a85637b3cf4039ef24e3234113588e3
+          name: postgres
+          ports:
+            - containerPort: 5432
+              name: postgredb
+          volumeMounts:
+            - mountPath: /var/data
+              name: postgredb
+            - mountPath: /docker-entrypoint-initdb.d
+              name: sql-initdb
+      volumes:
+        - configMap:
+            name: tekton-results-sql-initdb-config
+          name: sql-initdb
+  volumeClaimTemplates:
+    - metadata:
+        labels:
+          app.kubernetes.io/part-of: tekton-results
+          app.kubernetes.io/version: v0.4.0
+        name: postgredb
+      spec:
+        accessModes:
+          - ReadWriteOnce
+        resources:
+          requests:
+            storage: 1Gi
diff --git a/pkg/reconciler/common/testdata/test-resolver-config.yaml b/pkg/reconciler/common/testdata/test-resolver-config.yaml
new file mode 100644
index 000000000..10d7ce4c0
--- /dev/null
+++ b/pkg/reconciler/common/testdata/test-resolver-config.yaml
@@ -0,0 +1,20 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: hubresolver-config
+  namespace: tekton-pipelines-resolvers
+  labels:
+    app.kubernetes.io/component: resolvers
+    app.kubernetes.io/instance: default
+    app.kubernetes.io/part-of: tekton-pipelines
+data:
+  # the default Tekton Hub catalog from where to pull the resource.
+  default-tekton-hub-catalog: "Tekton"
+  # the default Artifact Hub Task catalog from where to pull the resource.
+  default-artifact-hub-task-catalog: "tekton-catalog-tasks"
+  # the default Artifact Hub Pipeline catalog from where to pull the resource.
+  default-artifact-hub-pipeline-catalog: "tekton-catalog-pipelines"
+  # the default layer kind in the hub image.
+  default-kind: "task"
+  # the default hub source to pull the resource from.
+  default-type: "artifact"
diff --git a/pkg/reconciler/common/transformers_test.go b/pkg/reconciler/common/transformers_test.go
index 751200b3d..30be23ee5 100644
--- a/pkg/reconciler/common/transformers_test.go
+++ b/pkg/reconciler/common/transformers_test.go
@@ -543,3 +543,62 @@ func TestAddPSA(t *testing.T) {
 		t.Errorf("failed to update deployment %s", diff.PrintWantGot(d))
 	}
 }
+
+func TestAddStatefulSetPSA(t *testing.T) {
+	testData := path.Join("testdata", "test-add-psa-statefulset.yaml")
+	manifest, err := mf.ManifestFrom(mf.Recursive(testData))
+	assert.NilError(t, err)
+
+	newManifest, err := manifest.Transform(AddStatefulSetRestrictedPSA())
+	assert.NilError(t, err)
+
+	got := &appsv1.StatefulSet{}
+	err = runtime.DefaultUnstructuredConverter.FromUnstructured(newManifest.Resources()[0].Object, got)
+	if err != nil {
+		t.Errorf("failed to load deployment yaml")
+	}
+
+	testData = path.Join("testdata", "test-add-psa-expected-statefulset.yaml")
+	expectedManifest, err := mf.ManifestFrom(mf.Recursive(testData))
+	assert.NilError(t, err)
+
+	expected := &appsv1.StatefulSet{}
+	err = runtime.DefaultUnstructuredConverter.FromUnstructured(expectedManifest.Resources()[0].Object, expected)
+	if err != nil {
+		t.Errorf("failed to load deployment yaml")
+	}
+
+	if d := cmp.Diff(expected, got); d != "" {
+		t.Errorf("failed to update deployment %s", diff.PrintWantGot(d))
+	}
+}
+
+func TestCopyConfigMapValues(t *testing.T) {
+	testData := path.Join("testdata", "test-resolver-config.yaml")
+	manifest, err := mf.ManifestFrom(mf.Recursive(testData))
+	assertNoEror(t, err)
+
+	expectedValues := map[string]string{
+		"default-tekton-hub-catalog":        "abc-catalog",
+		"default-artifact-hub-task-catalog": "some-random-catalog",
+		"ignore-me-field":                   "ignore-me",
+	}
+
+	manifest, err = manifest.Transform(CopyConfigMap("hubresolver-config", expectedValues))
+	assertNoEror(t, err)
+
+	cm := &corev1.ConfigMap{}
+	err = runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.Resources()[0].Object, cm)
+	assertNoEror(t, err)
+	// ConfigMap will have values changed only for field which are defined
+	assert.Equal(t, cm.Data["default-tekton-hub-catalog"], "abc-catalog")
+	assert.Equal(t, cm.Data["default-artifact-hub-task-catalog"], "some-random-catalog")
+
+	// fields which are not defined in expected configmap will be same as before
+	assert.Equal(t, cm.Data["default-kind"], "task")
+	assert.Equal(t, cm.Data["default-type"], "artifact")
+
+	// extra fields in expected configmap will be ignore and will not be added
+	assert.Equal(t, cm.Data["ignore-me-field"], "")
+
+}
diff --git a/pkg/reconciler/openshift/tektonconfig/extension/addon_test.go b/pkg/reconciler/openshift/tektonconfig/extension/addon_test.go
index 4dc76031c..7fdc7c4fd 100644
--- a/pkg/reconciler/openshift/tektonconfig/extension/addon_test.go
+++ b/pkg/reconciler/openshift/tektonconfig/extension/addon_test.go
@@ -44,7 +44,7 @@ func TestEnsureTektonAddonCRExists(t *testing.T) {
 	// during second invocation instance exists but waiting on dependencies (pipeline, triggers)
 	// hence returns DEPENDENCY_UPGRADE_PENDING_ERR
 	_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig)
-	util.AssertEqual(t, err, v1alpha1.DEPENDENCY_UPGRADE_PENDING_ERR)
+	util.AssertEqual(t, err, v1alpha1.RECONCILE_AGAIN_ERR)
 
 	// make upgrade checks pass
 	makeUpgradeCheckPass(t, ctx, c.OperatorV1alpha1().TektonAddons())
diff --git a/test/e2e/kubernetes/tektonresultdeployment_test.go b/test/e2e/kubernetes/tektonresultdeployment_test.go
index b9f281ac2..7e6b689ec 100644
--- a/test/e2e/kubernetes/tektonresultdeployment_test.go
+++ b/test/e2e/kubernetes/tektonresultdeployment_test.go
@@ -37,6 +37,7 @@ import (
 
 // TestTektonResultDeployment verifies the TektonResult creation, deployment recreation, and TektonResult deletion.
 func TestTektonResultDeployment(t *testing.T) {
+	t.Skip()
 	platform := os.Getenv("PLATFORM")
 	if platform == "linux/ppc64le" || platform == "linux/s390x" {
 		t.Skipf("Tekton Result is not available for %q", platform)