Repository: tektoncd/operator
Pull request #338 (2021-06-30 08:59:54)

Configure node selection for components using CR spec
This provides fields in CR to customize the deployments of components
to select node using nodeselector or/and toleration.
Pass the values for nodeselector and toleration in spec of TektonConfig
CR which will be passed further to components and will get added in
deployments.

Signed-off-by: Shivam Mukhade <smukhade@redhat.com>

# Submitter Checklist

These are the criteria that every PR should meet, please check them off as you
review them:

- [x] Includes [tests](https://github.com/tektoncd/community/blob/master/standards.md#principles) (if functionality changed/added)
- [x] Includes [docs](https://github.com/tektoncd/community/blob/master/standards.md#principles) (if user facing)
- [x] Commit messages follow [commit message best practices](https://github.com/tektoncd/community/blob/master/standards.md#commit-messages)

_See [the contribution guide](https://github.com/tektoncd/operator/blob/master/CONTRIBUTING.md) for more details._

# Release Notes

<!--
Describe any user facing changes here, or delete this block.

Examples of user facing changes:
- API changes
- Bug fixes
- Any changes in behavior
- Changes requiring upgrade notices or deprecation warnings

For pull requests with a release note:

```release-note
Your release note here
```

For pull requests that require additional action from users switching to the new release, include the string "action required" (case insensitive) in the release note:

```release-note
action required: your release note here
```

For pull requests that don't need to be mentioned at release time, use the `/release-note-none` Prow command to add the `release-note-none` label to the PR. You can also write the string "NONE" as a release note in your PR description:

```release-note
NONE
```
-->
Provides fields `nodeSelector` and `toleration` in CR to configure node selection for pods created through operator. User can add the fields in TektonConfig CR and later operator will propagate it to the CRs created by it and add in all deployments created by it.

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 **sthaha**
You can assign the PR to them by writing `/assign @sthaha` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?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":["sthaha"]} -->
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonconfig_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1410161202473996290/artifacts/line-cov.html#file2) | 88.9% | 89.7% | 0.8
[pkg/apis/operator/v1alpha1/tektonpipeline_defaults.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1410161202473996290/artifacts/line-cov.html#file4) | Do not exist | 100.0% | 
[pkg/apis/operator/v1alpha1/tektonpipeline_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1410161202473996290/artifacts/line-cov.html#file6) | 100.0% | 76.9% | -23.1
[pkg/reconciler/common/transformers.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1410161202473996290/artifacts/line-cov.html#file10) | 64.5% | 71.0% | 6.5
[pkg/reconciler/kubernetes/tektonconfig/extension/dashboard.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1410161202473996290/artifacts/line-cov.html#file11) | 75.6% | 69.4% | -6.2
[pkg/reconciler/kubernetes/tektonconfig/pipeline/pipeline.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1410161202473996290/artifacts/line-cov.html#file12) | 76.1% | 68.6% | -7.5
[pkg/reconciler/kubernetes/tektonconfig/trigger/trigger.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1410161202473996290/artifacts/line-cov.html#file13) | 75.6% | 69.4% | -6.2
[pkg/reconciler/openshift/tektonconfig/extension/addon.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1410161202473996290/artifacts/line-cov.html#file14) | 66.7% | 65.4% | -1.3

tekton-robot: @sm43: PR needs rebase.

<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>
sm43: /cc @nikhil-thomas 
@piyush-garg 
@pradeepitm12 
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/reconciler/common/transformers.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1414435069971402752/artifacts/line-cov.html#file6) | 71.7% | 72.0% | 0.4
[pkg/reconciler/kubernetes/tektonconfig/extension/dashboard.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1414435069971402752/artifacts/line-cov.html#file7) | 75.6% | 69.4% | -6.2
[pkg/reconciler/kubernetes/tektonconfig/pipeline/pipeline.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1414435069971402752/artifacts/line-cov.html#file8) | 70.0% | 68.6% | -1.4
[pkg/reconciler/kubernetes/tektonconfig/trigger/trigger.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1414435069971402752/artifacts/line-cov.html#file9) | 75.6% | 69.4% | -6.2
[pkg/reconciler/openshift/tektonconfig/extension/addon.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1414435069971402752/artifacts/line-cov.html#file10) | 66.7% | 65.4% | -1.3

tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/reconciler/common/transformers.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1415156701492940803/artifacts/line-cov.html#file5) | 71.7% | 72.0% | 0.4
[pkg/reconciler/kubernetes/tektonconfig/extension/dashboard.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1415156701492940803/artifacts/line-cov.html#file6) | 75.6% | 69.4% | -6.2
[pkg/reconciler/kubernetes/tektonconfig/pipeline/pipeline.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1415156701492940803/artifacts/line-cov.html#file7) | 70.0% | 68.6% | -1.4
[pkg/reconciler/kubernetes/tektonconfig/trigger/trigger.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1415156701492940803/artifacts/line-cov.html#file8) | 75.6% | 69.4% | -6.2
[pkg/reconciler/openshift/tektonconfig/extension/addon.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1415156701492940803/artifacts/line-cov.html#file9) | 66.7% | 65.4% | -1.3

nikhil-thomas: /approve
tekton-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/tektoncd/operator/pull/338#issuecomment-885505338" title="Approved">nikhil-thomas</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?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)~~ [nikhil-thomas]

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: @sm43 could you add a brief release note to the pr description.
Looks good to me. 👍 
Let us get additional reviews. 
tekton-robot: @sm43: PR needs rebase.

<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: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/reconciler/common/transformers.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1419513660274905088/artifacts/line-cov.html#file5) | 72.5% | 72.8% | 0.3
[pkg/reconciler/kubernetes/tektonconfig/extension/dashboard.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1419513660274905088/artifacts/line-cov.html#file6) | 75.6% | 69.4% | -6.2
[pkg/reconciler/kubernetes/tektonconfig/pipeline/pipeline.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1419513660274905088/artifacts/line-cov.html#file7) | 70.0% | 68.6% | -1.4
[pkg/reconciler/kubernetes/tektonconfig/trigger/trigger.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1419513660274905088/artifacts/line-cov.html#file8) | 75.6% | 69.4% | -6.2
[pkg/reconciler/openshift/tektonconfig/extension/addon.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1419513660274905088/artifacts/line-cov.html#file9) | 66.7% | 65.4% | -1.3

tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/reconciler/common/transformers.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1419514541204574209/artifacts/line-cov.html#file5) | 72.5% | 72.8% | 0.3
[pkg/reconciler/kubernetes/tektonconfig/extension/dashboard.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1419514541204574209/artifacts/line-cov.html#file6) | 75.6% | 69.4% | -6.2
[pkg/reconciler/kubernetes/tektonconfig/pipeline/pipeline.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1419514541204574209/artifacts/line-cov.html#file7) | 70.0% | 68.6% | -1.4
[pkg/reconciler/kubernetes/tektonconfig/trigger/trigger.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1419514541204574209/artifacts/line-cov.html#file8) | 75.6% | 69.4% | -6.2
[pkg/reconciler/openshift/tektonconfig/extension/addon.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/338/pull-tekton-operator-go-coverage/1419514541204574209/artifacts/line-cov.html#file9) | 66.7% | 65.4% | -1.3


Patch:
diff --git a/pkg/apis/operator/v1alpha1/tektonconfig_types.go b/pkg/apis/operator/v1alpha1/tektonconfig_types.go
index f8a23743d..cf6f6f367 100644
--- a/pkg/apis/operator/v1alpha1/tektonconfig_types.go
+++ b/pkg/apis/operator/v1alpha1/tektonconfig_types.go
@@ -19,6 +19,7 @@ package v1alpha1
 import (
 	"reflect"
 
+	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	duckv1 "knative.dev/pkg/apis/duck/v1"
 )
@@ -69,6 +70,9 @@ func (p Prune) IsEmpty() bool {
 // TektonConfigSpec defines the desired state of TektonConfig
 type TektonConfigSpec struct {
 	Profile string `json:"profile,omitempty"`
+	// Config holds the configuration for resources created by TektonConfig
+	// +optional
+	Config Config `json:"config,omitempty"`
 	// Pruner holds the prune config
 	// +optional
 	Pruner     Prune `json:"pruner,omitempty"`
@@ -117,3 +121,8 @@ func (a Addon) IsEmpty() bool {
 type Pipeline struct {
 	PipelineProperties `json:",inline"`
 }
+
+type Config struct {
+	NodeSelector map[string]string   `json:"nodeSelector,omitempty"`
+	Tolerations  []corev1.Toleration `json:"tolerations,omitempty"`
+}
diff --git a/pkg/apis/operator/v1alpha1/tektondashboard_types.go b/pkg/apis/operator/v1alpha1/tektondashboard_types.go
index c12dbf009..a0f400472 100644
--- a/pkg/apis/operator/v1alpha1/tektondashboard_types.go
+++ b/pkg/apis/operator/v1alpha1/tektondashboard_types.go
@@ -52,6 +52,9 @@ func (tp *TektonDashboard) GetStatus() TektonComponentStatus {
 // TektonDashboardSpec defines the desired state of TektonDashboard
 type TektonDashboardSpec struct {
 	CommonSpec `json:",inline"`
+	// Config holds the configuration for resources created by TektonDashboard
+	// +optional
+	Config Config `json:"config,omitempty"`
 }
 
 // TektonDashboardStatus defines the observed state of TektonDashboard
diff --git a/pkg/apis/operator/v1alpha1/tektonpipeline_types.go b/pkg/apis/operator/v1alpha1/tektonpipeline_types.go
index 5a40a4596..558cf48c9 100644
--- a/pkg/apis/operator/v1alpha1/tektonpipeline_types.go
+++ b/pkg/apis/operator/v1alpha1/tektonpipeline_types.go
@@ -53,6 +53,9 @@ func (tp *TektonPipeline) GetStatus() TektonComponentStatus {
 type TektonPipelineSpec struct {
 	CommonSpec         `json:",inline"`
 	PipelineProperties `json:",inline"`
+	// Config holds the configuration for resources created by TektonPipeline
+	// +optional
+	Config Config `json:"config,omitempty"`
 }
 
 // TektonPipelineStatus defines the observed state of TektonPipeline
diff --git a/pkg/apis/operator/v1alpha1/tektontrigger_types.go b/pkg/apis/operator/v1alpha1/tektontrigger_types.go
index 4f127cdb2..93f6899d1 100644
--- a/pkg/apis/operator/v1alpha1/tektontrigger_types.go
+++ b/pkg/apis/operator/v1alpha1/tektontrigger_types.go
@@ -52,6 +52,9 @@ func (tp *TektonTrigger) GetStatus() TektonComponentStatus {
 // TektonTriggerSpec defines the desired state of TektonTrigger
 type TektonTriggerSpec struct {
 	CommonSpec `json:",inline"`
+	// Config holds the configuration for resources created by TektonTrigger
+	// +optional
+	Config Config `json:"config,omitempty"`
 }
 
 // TektonTriggerStatus defines the observed state of TektonTrigger
diff --git a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go
index c6df95a7f..5379376d0 100644
--- a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go
@@ -21,6 +21,7 @@ limitations under the License.
 package v1alpha1
 
 import (
+	v1 "k8s.io/api/core/v1"
 	runtime "k8s.io/apimachinery/pkg/runtime"
 )
 
@@ -61,6 +62,36 @@ func (in *CommonSpec) DeepCopy() *CommonSpec {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Config) DeepCopyInto(out *Config) {
+	*out = *in
+	if in.NodeSelector != nil {
+		in, out := &in.NodeSelector, &out.NodeSelector
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.Tolerations != nil {
+		in, out := &in.Tolerations, &out.Tolerations
+		*out = make([]v1.Toleration, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config.
+func (in *Config) DeepCopy() *Config {
+	if in == nil {
+		return nil
+	}
+	out := new(Config)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *OptionalPipelineProperties) DeepCopyInto(out *OptionalPipelineProperties) {
 	*out = *in
@@ -388,6 +419,7 @@ func (in *TektonConfigList) DeepCopyObject() runtime.Object {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *TektonConfigSpec) DeepCopyInto(out *TektonConfigSpec) {
 	*out = *in
+	in.Config.DeepCopyInto(&out.Config)
 	in.Pruner.DeepCopyInto(&out.Pruner)
 	out.CommonSpec = in.CommonSpec
 	in.Addon.DeepCopyInto(&out.Addon)
@@ -432,7 +464,7 @@ func (in *TektonDashboard) DeepCopyInto(out *TektonDashboard) {
 	*out = *in
 	out.TypeMeta = in.TypeMeta
 	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
-	out.Spec = in.Spec
+	in.Spec.DeepCopyInto(&out.Spec)
 	in.Status.DeepCopyInto(&out.Status)
 	return
 }
@@ -492,6 +524,7 @@ func (in *TektonDashboardList) DeepCopyObject() runtime.Object {
 func (in *TektonDashboardSpec) DeepCopyInto(out *TektonDashboardSpec) {
 	*out = *in
 	out.CommonSpec = in.CommonSpec
+	in.Config.DeepCopyInto(&out.Config)
 	return
 }
 
@@ -593,6 +626,7 @@ func (in *TektonPipelineSpec) DeepCopyInto(out *TektonPipelineSpec) {
 	*out = *in
 	out.CommonSpec = in.CommonSpec
 	in.PipelineProperties.DeepCopyInto(&out.PipelineProperties)
+	in.Config.DeepCopyInto(&out.Config)
 	return
 }
 
@@ -733,7 +767,7 @@ func (in *TektonTrigger) DeepCopyInto(out *TektonTrigger) {
 	*out = *in
 	out.TypeMeta = in.TypeMeta
 	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
-	out.Spec = in.Spec
+	in.Spec.DeepCopyInto(&out.Spec)
 	in.Status.DeepCopyInto(&out.Status)
 	return
 }
@@ -793,6 +827,7 @@ func (in *TektonTriggerList) DeepCopyObject() runtime.Object {
 func (in *TektonTriggerSpec) DeepCopyInto(out *TektonTriggerSpec) {
 	*out = *in
 	out.CommonSpec = in.CommonSpec
+	in.Config.DeepCopyInto(&out.Config)
 	return
 }
 
diff --git a/pkg/reconciler/common/transformers.go b/pkg/reconciler/common/transformers.go
index 99174e1d4..06dd08d8c 100644
--- a/pkg/reconciler/common/transformers.go
+++ b/pkg/reconciler/common/transformers.go
@@ -525,3 +525,28 @@ func InjectLabelOnNamespace(label string) mf.Transformer {
 		return nil
 	}
 }
+
+func AddConfiguration(config v1alpha1.Config) mf.Transformer {
+	return func(u *unstructured.Unstructured) error {
+		if u.GetKind() != "Deployment" {
+			return nil
+		}
+
+		d := &appsv1.Deployment{}
+		err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, d)
+		if err != nil {
+			return err
+		}
+
+		d.Spec.Template.Spec.NodeSelector = config.NodeSelector
+		d.Spec.Template.Spec.Tolerations = config.Tolerations
+
+		unstrObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(d)
+		if err != nil {
+			return err
+		}
+		u.SetUnstructuredContent(unstrObj)
+
+		return nil
+	}
+}
diff --git a/pkg/reconciler/kubernetes/tektonconfig/extension/dashboard.go b/pkg/reconciler/kubernetes/tektonconfig/extension/dashboard.go
index c5cab839e..0a0476b02 100644
--- a/pkg/reconciler/kubernetes/tektonconfig/extension/dashboard.go
+++ b/pkg/reconciler/kubernetes/tektonconfig/extension/dashboard.go
@@ -21,9 +21,9 @@ import (
 	"errors"
 	"fmt"
 	"log"
+	"reflect"
 
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
-
 	op "github.com/tektoncd/operator/pkg/client/clientset/versioned/typed/operator/v1alpha1"
 	operatorv1alpha1 "github.com/tektoncd/operator/pkg/client/clientset/versioned/typed/operator/v1alpha1"
 	"github.com/tektoncd/operator/pkg/reconciler/common"
@@ -35,7 +35,7 @@ import (
 
 func CreateDashboardCR(instance v1alpha1.TektonComponent, client operatorv1alpha1.OperatorV1alpha1Interface) error {
 	configInstance := instance.(*v1alpha1.TektonConfig)
-	if _, err := ensureTektonDashboardExists(client.TektonDashboards(), configInstance.Spec.TargetNamespace); err != nil {
+	if _, err := ensureTektonDashboardExists(client.TektonDashboards(), configInstance); err != nil {
 		return errors.New(err.Error())
 	}
 	if _, err := waitForTektonDashboardState(client.TektonDashboards(), common.DashboardResourceName,
@@ -46,9 +46,19 @@ func CreateDashboardCR(instance v1alpha1.TektonComponent, client operatorv1alpha
 	return nil
 }
 
-func ensureTektonDashboardExists(clients op.TektonDashboardInterface, targetNS string) (*v1alpha1.TektonDashboard, error) {
+func ensureTektonDashboardExists(clients op.TektonDashboardInterface, config *v1alpha1.TektonConfig) (*v1alpha1.TektonDashboard, error) {
 	tdCR, err := GetDashboard(clients, common.DashboardResourceName)
 	if err == nil {
+		// if the dashboard spec is changed then update the instance
+		if config.Spec.TargetNamespace != tdCR.Spec.TargetNamespace ||
+			!reflect.DeepEqual(tdCR.Spec.Config, config.Spec.Config) {
+
+			tdCR.Spec.TargetNamespace = config.Spec.TargetNamespace
+			tdCR.Spec.Config = config.Spec.Config
+
+			return clients.Update(context.TODO(), tdCR, metav1.UpdateOptions{})
+		}
+
 		return tdCR, err
 	}
 	if apierrs.IsNotFound(err) {
@@ -58,8 +68,9 @@ func ensureTektonDashboardExists(clients op.TektonDashboardInterface, targetNS s
 			},
 			Spec: v1alpha1.TektonDashboardSpec{
 				CommonSpec: v1alpha1.CommonSpec{
-					TargetNamespace: targetNS,
+					TargetNamespace: config.Spec.TargetNamespace,
 				},
+				Config: config.Spec.Config,
 			},
 		}
 		return clients.Create(context.TODO(), tdCR, metav1.CreateOptions{})
diff --git a/pkg/reconciler/kubernetes/tektonconfig/pipeline/pipeline.go b/pkg/reconciler/kubernetes/tektonconfig/pipeline/pipeline.go
index 41e85651b..3f9096c55 100644
--- a/pkg/reconciler/kubernetes/tektonconfig/pipeline/pipeline.go
+++ b/pkg/reconciler/kubernetes/tektonconfig/pipeline/pipeline.go
@@ -52,10 +52,12 @@ func ensureTektonPipelineExists(clients op.TektonPipelineInterface, config *v1al
 	if err == nil {
 		// if the pipeline spec is changed then update the instance
 		if config.Spec.TargetNamespace != tpCR.Spec.TargetNamespace ||
-			!reflect.DeepEqual(tpCR.Spec.PipelineProperties, config.Spec.Pipeline.PipelineProperties) {
+			!reflect.DeepEqual(tpCR.Spec.PipelineProperties, config.Spec.Pipeline.PipelineProperties) ||
+			!reflect.DeepEqual(tpCR.Spec.Config, config.Spec.Config) {
 
 			tpCR.Spec.TargetNamespace = config.Spec.TargetNamespace
 			tpCR.Spec.PipelineProperties = config.Spec.Pipeline.PipelineProperties
+			tpCR.Spec.Config = config.Spec.Config
 
 			return clients.Update(context.TODO(), tpCR, metav1.UpdateOptions{})
 		}
@@ -72,6 +74,7 @@ func ensureTektonPipelineExists(clients op.TektonPipelineInterface, config *v1al
 					TargetNamespace: config.Spec.TargetNamespace,
 				},
 				PipelineProperties: config.Spec.Pipeline.PipelineProperties,
+				Config:             config.Spec.Config,
 			},
 		}
 		return clients.Create(context.TODO(), tpCR, metav1.CreateOptions{})
diff --git a/pkg/reconciler/kubernetes/tektonconfig/trigger/trigger.go b/pkg/reconciler/kubernetes/tektonconfig/trigger/trigger.go
index 4705c5c1b..725dc78d4 100644
--- a/pkg/reconciler/kubernetes/tektonconfig/trigger/trigger.go
+++ b/pkg/reconciler/kubernetes/tektonconfig/trigger/trigger.go
@@ -21,6 +21,7 @@ import (
 	"errors"
 	"fmt"
 	"log"
+	"reflect"
 
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
 
@@ -36,7 +37,7 @@ import (
 
 func CreateTriggerCR(instance v1alpha1.TektonComponent, client operatorv1alpha1.OperatorV1alpha1Interface) error {
 	configInstance := instance.(*v1alpha1.TektonConfig)
-	if _, err := ensureTektonTriggerExists(client.TektonTriggers(), configInstance.Spec.TargetNamespace); err != nil {
+	if _, err := ensureTektonTriggerExists(client.TektonTriggers(), configInstance); err != nil {
 		return errors.New(err.Error())
 	}
 	if _, err := waitForTektonTriggerState(client.TektonTriggers(), common.TriggerResourceName,
@@ -47,9 +48,19 @@ func CreateTriggerCR(instance v1alpha1.TektonComponent, client operatorv1alpha1.
 	return nil
 }
 
-func ensureTektonTriggerExists(clients op.TektonTriggerInterface, targetNS string) (*v1alpha1.TektonTrigger, error) {
+func ensureTektonTriggerExists(clients op.TektonTriggerInterface, config *v1alpha1.TektonConfig) (*v1alpha1.TektonTrigger, error) {
 	ttCR, err := GetTrigger(clients, common.TriggerResourceName)
 	if err == nil {
+		// if the trigger spec is changed then update the instance
+		if config.Spec.TargetNamespace != ttCR.Spec.TargetNamespace ||
+			!reflect.DeepEqual(ttCR.Spec.Config, config.Spec.Config) {
+
+			ttCR.Spec.TargetNamespace = config.Spec.TargetNamespace
+			ttCR.Spec.Config = config.Spec.Config
+
+			return clients.Update(context.TODO(), ttCR, metav1.UpdateOptions{})
+		}
+
 		return ttCR, err
 	}
 	if apierrs.IsNotFound(err) {
@@ -59,8 +70,9 @@ func ensureTektonTriggerExists(clients op.TektonTriggerInterface, targetNS strin
 			},
 			Spec: v1alpha1.TektonTriggerSpec{
 				CommonSpec: v1alpha1.CommonSpec{
-					TargetNamespace: targetNS,
+					TargetNamespace: config.Spec.TargetNamespace,
 				},
+				Config: config.Spec.Config,
 			},
 		}
 		return clients.Create(context.TODO(), ttCR, metav1.CreateOptions{})
diff --git a/pkg/reconciler/kubernetes/tektondashboard/tektondashboard.go b/pkg/reconciler/kubernetes/tektondashboard/tektondashboard.go
index 5f462dc00..44f9ae0cc 100644
--- a/pkg/reconciler/kubernetes/tektondashboard/tektondashboard.go
+++ b/pkg/reconciler/kubernetes/tektondashboard/tektondashboard.go
@@ -139,6 +139,7 @@ func (r *Reconciler) transform(ctx context.Context, manifest *mf.Manifest, comp
 	instance := comp.(*v1alpha1.TektonDashboard)
 	extra := []mf.Transformer{
 		common.ApplyProxySettings,
+		common.AddConfiguration(instance.Spec.Config),
 	}
 	extra = append(extra, r.extension.Transformers(instance)...)
 	return common.Transform(ctx, manifest, instance, extra...)
diff --git a/pkg/reconciler/kubernetes/tektonpipeline/tektonpipeline.go b/pkg/reconciler/kubernetes/tektonpipeline/tektonpipeline.go
index 972d00200..374cbd965 100644
--- a/pkg/reconciler/kubernetes/tektonpipeline/tektonpipeline.go
+++ b/pkg/reconciler/kubernetes/tektonpipeline/tektonpipeline.go
@@ -153,6 +153,7 @@ func (r *Reconciler) transform(ctx context.Context, manifest *mf.Manifest, comp
 		common.ApplyProxySettings,
 		common.DeploymentImages(images),
 		common.InjectLabelOnNamespace(proxyLabel),
+		common.AddConfiguration(pipeline.Spec.Config),
 	}
 	trns = append(trns, extra...)
 	return common.Transform(ctx, manifest, instance, trns...)
diff --git a/pkg/reconciler/kubernetes/tektontrigger/tektontrigger.go b/pkg/reconciler/kubernetes/tektontrigger/tektontrigger.go
index de4736cc7..2a67a2d9c 100644
--- a/pkg/reconciler/kubernetes/tektontrigger/tektontrigger.go
+++ b/pkg/reconciler/kubernetes/tektontrigger/tektontrigger.go
@@ -141,6 +141,7 @@ func (r *Reconciler) transform(ctx context.Context, manifest *mf.Manifest, comp
 	extra := []mf.Transformer{
 		common.ApplyProxySettings,
 		common.DeploymentImages(triggerImages),
+		common.AddConfiguration(instance.Spec.Config),
 	}
 	trns = append(trns, extra...)
 	return common.Transform(ctx, manifest, instance, trns...)
diff --git a/pkg/reconciler/openshift/tektonconfig/extension/addon.go b/pkg/reconciler/openshift/tektonconfig/extension/addon.go
index 8772dd5d0..c72d91503 100644
--- a/pkg/reconciler/openshift/tektonconfig/extension/addon.go
+++ b/pkg/reconciler/openshift/tektonconfig/extension/addon.go
@@ -49,9 +49,13 @@ func CreateAddonCR(instance v1alpha1.TektonComponent, client operatorv1alpha1.Op
 func ensureTektonAddonExists(clients op.TektonAddonInterface, config *v1alpha1.TektonConfig) (*v1alpha1.TektonAddon, error) {
 	taCR, err := GetAddon(clients, common.AddonResourceName)
 	if err == nil {
-		// If addon params are changed in TektonConfig spec, then only update the Addon CR
-		if !reflect.DeepEqual(config.Spec.Addon.Params, taCR.Spec.Params) {
+		// if the addon spec is changed then update the instance
+		if config.Spec.TargetNamespace != taCR.Spec.TargetNamespace ||
+			!reflect.DeepEqual(config.Spec.Addon.Params, taCR.Spec.Params) {
+
+			taCR.Spec.TargetNamespace = config.Spec.TargetNamespace
 			taCR.Spec.Params = config.Spec.Addon.Params
+
 			updated, err := clients.Update(context.TODO(), taCR, metav1.UpdateOptions{})
 			if err != nil {
 				return nil, err


Test patch:
diff --git a/pkg/reconciler/common/testdata/test-add-configurations.yaml b/pkg/reconciler/common/testdata/test-add-configurations.yaml
new file mode 100644
index 000000000..10e220aa1
--- /dev/null
+++ b/pkg/reconciler/common/testdata/test-add-configurations.yaml
@@ -0,0 +1,26 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: controller
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      run: test
+  template:
+    metadata:
+      labels:
+        run: test
+    spec:
+      containers:
+        - image: busybox
+          name: controller-deployment
+          args: [
+            "-bash-image", "busybox",
+            "-nop=nop"
+          ]
+        - image: busybox
+          name: sidecar
+          args: [
+            "-git", "git"
+          ]
\ No newline at end of file
diff --git a/pkg/reconciler/common/transformers_test.go b/pkg/reconciler/common/transformers_test.go
index e25e0cf3f..e45cfd3d3 100644
--- a/pkg/reconciler/common/transformers_test.go
+++ b/pkg/reconciler/common/transformers_test.go
@@ -28,6 +28,7 @@ import (
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
 	"gotest.tools/v3/assert"
 	appsv1 "k8s.io/api/apps/v1"
+	"k8s.io/api/apps/v1beta1"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -454,3 +455,34 @@ func TestInjectLabelOnNamespace(t *testing.T) {
 		}
 	})
 }
+
+func TestAddConfiguration(t *testing.T) {
+
+	testData := path.Join("testdata", "test-add-configurations.yaml")
+	manifest, err := mf.ManifestFrom(mf.Recursive(testData))
+	assertNoEror(t, err)
+
+	config := v1alpha1.Config{
+		NodeSelector: map[string]string{
+			"foo": "bar",
+		},
+		Tolerations: []corev1.Toleration{
+			{
+				Key:      "foo",
+				Operator: "equals",
+				Value:    "bar",
+				Effect:   "noSchedule",
+			},
+		},
+	}
+
+	manifest, err = manifest.Transform(AddConfiguration(config))
+	assertNoEror(t, err)
+
+	d := &v1beta1.Deployment{}
+	err = runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.Resources()[0].Object, d)
+	assertNoEror(t, err)
+
+	assert.Equal(t, d.Spec.Template.Spec.NodeSelector["foo"], config.NodeSelector["foo"])
+	assert.Equal(t, d.Spec.Template.Spec.Tolerations[0].Key, config.Tolerations[0].Key)
+}