Repository: redhat-developer/service-binding-operator
Pull request #881 (2021-02-24 15:52:22)

Consolidate roles landing into bundle
* Several roles were bound to a wrong service account, fixed to use `service-binding-operator`
* we are not protecting /metric endpoints for now, hence the auth proxy roles are removed from the bundle
* service binding viewer and editor clusterroles added to the bundle so that cluster roles can make use of them
  and enable appropriate users/service-accounts to manage service bindings

openshift-ci-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 **pedjak** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @pedjak` 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=redhat-developer%2Fservice-binding-operator).

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

- **[OWNERS](https://github.com/redhat-developer/service-binding-operator/blob/master/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":["pedjak"]} -->

Patch:
diff --git a/Makefile b/Makefile
index 6ae348a9..3856871f 100644
--- a/Makefile
+++ b/Makefile
@@ -9,6 +9,7 @@ GIT_COMMIT_ID ?= $(shell git rev-parse --short=8 HEAD)
 OPERATOR_REGISTRY ?= quay.io
 OPERATOR_REPO_REF ?= $(OPERATOR_REGISTRY)/redhat-developer/servicebinding-operator
 OPERATOR_IMAGE_REF ?= $(OPERATOR_REPO_REF):$(GIT_COMMIT_ID)
+OPERATOR_IMAGE_SHA_REF ?= $(shell $(CONTAINER_RUNTIME) inspect --format='{{index .RepoDigests 0}}' $(OPERATOR_IMAGE_REF))
 OPERATOR_BUNDLE_IMAGE_REF ?= $(OPERATOR_REPO_REF):bundle-$(VERSION)-$(GIT_COMMIT_ID)
 OPERATOR_INDEX_IMAGE_REF ?= $(OPERATOR_REPO_REF):index
 
@@ -154,7 +155,7 @@ vet:
 # Generate bundle manifests and metadata, then validate generated files.
 bundle: manifests kustomize push-image
 #	operator-sdk generate kustomize manifests -q
-	cd config/manager && $(KUSTOMIZE) edit set image controller=$(shell $(CONTAINER_RUNTIME) inspect --format='{{index .RepoDigests 0}}' $(OPERATOR_IMAGE_REF))
+	cd config/manager && $(KUSTOMIZE) edit set image controller=$(OPERATOR_IMAGE_SHA_REF)
 	$(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)
 	operator-sdk bundle validate ./bundle --select-optional name=operatorhub
 
diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml
index a1022b96..b774ebcd 100644
--- a/config/manager/kustomization.yaml
+++ b/config/manager/kustomization.yaml
@@ -12,5 +12,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
 images:
 - name: controller
-  newName: quay.io/redhat-developer/servicebinding-operator
-  newTag: 395e87bc
+  newName: sbo
+  newTag: latest
diff --git a/config/manifests/kustomization.yaml b/config/manifests/kustomization.yaml
index dabb4705..901f9292 100644
--- a/config/manifests/kustomization.yaml
+++ b/config/manifests/kustomization.yaml
@@ -6,8 +6,28 @@ resources:
 patches:
   - target:
       kind: Deployment
-      name: .*
     patch: |-
       - op: replace
         path: /metadata/name
         value: service-binding-operator
+# use dedicated service-binding-operator service account
+# because the operator is usually installed by OLM
+# in a namespace shared with other operators
+  - target:
+      kind: ClusterRoleBinding
+    patch: |-
+      - op: replace
+        path: /subjects/0/name
+        value: service-binding-operator
+  - target:
+      kind: RoleBinding
+    patch: |-
+      - op: replace
+        path: /subjects/0/name
+        value: service-binding-operator
+  - target:
+      kind: Deployment
+    patch: |-
+      - op: replace
+        path: /spec/template/spec/serviceAccountName
+        value: service-binding-operator
diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml
index 66c28338..0cbd9fb7 100644
--- a/config/rbac/kustomization.yaml
+++ b/config/rbac/kustomization.yaml
@@ -3,10 +3,12 @@ resources:
 - role_binding.yaml
 - leader_election_role.yaml
 - leader_election_role_binding.yaml
+- servicebinding_editor_role.yaml
+- servicebinding_viewer_role.yaml
 # Comment the following 4 lines if you want to disable
 # the auth proxy (https://github.com/brancz/kube-rbac-proxy)
 # which protects your /metrics endpoint.
-- auth_proxy_service.yaml
-- auth_proxy_role.yaml
-- auth_proxy_role_binding.yaml
-- auth_proxy_client_clusterrole.yaml
+#- auth_proxy_service.yaml
+#- auth_proxy_role.yaml
+#- auth_proxy_role_binding.yaml
+#- auth_proxy_client_clusterrole.yaml
diff --git a/controllers/binder.go b/controllers/binder.go
index e868e6b8..c57435b7 100644
--- a/controllers/binder.go
+++ b/controllers/binder.go
@@ -2,6 +2,7 @@ package controllers
 
 import (
 	"context"
+	err "errors"
 	"fmt"
 	"path"
 	"strings"
@@ -22,6 +23,9 @@ import (
 	"github.com/redhat-developer/service-binding-operator/pkg/log"
 )
 
+// changeTriggerEnv hijacking environment in order to trigger a change
+const changeTriggerEnv = "ServiceBindingOperatorChangeTriggerEnvVar"
+
 const serviceBindingRootEnvVar = "SERVICE_BINDING_ROOT"
 
 // binder executes the "binding" act of updating different application kinds to use intermediary
@@ -56,14 +60,13 @@ func (f extraFieldsModifierFunc) ModifyExtraFields(u *unstructured.Unstructured)
 // search objects based in Kind/APIVersion, which contain the labels defined in Application.
 func (b *binder) search() (*unstructured.UnstructuredList, error) {
 	// If Application name is present
-	if b.sbr.Spec.Application != nil {
-		if b.sbr.Spec.Application.Name != "" {
-			return b.getApplicationByName()
-		} else if b.sbr.Spec.Application.LabelSelector != nil && b.sbr.Spec.Application.LabelSelector.MatchLabels != nil {
-			return b.getApplicationByLabelSelector()
-		}
+	if b.sbr.Spec.Application.Name != "" {
+		return b.getApplicationByName()
+	} else if b.sbr.Spec.Application.LabelSelector != nil && b.sbr.Spec.Application.LabelSelector.MatchLabels != nil {
+		return b.getApplicationByLabelSelector()
+	} else {
+		return nil, errEmptyApplication
 	}
-	return nil, errEmptyApplication
 }
 
 func (b *binder) getApplicationByName() (*unstructured.UnstructuredList, error) {
@@ -109,44 +112,28 @@ func (b *binder) getApplicationByLabelSelector() (*unstructured.UnstructuredList
 
 // extractSpecVolumes based on volume path, extract it unstructured. It can return error on trying
 // to find data in informed Unstructured object.
-func (b *binder) extractSpecVolumes(obj *unstructured.Unstructured) ([]corev1.Volume, error) {
-	var volumes []corev1.Volume
+func (b *binder) extractSpecVolumes(obj *unstructured.Unstructured) ([]interface{}, error) {
 	log := b.logger.WithValues("Volumes.NestedPath", b.getVolumesPath())
 	log.Debug("Reading volumes definitions...")
-	volumesUnstructured, _, err := unstructured.NestedSlice(obj.Object, b.getVolumesPath()...)
+	volumes, _, err := unstructured.NestedSlice(obj.Object, b.getVolumesPath()...)
 	if err != nil {
 		return nil, err
 	}
-	for _, v := range volumesUnstructured {
-		volume := corev1.Volume{}
-		err := runtime.DefaultUnstructuredConverter.FromUnstructured(v.(map[string]interface{}), &volume)
-		if err != nil {
-			return nil, err
-		}
-		volumes = append(volumes, volume)
-	}
 	return volumes, nil
 }
 
 // updateSpecVolumes execute the inspection and update "volumes" entries in informed spec.
 func (b *binder) updateSpecVolumes(obj *unstructured.Unstructured) error {
-	var volumesUnstructured []interface{}
 	volumes, err := b.extractSpecVolumes(obj)
 	if err != nil {
 		return err
 	}
+
 	volumes, err = b.updateVolumes(volumes)
 	if err != nil {
 		return err
 	}
-	for _, v := range volumes {
-		volume, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&v)
-		if err != nil {
-			return err
-		}
-		volumesUnstructured = append(volumesUnstructured, volume)
-	}
-	if err = unstructured.SetNestedSlice(obj.Object, volumesUnstructured, b.getVolumesPath()...); err != nil {
+	if err = unstructured.SetNestedSlice(obj.Object, volumes, b.getVolumesPath()...); err != nil {
 		return err
 	}
 	return nil
@@ -163,7 +150,7 @@ func (b *binder) removeSpecVolumes(
 		return nil, err
 	}
 	volumes = b.removeVolumes(volumes)
-	if err = unstructured.SetNestedField(obj.Object, volumes, b.getVolumesPath()...); err != nil {
+	if err = unstructured.SetNestedSlice(obj.Object, volumes, b.getVolumesPath()...); err != nil {
 		return nil, err
 	}
 	return obj, nil
@@ -171,39 +158,47 @@ func (b *binder) removeSpecVolumes(
 
 // updateVolumes inspect informed list assuming as []corev1.Volume, and if binding volume is already
 // defined just return the same list, otherwise, appending the binding volume.
-func (b *binder) updateVolumes(volumes []corev1.Volume) ([]corev1.Volume, error) {
+func (b *binder) updateVolumes(volumes []interface{}) ([]interface{}, error) {
 	name := b.sbr.GetName()
 	log := b.logger
+
 	log.Debug("Checking if binding volume is already defined...")
-	if len(volumes) > 0 {
-		for _, v := range volumes {
-			if v.Name == name {
-				if v.Secret.SecretName == b.sbr.Status.Secret {
-					return volumes, nil
-				}
-				v.Secret.SecretName = b.sbr.Status.Secret
-			}
-			v.Name = name
+	for _, v := range volumes {
+		volume, ok := v.(map[string]interface{})
+		if !ok {
+			return nil, err.New("type asserting volume to map of string to interface{} error")
 		}
-	} else {
-		volume := &corev1.Volume{
-			Name: name,
-			VolumeSource: corev1.VolumeSource{
-				Secret: &corev1.SecretVolumeSource{
-					SecretName: b.sbr.Status.Secret,
-				},
-			},
+		if name == volume["name"] {
+			log.Debug("Volume is already defined!")
+			return volumes, nil
 		}
-		volumes = append(volumes, *volume)
 	}
-	return volumes, nil
+
+	log.Debug("Appending new volume.", "Secret.Name", name)
+	bindVolume := &corev1.Volume{
+		Name: name,
+		VolumeSource: corev1.VolumeSource{
+			Secret: &corev1.SecretVolumeSource{
+				SecretName: name,
+			},
+		},
+	}
+
+	// making sure tranforming it back to unstructured before returning
+	u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(bindVolume)
+	if err != nil {
+		return nil, err
+	}
+	return append(volumes, u), nil
 }
 
-// removeVolumes remove the Service Binding volumes from informed list of unstructured volumes.
-func (b *binder) removeVolumes(volumes []corev1.Volume) []corev1.Volume {
-	var cleanVolumes []corev1.Volume
+// removeVolumes remove the bind volumes from informed list of unstructured volumes.
+func (b *binder) removeVolumes(volumes []interface{}) []interface{} {
+	name := b.sbr.GetName()
+	var cleanVolumes []interface{}
 	for _, v := range volumes {
-		if v.Name != b.sbr.GetName() {
+		volume := v.(corev1.Volume)
+		if name != volume.Name {
 			cleanVolumes = append(cleanVolumes, v)
 		}
 	}
@@ -229,7 +224,7 @@ func (b *binder) extractSpecContainers(obj *unstructured.Unstructured) ([]interf
 // updateSecretField extract the specific secret field from
 // the object, and triggers an update.
 func (b *binder) updateSecretField(obj *unstructured.Unstructured) error {
-	return unstructured.SetNestedField(obj.Object, b.sbr.Status.Secret, b.getSecretFieldPath()...)
+	return unstructured.SetNestedField(obj.Object, b.sbr.GetName(), b.getSecretFieldPath()...)
 }
 
 // updateSpecContainers extract containers from object, and trigger update.
@@ -298,6 +293,7 @@ func (b *binder) updateContainers(containers []interface{}) ([]interface{}, erro
 			return nil, err
 		}
 	}
+
 	return containers, nil
 }
 
@@ -344,22 +340,17 @@ func (b *binder) appendEnvVar(
 	return updatedEnvList
 }
 
-// updateEnvFromList based on secret name and list of EnvFromSource instances, making sure secret is
+// appendEnvFrom based on secret name and list of EnvFromSource instances, making sure secret is
 // part of the list or appended.
-func (b *binder) updateEnvFromList(envList []corev1.EnvFromSource, secret string) []corev1.EnvFromSource {
-	var indices []int
-	for k, env := range envList {
-		if env.SecretRef != nil {
-			if env.SecretRef.Name == secret {
-				return envList
-			} else if strings.Contains(env.SecretRef.Name, b.sbr.GetName()) {
-				indices = append(indices, k)
-			}
+func (b *binder) appendEnvFrom(envList []corev1.EnvFromSource, secret string) []corev1.EnvFromSource {
+	for _, env := range envList {
+		if env.SecretRef != nil && env.SecretRef.Name == secret {
+			b.logger.Debug("Directive 'envFrom' is already present!")
+			// secret name is already referenced
+			return envList
 		}
 	}
-	for _, v := range indices {
-		envList = append(envList[:v], envList[v+1:]...)
-	}
+
 	b.logger.Debug("Adding 'envFrom' directive...")
 	return append(envList, corev1.EnvFromSource{
 		SecretRef: &corev1.SecretEnvSource{
@@ -399,23 +390,38 @@ func (b *binder) updateContainer(container interface{}) (map[string]interface{},
 	if err != nil {
 		return nil, err
 	}
+
 	if !b.sbr.Spec.BindAsFiles {
-		c.EnvFrom = b.updateEnvFromList(c.EnvFrom, b.sbr.Status.Secret)
+		c.EnvFrom = b.appendEnvFrom(c.EnvFrom, b.sbr.GetName())
 	}
+
 	// and adding volume mount entries
 	if b.sbr.Spec.BindAsFiles {
+
 		for _, e := range c.Env {
 			if e.Name == serviceBindingRootEnvVar {
 				b.bindingRoot = e.Value
 				break
 			}
 		}
+
 		p, bindingRoot, fixedMountPath := b.mountPath()
 		c.VolumeMounts = b.appendVolumeMounts(c.VolumeMounts, p)
 		if !fixedMountPath {
 			c.Env = b.appendEnvVar(c.Env, serviceBindingRootEnvVar, bindingRoot)
 		}
 	}
+
+	secretRes := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"}
+	existingSecret, err := b.dynClient.Resource(secretRes).Namespace(b.sbr.GetNamespace()).Get(context.TODO(), b.sbr.GetName(), metav1.GetOptions{})
+	if err != nil {
+		return nil, err
+	}
+	// add a special environment variable that is only used to trigger a change in the declaration,
+	// attempting to force a side effect (in case of a Deployment, it would result in its Pods to be
+	// restarted)
+	c.Env = b.appendEnvVar(c.Env, changeTriggerEnv, existingSecret.GetResourceVersion())
+
 	return runtime.DefaultUnstructuredConverter.ToUnstructured(c)
 }
 
@@ -428,7 +434,7 @@ func (b *binder) removeContainer(container interface{}) (map[string]interface{},
 
 	if !b.sbr.Spec.BindAsFiles {
 		// removing intermediary secret, effectively unbinding the application
-		c.EnvFrom = b.removeEnvFrom(c.EnvFrom, b.sbr.Status.Secret)
+		c.EnvFrom = b.removeEnvFrom(c.EnvFrom, b.sbr.GetName())
 	}
 
 	if b.sbr.Spec.BindAsFiles {
@@ -541,25 +547,26 @@ func (b *binder) update(objs *unstructured.UnstructuredList) ([]*unstructured.Un
 		log.Debug("Inspecting object...")
 
 		var err error
-		if b.sbr.Spec.Application.BindingPath != nil {
-			if b.sbr.Spec.Application.BindingPath.SecretPath != "" {
-				err = b.updateSecretField(updatedObj)
-				if err != nil {
-					return nil, err
-				}
+		if b.sbr.Spec.Application.BindingPath.SecretPath != "" {
+			err = b.updateSecretField(updatedObj)
+			if err != nil {
+				return nil, err
 			}
-			if b.sbr.Spec.Application.BindingPath.ContainersPath != "" {
-				err = b.updateSpecContainers(updatedObj)
-				if err != nil {
-					return nil, err
-				}
+		}
+
+		if b.sbr.Spec.Application.BindingPath.ContainersPath != "" {
+			err = b.updateSpecContainers(updatedObj)
+			if err != nil {
+				return nil, err
 			}
 		}
+
 		if b.sbr.Spec.BindAsFiles {
 			if err = b.updateSpecVolumes(updatedObj); err != nil {
 				return nil, err
 			}
 		}
+
 		if specsAreEqual, err := nestedUnstructuredComparison(&obj, updatedObj); err != nil {
 			log.Error(err, "Error comparing previous and updated object")
 			continue
@@ -634,6 +641,7 @@ func (b *binder) unbind() error {
 }
 
 // bind resources to intermediary secret, by searching informed ResourceKind containing the labels
+// in Application, and then updating spec.
 func (b *binder) bind() ([]*unstructured.Unstructured, error) {
 	objs, err := b.search()
 	if err != nil {
diff --git a/controllers/common.go b/controllers/common.go
index 303dc42f..b245a155 100644
--- a/controllers/common.go
+++ b/controllers/common.go
@@ -10,6 +10,10 @@ import (
 const (
 	// clusterServiceVersionKind the name of ClusterServiceVersion kind.
 	clusterServiceVersionKind = "ClusterServiceVersion"
+	// secretResource defines the resource name for Secrets.
+	secretResource = "secrets"
+	// secretKind defines the name of Secret kind.
+	secretKind = "Secret"
 )
 
 // requeueOnNotFound inspect error, if not-found then returns Requeue, otherwise expose the error.
diff --git a/controllers/reconciler.go b/controllers/reconciler.go
index 886d4688..7e3b6c3e 100644
--- a/controllers/reconciler.go
+++ b/controllers/reconciler.go
@@ -176,6 +176,7 @@ func (r *ServiceBindingReconciler) doReconcile(request reconcile.Request) (recon
 		}
 		return requeueError(err)
 	}
+
 	options := &serviceBinderOptions{
 		dynClient:              r.dynClient,
 		detectBindingResources: *sbr.Spec.DetectBindingResources,
diff --git a/controllers/sbrcontroller.go b/controllers/sbrcontroller.go
index a851e528..9006d8b9 100644
--- a/controllers/sbrcontroller.go
+++ b/controllers/sbrcontroller.go
@@ -32,9 +32,9 @@ type ResourceWatcher interface {
 
 // sbrController hold the controller instance and methods for a ServiceBinding.
 type sbrController struct {
-	Controller   controller.Controller // controller-runtime instance
-	Client       dynamic.Interface     // kubernetes dynamic api client
-	typeLookup   K8STypeLookup
+	Controller   controller.Controller            // controller-runtime instance
+	Client       dynamic.Interface                // kubernetes dynamic api client
+	typeLookup 		K8STypeLookup
 	watchingGVKs map[schema.GroupVersionKind]bool // cache to identify GVKs on watch
 	logger       *log.Log                         // logger instance
 }
diff --git a/controllers/secret.go b/controllers/secret.go
new file mode 100644
index 00000000..a898d03c
--- /dev/null
+++ b/controllers/secret.go
@@ -0,0 +1,108 @@
+package controllers
+
+import (
+	"context"
+	"encoding/base64"
+
+	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/client-go/dynamic"
+
+	"github.com/redhat-developer/service-binding-operator/pkg/converter"
+	"github.com/redhat-developer/service-binding-operator/pkg/log"
+)
+
+// secret represents the data collected by this operator, and later handled as a secret.
+type secret struct {
+	logger *log.Log          // logger instance
+	client dynamic.Interface // Kubernetes API client
+	ns     string
+	name   string
+}
+
+// buildResourceClient creates a resource client to handle corev1/secret resource.
+func (s *secret) buildResourceClient() dynamic.ResourceInterface {
+	gvr := corev1.SchemeGroupVersion.WithResource(secretResource)
+	return s.client.Resource(gvr).Namespace(s.ns)
+}
+
+// createOrUpdate will take informed payload and either create a new secret or update an existing
+// one. It can return error when Kubernetes client does.
+func (s *secret) createOrUpdate(payload map[string][]byte, ownerReference metav1.OwnerReference) (*unstructured.Unstructured, error) {
+	logger := s.logger.WithValues("Namespace", s.ns, "Name", s.name)
+	secretObj := &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace:       s.ns,
+			Name:            s.name,
+			OwnerReferences: []metav1.OwnerReference{ownerReference},
+		},
+		Data: payload,
+	}
+
+	gvk := corev1.SchemeGroupVersion.WithKind(secretKind)
+	u, err := converter.ToUnstructuredAsGVK(secretObj, gvk)
+	if err != nil {
+		return nil, err
+	}
+
+	resourceClient := s.buildResourceClient()
+
+	logger.Debug("Attempt to create secret...")
+	existingSecret, err := s.get()
+	if err != nil {
+		if errors.IsNotFound(err) {
+			_, err := resourceClient.Create(context.TODO(), u, metav1.CreateOptions{})
+			if err != nil {
+				logger.Error(err, "Error creating secret")
+				return nil, err
+			}
+			logger.Info("Secret created")
+			return u, nil
+		}
+		return nil, err
+	}
+	existingSecretData, _, _ := unstructured.NestedMap(existingSecret.Object, "data")
+	payloadInterim := make(map[string]interface{})
+	for k, v := range payload {
+		payloadInterim[k] = base64.StdEncoding.EncodeToString(v)
+	}
+	comparisonResult := nestedMapComparison(existingSecretData, payloadInterim)
+	if comparisonResult.Success {
+		logger.Debug("Secret data is same. Skip Update")
+	} else {
+		logger.Info("Secret data is different; update secret", "Diff", comparisonResult.Diff)
+		_, err = resourceClient.Update(context.TODO(), u, metav1.UpdateOptions{})
+		if err != nil {
+			return nil, err
+		}
+	}
+	return u, nil
+}
+
+// get an unstructured object from the secret handled by this component. It can return errors in case
+// the API server does.
+func (s *secret) get() (*unstructured.Unstructured, error) {
+	resourceClient := s.buildResourceClient()
+	u, err := resourceClient.Get(context.TODO(), s.name, metav1.GetOptions{})
+	if err != nil {
+		return nil, err
+	}
+	return u, nil
+}
+
+// newSecret instantiate a new Secret.
+func newSecret(
+	client dynamic.Interface,
+	ns string,
+	name string,
+) *secret {
+	return &secret{
+		logger: log.NewLog("secret"),
+		client: client,
+
+		name: name,
+		ns:   ns,
+	}
+}
diff --git a/controllers/secret/secret.go b/controllers/secret/secret.go
deleted file mode 100644
index e95f9169..00000000
--- a/controllers/secret/secret.go
+++ /dev/null
@@ -1,134 +0,0 @@
-package secret
-
-import (
-	"context"
-	"crypto/sha1"
-	"encoding/hex"
-	"sort"
-
-	corev1 "k8s.io/api/core/v1"
-	"k8s.io/apimachinery/pkg/api/errors"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/client-go/dynamic"
-
-	"github.com/redhat-developer/service-binding-operator/pkg/converter"
-)
-
-const (
-	// secretResource defines the resource name for Secrets.
-	secretResource = "secrets"
-	// secretKind defines the name of Secret kind.
-	secretKind = "Secret"
-)
-
-// buildResourceClient creates a resource client to handle corev1/secret resource.
-func buildResourceClient(client dynamic.Interface, namespace string) dynamic.ResourceInterface {
-	gvr := corev1.SchemeGroupVersion.WithResource(secretResource)
-	return client.Resource(gvr).Namespace(namespace)
-}
-
-// buildSecretHash is a utility function to get a checksum of the resource data
-func buildSecretHash(data map[string][]byte) (string, error) {
-	keys := make([]string, 0, len(data))
-	for k := range data {
-		keys = append(keys, k)
-	}
-	sort.Strings(keys)
-	hash := sha1.New()
-	for _, k := range keys {
-		_, err := hash.Write([]byte(k))
-		if err != nil {
-			return "", err
-		}
-		_, err = hash.Write(data[k])
-		if err != nil {
-			return "", err
-		}
-	}
-	return hex.EncodeToString(hash.Sum(nil)), nil
-}
-
-// WriteServiceBindingSecret will take informed payload and create a new secret
-// It can return error when Kubernetes client does.
-func WriteServiceBindingSecret(
-	client dynamic.Interface,
-	ns string,
-	prefix string,
-	payload map[string][]byte,
-	ownerReference metav1.OwnerReference,
-) (*corev1.Secret, error) {
-	secretHash, err := buildSecretHash(payload)
-	if err != nil {
-		return nil, err
-	}
-
-	secret := &corev1.Secret{
-		ObjectMeta: metav1.ObjectMeta{
-			Namespace:       ns,
-			Name:            prefix + "-" + secretHash,
-			OwnerReferences: []metav1.OwnerReference{ownerReference},
-		},
-		Data: payload,
-	}
-
-	gvk := corev1.SchemeGroupVersion.WithKind(secretKind)
-	u, err := converter.ToUnstructuredAsGVK(secret, gvk)
-	if err != nil {
-		return nil, err
-	}
-
-	resourceClient := buildResourceClient(client, ns)
-	expectedSecret, err := getServiceBindingSecret(resourceClient, secret.Name, ns)
-	if err != nil {
-		if errors.IsNotFound(err) {
-			secretNew, err := resourceClient.Create(context.TODO(), u, metav1.CreateOptions{})
-			if err != nil {
-				return nil, err
-			}
-			s := &corev1.Secret{}
-			err = runtime.DefaultUnstructuredConverter.FromUnstructured(secretNew.Object, s)
-			if err != nil {
-				return nil, err
-			}
-			return s, nil
-		}
-		return nil, err
-	}
-
-	expectedDataHash, err := buildSecretHash(expectedSecret.Data)
-	if err != nil {
-		return nil, err
-	}
-
-	// compare current and existing secret name and data hash
-	if expectedSecret.GetName() != secret.Name || expectedDataHash != secretHash {
-		secretNew, err := resourceClient.Update(context.TODO(), u, metav1.UpdateOptions{})
-		if err != nil {
-			return nil, err
-		}
-		s := &corev1.Secret{}
-		err = runtime.DefaultUnstructuredConverter.FromUnstructured(secretNew.Object, s)
-		if err != nil {
-			return nil, err
-		}
-		return s, nil
-	}
-	return secret, nil
-}
-
-// getServiceBindingSecret an unstructured object from the secret handled by this component. It can return errors in case
-// the API server does.
-func getServiceBindingSecret(resourceClient dynamic.ResourceInterface, name, namespace string) (*corev1.Secret, error) {
-	u, err := resourceClient.Get(context.TODO(), name, metav1.GetOptions{})
-	if err != nil {
-		return nil, err
-	}
-
-	s := &corev1.Secret{}
-	err = runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, s)
-	if err != nil {
-		return nil, err
-	}
-	return s, nil
-}
diff --git a/controllers/service.go b/controllers/service.go
index 3ef78f1f..22d2d042 100644
--- a/controllers/service.go
+++ b/controllers/service.go
@@ -194,7 +194,7 @@ func getOwnedResources(
 		for idx, item := range lst.Items {
 			owners := item.GetOwnerReferences()
 			for _, owner := range owners {
-				if owner.UID != "" && owner.UID == uid {
+				if owner.UID == uid {
 					resources = append(resources, &lst.Items[idx])
 				}
 			}
diff --git a/controllers/servicebinder.go b/controllers/servicebinder.go
index 4ad14b6d..e95ddf11 100644
--- a/controllers/servicebinder.go
+++ b/controllers/servicebinder.go
@@ -14,8 +14,6 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/reconcile"
 
 	"github.com/redhat-developer/service-binding-operator/api/v1alpha1"
-	"github.com/redhat-developer/service-binding-operator/controllers/secret"
-
 	"github.com/redhat-developer/service-binding-operator/pkg/converter"
 	"github.com/redhat-developer/service-binding-operator/pkg/log"
 )
@@ -92,6 +90,8 @@ type serviceBinder struct {
 	objects []*unstructured.Unstructured
 	// sbr is the ServiceBinding associated with binding.
 	sbr *v1alpha1.ServiceBinding
+	// secret is the secret associated with the Service Binding.
+	secret *secret
 }
 
 // updateServiceBinding execute update API call on a SBR request. It can return errors from
@@ -292,13 +292,7 @@ func (b *serviceBinder) bind() (reconcile.Result, error) {
 
 	b.logger.Debug("Saving data on intermediary secret...")
 
-	secretObj, err := secret.WriteServiceBindingSecret(
-		b.dynClient,
-		b.sbr.GetNamespace(),
-		b.sbr.GetName(),
-		b.envVars,
-		b.sbr.AsOwnerReference(),
-	)
+	secretObj, err := b.secret.createOrUpdate(b.envVars, b.sbr.AsOwnerReference())
 	if err != nil {
 		b.logger.Error(err, "On saving secret data..")
 		return b.onError(err, b.sbr, sbrStatus, nil)
@@ -311,12 +305,6 @@ func (b *serviceBinder) bind() (reconcile.Result, error) {
 		Reason: v1alpha1.BindingInjectedReason,
 	})
 
-	// updating status of request instance
-	_, err = b.updateStatusServiceBinding(b.sbr, sbrStatus)
-	if err != nil {
-		return requeueOnConflict(err)
-	}
-	ensureDefaults(b.sbr.Spec.Application)
 	if isApplicationEmpty(b.sbr.Spec.Application) {
 		meta.SetStatusCondition(&sbrStatus.Conditions, metav1.Condition{
 			Type:    v1alpha1.InjectionReady,
@@ -431,6 +419,14 @@ func buildServiceBinder(
 		return nil, err
 	}
 
+	// FIXME(isuttonl): review whether it is possible to move Secret.Commit() and Secret.Delete() to
+	// ServiceBinder.
+	secret := newSecret(
+		options.dynClient,
+		options.sbr.GetNamespace(),
+		options.sbr.GetName(),
+	)
+
 	// FIXME(isuttonl): review whether binder can be lazily created in Bind() and Unbind(); also
 	// consider renaming to ResourceBinder
 	binder := newBinder(
@@ -449,6 +445,7 @@ func buildServiceBinder(
 		sbr:       options.sbr,
 		objects:   options.objects,
 		envVars:   options.binding.envVars,
+		secret:    secret,
 	}, nil
 }
 
diff --git a/docs/User_Guide.md b/docs/User_Guide.md
index 25a3dc41..1d3bb44e 100644
--- a/docs/User_Guide.md
+++ b/docs/User_Guide.md
@@ -530,7 +530,7 @@ kind: AppConfig
 metadata:
     name: example-appconfig
 spec:
-    secret: some-value-72ddc0c540ab3a290e138726940591debf14c581
+    secret: some-value
 ```
 
 In the above CR, the secret path is at `spec.secret`.  You can specify
@@ -570,7 +570,7 @@ kind: AppConfig
 metadata:
     name: example-appconfig
 spec:
-    secret: binding-request-72ddc0c540ab3a290e138726940591debf14c581
+    secret: binding-request
 ```
 
 # Binding Metadata in Annotations
diff --git a/examples/java_postgresql_customvar/README.md b/examples/java_postgresql_customvar/README.md
index bca46c85..0cb5eef1 100644
--- a/examples/java_postgresql_customvar/README.md
+++ b/examples/java_postgresql_customvar/README.md
@@ -242,7 +242,7 @@ status:
     lastTransitionTime: "2020-08-12T06:39:13Z"
     status: "True"
     type: InjectionReady
-  secret: binding-request-72ddc0c540ab3a290e138726940591debf14c581
+  secret: binding-request
 ```
 
 where
@@ -272,7 +272,7 @@ Conditions can have the following type, status and reason:
 
 ### Check secret injection into the application deployment
 
-When `ServiceBinding` was created the Service Binding Operator's controller injected the DB connection information into the application's `Deployment` as environment variables through the secret `binding-request-72ddc0c540ab3a290e138726940591debf14c581`:
+When the `ServiceBinding` was created the Service Binding Operator's controller injected the DB connection information into the application's `Deployment` as environment variables via an intermediate `Secret` called `binding-request`:
 
 ```shell
 kubectl get deployment java-app -n service-binding-demo -o yaml
@@ -285,7 +285,7 @@ spec:
       containers:
         - envFrom:
           - secretRef:
-              name: binding-request-72ddc0c540ab3a290e138726940591debf14c581
+              name: binding-request
 ```
 
 ### Check the environment variable creation in the application pod
diff --git a/examples/knative_postgresql_customvar/README.md b/examples/knative_postgresql_customvar/README.md
index 34f51c7b..b7dfa0c9 100644
--- a/examples/knative_postgresql_customvar/README.md
+++ b/examples/knative_postgresql_customvar/README.md
@@ -190,7 +190,7 @@ That causes the application to be re-deployed.
 Once the new version is up, go to the application's route to check the UI. Now, it works!
 
 When the `ServiceBinding` was created the Service Binding Operator's controller injected the DB connection information into the
-application as environment variables via an intermediate `Secret` called `binding-request-72ddc0c540ab3a290e138726940591debf14c581`:
+application as environment variables via an intermediate `Secret` called `binding-request`:
 
 ```shell
 kubectl get servicebinding binding-request -o yaml
@@ -202,9 +202,8 @@ spec:
       containers:
         - envFrom:
           - secretRef:
-              name: binding-request-72ddc0c540ab3a290e138726940591debf14c581
+              name: binding-request
 ```
-The name of the binding secret has the format `Service Binding name + hash of the secret content`. So the name of binding secret changes when the content of binding secret changes.
 
 #### Check the status of Service Binding
 
@@ -229,7 +228,7 @@ status:
     lastTransitionTime: "2020-10-15T13:23:23Z"
     status: "True"
     type: InjectionReady
-  secret: binding-request-72ddc0c540ab3a290e138726940591debf14c581
+  secret: binding-request
 ```
 
 where
diff --git a/examples/multiple_services/README.md b/examples/multiple_services/README.md
index a3e2944d..484822bf 100644
--- a/examples/multiple_services/README.md
+++ b/examples/multiple_services/README.md
@@ -204,7 +204,7 @@ status:
     lastTransitionTime: "2020-10-15T13:23:23Z"
     status: "True"
     type: InjectionReady
-  secret: binding-request-72ddc0c540ab3a290e138726940591debf14c581
+  secret: binding-request
 ```
 
 where
diff --git a/examples/nodejs_awsrds_varprefix/README.md b/examples/nodejs_awsrds_varprefix/README.md
index e7bd9bd0..1ad2d148 100644
--- a/examples/nodejs_awsrds_varprefix/README.md
+++ b/examples/nodejs_awsrds_varprefix/README.md
@@ -363,7 +363,7 @@ status:
     lastTransitionTime: "2020-10-15T13:23:23Z"
     status: "True"
     type: InjectionReady
-  secret: mydb.to.shell-app-72ddc0c540ab3a290e138726940591debf14c581
+  secret: mydb.to.shell-app
 ```
 
 where
diff --git a/examples/nodejs_postgresql/README.md b/examples/nodejs_postgresql/README.md
index 4fc1cdf1..07d0d849 100644
--- a/examples/nodejs_postgresql/README.md
+++ b/examples/nodejs_postgresql/README.md
@@ -185,7 +185,7 @@ status:
     lastTransitionTime: "2020-10-15T13:23:23Z"
     status: "True"
     type: InjectionReady
-  secret: binding-request-72ddc0c540ab3a290e138726940591debf14c581
+  secret: binding-request
 ```
 
 where
diff --git a/examples/pod_spec_path/README.md b/examples/pod_spec_path/README.md
index 199ebc73..0c753eca 100644
--- a/examples/pod_spec_path/README.md
+++ b/examples/pod_spec_path/README.md
@@ -111,7 +111,7 @@ spec:
 EOD
 ```
 
-Check the secret `binding-request-sample-72ddc0c540ab3a290e138726940591debf14c581` has been injected:
+Check the secret `binding-request-sample` has been injected:
 
 ```shell
 kubectl get appconfigs.stable.example.com demo-appconfig -o yaml
diff --git a/examples/route_k8s_resource/README.md b/examples/route_k8s_resource/README.md
index cdd81ce5..75ea7901 100644
--- a/examples/route_k8s_resource/README.md
+++ b/examples/route_k8s_resource/README.md
@@ -141,13 +141,13 @@ status:
     lastTransitionTime: "2020-10-19T11:35:37Z"
     status: "True"
     type: InjectionReady
-  secret: binding-request-72ddc0c540ab3a290e138726940591debf14c581
+  secret: binding-request
 ```
 
-Check the contents of `Secret` - `binding-request-72ddc0c540ab3a290e138726940591debf14c581` by executing:
+Check the contents of `Secret` - `binding-request` by executing:
 
 ```shell
-kubectl get secrets binding-request-72ddc0c540ab3a290e138726940591debf14c581 -n service-binding-demo -o yaml
+kubectl get secrets binding-request -n service-binding-demo -o yaml
 ```
 
 for the following result:
@@ -159,7 +159,7 @@ data:
 kind: Secret
 metadata:
   ...
-  name: binding-request-72ddc0c540ab3a290e138726940591debf14c581
+  name: binding-request
   namespace: service-binding-demo
   ...
 ...
@@ -168,7 +168,7 @@ metadata:
 The secret value is actually encoded with base64 so to get the actual value we need to decode it properly:
 
 ```shell
-kubectl get secret binding-request-72ddc0c540ab3a290e138726940591debf14c581 -n service-binding-demo -o jsonpath='{.data.ROUTE_HOST}' | base64 --decode
+kubectl get secret binding-request -n service-binding-demo -o jsonpath='{.data.ROUTE_HOST}' | base64 --decode
 ```
 for the following result:
 ```


Test patch:
diff --git a/controllers/binder_test.go b/controllers/binder_test.go
index 243b8a02..1ee0f311 100644
--- a/controllers/binder_test.go
+++ b/controllers/binder_test.go
@@ -12,6 +12,7 @@ import (
 	"github.com/stretchr/testify/require"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
+
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
@@ -25,6 +26,16 @@ func init() {
 	log.SetLogger(zap.New(zap.UseDevMode((true))))
 }
 
+// getEnvVar returns an EnvVar with given name if exists in the given envVars.
+func getEnvVar(envVars []corev1.EnvVar, name string) *corev1.EnvVar {
+	for _, v := range envVars {
+		if v.Name == name {
+			return &v
+		}
+	}
+	return nil
+}
+
 func TestBindingCustomSecretPath(t *testing.T) {
 	ns := "custombinder"
 	name := "service-binding-request-custom"
@@ -67,7 +78,7 @@ func TestBindingCustomSecretPath(t *testing.T) {
 		customSecretInMeta, found, err := unstructured.NestedFieldCopy(obj.Object, customSecretPathSlice...)
 		require.NoError(t, err)
 		require.True(t, found)
-		require.Equal(t, binderForsbrSecretPath.sbr.Status.Secret, customSecretInMeta)
+		require.Equal(t, name, customSecretInMeta)
 	})
 }
 
@@ -132,7 +143,7 @@ func TestBinderNew(t *testing.T) {
 		require.Equal(t, 1, len(list.Items))
 	})
 
-	t.Run("updateEnvFrom-removeEnvFrom-with-empty-envFrom", func(t *testing.T) {
+	t.Run("appendEnvFrom-removeEnvFrom-with-empty-envFrom", func(t *testing.T) {
 		binder := newBinder(
 			context.TODO(),
 			f.FakeDynClient(),
@@ -145,7 +156,7 @@ func TestBinderNew(t *testing.T) {
 		d := mocks.DeploymentMock("binder", "binder", map[string]string{})
 		envFrom := d.Spec.Template.Spec.Containers[0].EnvFrom
 
-		list := binder.updateEnvFromList(envFrom, secretName)
+		list := binder.appendEnvFrom(envFrom, secretName)
 		require.Equal(t, 1, len(list))
 		require.Equal(t, secretName, list[0].SecretRef.Name)
 
@@ -153,7 +164,7 @@ func TestBinderNew(t *testing.T) {
 		require.Equal(t, 0, len(list))
 	})
 
-	t.Run("updateEnvFrom-removeEnvFrom-with-configMapRef", func(t *testing.T) {
+	t.Run("appendEnvFrom-removeEnvFrom-with-configMapRef", func(t *testing.T) {
 		binder := newBinder(
 			context.TODO(),
 			f.FakeDynClient(),
@@ -174,7 +185,7 @@ func TestBinderNew(t *testing.T) {
 			},
 		})
 
-		list := binder.updateEnvFromList(envFrom, secretName)
+		list := binder.appendEnvFrom(envFrom, secretName)
 		require.Equal(t, 2, len(list))
 		require.Equal(t, configMapName, list[0].ConfigMapRef.Name)
 		require.Equal(t, secretName, list[1].SecretRef.Name)
@@ -218,6 +229,11 @@ func TestBinderNew(t *testing.T) {
 		require.NoError(t, err)
 		require.Len(t, updatedObjects, 1)
 
+		// make sure SBR annonation is added
+		deployment := appsv1.Deployment{}
+		err = runtime.DefaultUnstructuredConverter.FromUnstructured(updatedObjects[0].Object, &deployment)
+		require.NoError(t, err)
+
 		containers, found, err := unstructured.NestedSlice(updatedObjects[0].Object, binder.getContainersPath()...)
 		require.NoError(t, err)
 		require.True(t, found)
@@ -228,11 +244,18 @@ func TestBinderNew(t *testing.T) {
 		err = runtime.DefaultUnstructuredConverter.FromUnstructured(u, &c)
 		require.NoError(t, err)
 
+		// special env-var should exist to trigger a side effect such as Pod restart when the
+		// intermediate secret has been modified
+		envVar := getEnvVar(c.Env, changeTriggerEnv)
+		require.NotNil(t, envVar)
+		require.NotEmpty(t, envVar.Value)
+
 		uSecret, err := fakeDynClient.Resource(secretsGVR).Namespace(ns).Get(context.TODO(), name, metav1.GetOptions{})
 		require.NoError(t, err)
 		s := corev1.Secret{}
 		err = runtime.DefaultUnstructuredConverter.FromUnstructured(uSecret.Object, &s)
 		require.NoError(t, err)
+		require.Equal(t, s.ObjectMeta.ResourceVersion, envVar.Value)
 	})
 
 	t.Run("update with extra modifier present", func(t *testing.T) {
@@ -376,28 +399,6 @@ func TestBindingWithDeploymentConfig(t *testing.T) {
 
 }
 
-func TestBindEmptyApplication(t *testing.T) {
-	ns := "binder"
-	f := mocks.NewFake(t, ns)
-
-	name := "service-binding-empty-application"
-	sbr := f.AddMockedServiceBinding(name, nil, "backingServiceResourceRef", "", deploymentsGVR, nil)
-
-	binder1 := newBinder(
-		context.TODO(),
-		f.FakeDynClient(),
-		sbr,
-		&ServiceBindingReconciler{restMapper: testutils.BuildTestRESTMapper()},
-	)
-	require.NotNil(t, binder1)
-
-	t.Run("Binder search should return errEmptyApplication error for service binding with empty application", func(t *testing.T) {
-		applicationList, err := binder1.search()
-		assert.Error(t, errEmptyApplication, err)
-		assert.Empty(t, applicationList)
-	})
-}
-
 func TestBindTwoApplications(t *testing.T) {
 	ns := "binder"
 	f := mocks.NewFake(t, ns)
diff --git a/controllers/reconciler_test.go b/controllers/reconciler_test.go
index 6061f670..089cb278 100644
--- a/controllers/reconciler_test.go
+++ b/controllers/reconciler_test.go
@@ -184,6 +184,7 @@ func TestReconcilerReconcileUsingSecret(t *testing.T) {
 		require.Equal(t, 1, len(containers))
 		require.Equal(t, 1, len(containers[0].EnvFrom))
 		require.NotNil(t, containers[0].EnvFrom[0].SecretRef)
+		require.Equal(t, reconcilerName, containers[0].EnvFrom[0].SecretRef.Name)
 
 		namespacedName = types.NamespacedName{Namespace: reconcilerNs, Name: reconcilerName}
 		sbrOutput, err := r.getServiceBinding(namespacedName)
@@ -193,15 +194,7 @@ func TestReconcilerReconcileUsingSecret(t *testing.T) {
 		requireConditionPresentAndTrue(t, v1alpha1.InjectionReady, sbrOutput.Status.Conditions)
 		requireConditionPresentAndTrue(t, v1alpha1.BindingReady, sbrOutput.Status.Conditions)
 
-		var envList []corev1.EnvFromSource
-		envList = append(envList, corev1.EnvFromSource{
-			SecretRef: &corev1.SecretEnvSource{
-				LocalObjectReference: corev1.LocalObjectReference{
-					Name: sbrOutput.Status.Secret,
-				},
-			},
-		})
-		require.Contains(t, containers[0].EnvFrom, envList[0])
+		require.Equal(t, reconcilerName, sbrOutput.Status.Secret)
 
 		require.Equal(t, 1, len(sbrOutput.Status.Applications))
 		expectedStatus := v1alpha1.Ref{
@@ -308,6 +301,7 @@ func TestServiceNotFound(t *testing.T) {
 	requireConditionPresentAndTrue(t, v1alpha1.InjectionReady, sbrOutput2.Status.Conditions)
 	requireConditionPresentAndTrue(t, v1alpha1.BindingReady, sbrOutput2.Status.Conditions)
 
+	require.Equal(t, reconcilerName, sbrOutput2.Status.Secret)
 	require.Equal(t, 1, len(sbrOutput2.Status.Applications))
 }
 
@@ -365,6 +359,7 @@ func TestApplicationNotFound(t *testing.T) {
 	requireConditionPresentAndTrue(t, v1alpha1.InjectionReady, sbrOutput2.Status.Conditions)
 	requireConditionPresentAndTrue(t, v1alpha1.BindingReady, sbrOutput2.Status.Conditions)
 
+	require.Equal(t, reconcilerName, sbrOutput2.Status.Secret)
 	require.Equal(t, 1, len(sbrOutput2.Status.Applications))
 }
 
@@ -416,10 +411,13 @@ func TestReconcilerUpdateCredentials(t *testing.T) {
 	requireConditionPresentAndTrue(t, v1alpha1.InjectionReady, sbrOutput3.Status.Conditions)
 	requireConditionPresentAndTrue(t, v1alpha1.BindingReady, sbrOutput3.Status.Conditions)
 
+	require.Equal(t, reconcilerName, sbrOutput3.Status.Secret)
 	require.Equal(t, s.Data["password"], []byte("abc123"))
 	require.Equal(t, 1, len(sbrOutput3.Status.Applications))
-	fetchSecret, err := fakeDynClient.Resource(secretsGVR).Namespace(updated.GetNamespace()).Get(context.TODO(), sbrOutput3.Status.Secret, metav1.GetOptions{})
+	require.Equal(t, reconcilerName, sbrOutput3.Status.Secret)
+	fetchSecret, err := fakeDynClient.Resource(secretsGVR).Namespace(updated.GetNamespace()).Get(context.TODO(), reconcilerName, metav1.GetOptions{})
 	require.NoError(t, err)
+	require.Equal(t, fetchSecret.GetName(), reconcilerName)
 	require.Equal(t, fetchSecret.GetResourceVersion(), "")
 	require.Equal(t, 1, len(sbrOutput3.Status.Applications))
 }
@@ -469,6 +467,7 @@ func TestReconcilerReconcileWithConflictingAppSelc(t *testing.T) {
 		requireConditionPresentAndTrue(t, v1alpha1.InjectionReady, sbrOutput.Status.Conditions)
 		requireConditionPresentAndTrue(t, v1alpha1.BindingReady, sbrOutput.Status.Conditions)
 
+		require.Equal(t, reconcilerName, sbrOutput.Status.Secret)
 		require.Len(t, sbrOutput.Status.Applications, 1)
 		require.True(t, reflect.DeepEqual(expectedStatus, sbrOutput.Status.Applications[0]))
 	})
@@ -561,7 +560,7 @@ func TestBindTwoSbrsWithSingleApplication(t *testing.T) {
 
 		// Get sbr after reconciling
 		namespacedName := types.NamespacedName{Namespace: reconcilerNs, Name: sbrName1}
-		sbrOutput1, err := r.getServiceBinding(namespacedName)
+		sbrOutput, err := r.getServiceBinding(namespacedName)
 		require.NoError(t, err)
 
 		// expected sbr assertion
@@ -572,11 +571,12 @@ func TestBindTwoSbrsWithSingleApplication(t *testing.T) {
 			Name:    applicationResourceRef,
 		}
 
-		requireConditionPresentAndTrue(t, v1alpha1.CollectionReady, sbrOutput1.Status.Conditions)
-		requireConditionPresentAndTrue(t, v1alpha1.InjectionReady, sbrOutput1.Status.Conditions)
-		requireConditionPresentAndTrue(t, v1alpha1.BindingReady, sbrOutput1.Status.Conditions)
-		require.Len(t, sbrOutput1.Status.Applications, 1)
-		require.True(t, reflect.DeepEqual(expectedStatus, sbrOutput1.Status.Applications[0]))
+		requireConditionPresentAndTrue(t, v1alpha1.CollectionReady, sbrOutput.Status.Conditions)
+		requireConditionPresentAndTrue(t, v1alpha1.InjectionReady, sbrOutput.Status.Conditions)
+		requireConditionPresentAndTrue(t, v1alpha1.BindingReady, sbrOutput.Status.Conditions)
+		require.Equal(t, sbrName1, sbrOutput.Status.Secret)
+		require.Len(t, sbrOutput.Status.Applications, 1)
+		require.True(t, reflect.DeepEqual(expectedStatus, sbrOutput.Status.Applications[0]))
 
 		// Reconciling second sbr
 		// Second sbr reconcile request
@@ -594,7 +594,7 @@ func TestBindTwoSbrsWithSingleApplication(t *testing.T) {
 
 		// Get sbr after reconciling
 		namespacedName = types.NamespacedName{Namespace: reconcilerNs, Name: sbrName2}
-		sbrOutput2, err := r.getServiceBinding(namespacedName)
+		sbrOutput, err = r.getServiceBinding(namespacedName)
 		require.NoError(t, err)
 
 		// expected sbr assertion
@@ -605,11 +605,12 @@ func TestBindTwoSbrsWithSingleApplication(t *testing.T) {
 			Name:    applicationResourceRef,
 		}
 
-		requireConditionPresentAndTrue(t, v1alpha1.CollectionReady, sbrOutput2.Status.Conditions)
-		requireConditionPresentAndTrue(t, v1alpha1.InjectionReady, sbrOutput2.Status.Conditions)
-		requireConditionPresentAndTrue(t, v1alpha1.BindingReady, sbrOutput2.Status.Conditions)
-		require.Len(t, sbrOutput2.Status.Applications, 1)
-		require.True(t, reflect.DeepEqual(expectedStatus, sbrOutput2.Status.Applications[0]))
+		requireConditionPresentAndTrue(t, v1alpha1.CollectionReady, sbrOutput.Status.Conditions)
+		requireConditionPresentAndTrue(t, v1alpha1.InjectionReady, sbrOutput.Status.Conditions)
+		requireConditionPresentAndTrue(t, v1alpha1.BindingReady, sbrOutput.Status.Conditions)
+		require.Equal(t, sbrName2, sbrOutput.Status.Secret)
+		require.Len(t, sbrOutput.Status.Applications, 1)
+		require.True(t, reflect.DeepEqual(expectedStatus, sbrOutput.Status.Applications[0]))
 
 		// Get applicationResourceRef deployment
 		resourceClient := r.dynClient.Resource(deploymentsGVR).Namespace(namespacedName.Namespace)
@@ -619,98 +620,10 @@ func TestBindTwoSbrsWithSingleApplication(t *testing.T) {
 		err = runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, dep)
 		require.NoError(t, err)
 
-		var envList []corev1.EnvFromSource
 		// Assert SBR name with secretRef object in containers env var
 		// Expected secretRef=binding-request1
-		bindingSecret1, err := fakeDynClient.Resource(secretsGVR).Namespace(reconcilerNs).Get(context.TODO(), sbrOutput1.Status.Secret, metav1.GetOptions{})
-		require.NoError(t, err)
-		require.Equal(t, sbrOutput1.Status.Secret, bindingSecret1.GetName())
-		envList = append(envList, corev1.EnvFromSource{
-			ConfigMapRef: nil,
-			SecretRef: &corev1.SecretEnvSource{
-				LocalObjectReference: corev1.LocalObjectReference{
-					Name: bindingSecret1.GetName(),
-				},
-			},
-		})
+		require.Equal(t, sbrName1, dep.Spec.Template.Spec.Containers[0].EnvFrom[0].SecretRef.LocalObjectReference.Name)
 		// Expected secretRef=binding-request2
-		bindingSecret2, err := fakeDynClient.Resource(secretsGVR).Namespace(reconcilerNs).Get(context.TODO(), sbrOutput2.Status.Secret, metav1.GetOptions{})
-		require.NoError(t, err)
-		require.Equal(t, sbrOutput2.Status.Secret, bindingSecret2.GetName())
-		envList = append(envList, corev1.EnvFromSource{
-			ConfigMapRef: nil,
-			SecretRef: &corev1.SecretEnvSource{
-				LocalObjectReference: corev1.LocalObjectReference{
-					Name: bindingSecret2.GetName(),
-				},
-			},
-		})
-		require.Contains(t, dep.Spec.Template.Spec.Containers[0].EnvFrom, envList[0])
-		require.Contains(t, dep.Spec.Template.Spec.Containers[0].EnvFrom, envList[1])
+		require.Equal(t, sbrName2, dep.Spec.Template.Spec.Containers[0].EnvFrom[1].SecretRef.LocalObjectReference.Name)
 	})
 }
-
-func TestRepopulateBindingSecretOnExternalUpdate(t *testing.T) {
-	backingServiceResourceRef := "backingService"
-	matchLabels := map[string]string{
-		"connects-to": "database",
-		"environment": "reconciler",
-	}
-	f := mocks.NewFake(t, reconcilerNs)
-	f.AddMockedUnstructuredServiceBinding(reconcilerName, backingServiceResourceRef, "", deploymentsGVR, matchLabels)
-	f.AddMockedUnstructuredCSV("cluster-service-version-list")
-	f.AddMockedUnstructuredDatabaseCRD()
-	f.AddMockedUnstructuredDatabaseCR(backingServiceResourceRef)
-	f.AddMockedUnstructuredDeployment(reconcilerName, matchLabels)
-	f.AddMockedUnstructuredSecret("db-credentials")
-
-	fakeDynClient := f.FakeDynClient()
-	mapper := testutils.BuildTestRESTMapper()
-	r := &ServiceBindingReconciler{dynClient: fakeDynClient, restMapper: mapper, Scheme: f.S}
-	r.resourceWatcher = newFakeResourceWatcher(mapper)
-
-	res, err := r.Reconcile(reconcileRequest())
-	require.NoError(t, err)
-	require.False(t, res.Requeue)
-
-	namespacedName := types.NamespacedName{Namespace: reconcilerNs, Name: reconcilerName}
-	sbr, err := r.getServiceBinding(namespacedName)
-	require.NoError(t, err)
-
-	requireConditionPresentAndTrue(t, v1alpha1.CollectionReady, sbr.Status.Conditions)
-	requireConditionPresentAndTrue(t, v1alpha1.InjectionReady, sbr.Status.Conditions)
-	requireConditionPresentAndTrue(t, v1alpha1.BindingReady, sbr.Status.Conditions)
-
-	bindingSecret, err := fakeDynClient.Resource(secretsGVR).Namespace(reconcilerNs).Get(context.TODO(), sbr.Status.Secret, metav1.GetOptions{})
-	require.NoError(t, err)
-
-	// Update Credentials
-	secret := &corev1.Secret{}
-	err = runtime.DefaultUnstructuredConverter.FromUnstructured(bindingSecret.Object, secret)
-	require.NoError(t, err)
-	bindingData := make(map[string][]byte)
-	bindingData["love"] = []byte("dhriti")
-	secret.Data = bindingData
-
-	obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&secret)
-	require.NoError(t, err)
-	updated := unstructured.Unstructured{Object: obj}
-
-	updatedSecret, err := fakeDynClient.Resource(secretsGVR).Namespace(secret.Namespace).Update(context.TODO(), &updated, metav1.UpdateOptions{})
-	require.NoError(t, err)
-
-	secrett := &corev1.Secret{}
-	err = runtime.DefaultUnstructuredConverter.FromUnstructured(updatedSecret.Object, secrett)
-	require.NoError(t, err)
-
-	require.Equal(t, secrett.Data["love"], []byte("dhriti"))
-
-	res, err = r.Reconcile(reconcileRequest())
-	require.NoError(t, err)
-	require.False(t, res.Requeue)
-
-	bindingSecret2, err := fakeDynClient.Resource(secretsGVR).Namespace(reconcilerNs).Get(context.TODO(), sbr.Status.Secret, metav1.GetOptions{})
-	require.NoError(t, err)
-	require.Equal(t, bindingSecret.GetName(), bindingSecret2.GetName())
-	require.Equal(t, bindingSecret.Object, bindingSecret2.Object)
-}
diff --git a/controllers/secret/secret_test.go b/controllers/secret/secret_test.go
deleted file mode 100644
index de9c7169..00000000
--- a/controllers/secret/secret_test.go
+++ /dev/null
@@ -1,276 +0,0 @@
-package secret
-
-import (
-	"context"
-	"fmt"
-	"testing"
-
-	"github.com/redhat-developer/service-binding-operator/pkg/converter"
-	"github.com/redhat-developer/service-binding-operator/test/mocks"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/apimachinery/pkg/runtime/schema"
-	"k8s.io/client-go/dynamic/fake"
-)
-
-var ownerRefController bool = true
-var secretOwnerReference = v1.OwnerReference{
-	Name:       "binding-request",
-	UID:        "c77ca1ae-72d0-4fdd-809f-58fdd37facf3",
-	Kind:       "ServiceBinding",
-	APIVersion: "operators.coreos.com/v1alpha1",
-	Controller: &ownerRefController,
-}
-
-var namespace string = "secret-namespace"
-
-var secretsGVR = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"}
-
-func assertSecretMetadata(t *testing.T, secret *corev1.Secret) {
-	assert.Equal(t, namespace, secret.GetNamespace())
-	ownerReference := secret.GetOwnerReferences()
-	assert.Equal(t, secretOwnerReference, ownerReference[0])
-}
-
-func isSecretPresent(t *testing.T, f *fake.FakeDynamicClient, secret *corev1.Secret, len int) {
-	secretList, err := f.Resource(secretsGVR).Namespace(namespace).List(context.TODO(), metav1.ListOptions{})
-	assert.NoError(t, err)
-
-	// Ensure length of List
-	assert.Len(t, secretList.Items, len)
-
-	// Ensure secret is present in List
-	s, err := converter.ToUnstructured(secret)
-	assert.NoError(t, err)
-	assert.Contains(t, secretList.Items, *s)
-}
-
-// TestSecretWriteWithSamePrefixAndData tests secret write() and returns existing secret if both prefix and data of existing and current secrets are same
-func TestSecretWriteWithSamePrefixAndData(t *testing.T) {
-	f := mocks.NewFake(t, namespace)
-	fakeClient := f.FakeDynClient()
-	resourceClient := buildResourceClient(fakeClient, namespace)
-
-	prefix := "prefix-1"
-	data := map[string][]byte{"key1": []byte("value1")}
-	secretHash, err := buildSecretHash(data)
-	assert.NoError(t, err)
-
-	readSecret, err := getServiceBindingSecret(resourceClient, prefix+"-"+secretHash, namespace)
-	// read non existing secret
-	assert.EqualError(t, err, fmt.Sprintf("secrets \"%s\" not found", prefix+"-"+secretHash))
-	assert.Nil(t, readSecret)
-
-	secret, err := WriteServiceBindingSecret(
-		fakeClient,
-		namespace,
-		prefix,
-		data,
-		secretOwnerReference,
-	)
-	assert.NoError(t, err)
-	assertSecretMetadata(t, secret)
-	assert.Equal(t, secret.GetName(), prefix+"-"+secretHash)
-
-	// Return existing secret if both prefix and data are same
-	existingSecret, err := WriteServiceBindingSecret(
-		fakeClient,
-		namespace,
-		prefix,
-		data,
-		secretOwnerReference,
-	)
-	assert.NoError(t, err)
-	assertSecretMetadata(t, existingSecret)
-
-	// Secret name should be same if both prefixes and data are same for two consecutive invocations
-	assert.Equal(t, secret.GetName(), existingSecret.GetName())
-
-	// Ensure only one secret is present
-	isSecretPresent(t, fakeClient, secret, 1)
-}
-
-// TestSecretWriteWithDifferentPrefixSameData tests secret write() and creates new secret if prefix of current secret is different
-func TestSecretWriteWithDifferentPrefixSameData(t *testing.T) {
-	f := mocks.NewFake(t, namespace)
-	fakeClient := f.FakeDynClient()
-
-	prefix := "prefix-1"
-	data := map[string][]byte{"key1": []byte("value1")}
-	secretHash, err := buildSecretHash(data)
-	assert.NoError(t, err)
-
-	secret, err := WriteServiceBindingSecret(
-		fakeClient,
-		namespace,
-		prefix,
-		data,
-		secretOwnerReference,
-	)
-	assert.NoError(t, err)
-	assertSecretMetadata(t, secret)
-	assert.Equal(t, secret.GetName(), prefix+"-"+secretHash)
-
-	prefix2 := "prefix-2"
-	differentPrefixSecret, err := WriteServiceBindingSecret(
-		fakeClient,
-		namespace,
-		prefix2,
-		data,
-		secretOwnerReference,
-	)
-	assert.NoError(t, err)
-	assertSecretMetadata(t, differentPrefixSecret)
-	assert.NotEqual(t, differentPrefixSecret.GetName(), secret.GetName())
-	assert.Equal(t, differentPrefixSecret.GetName(), prefix2+"-"+secretHash)
-
-	// Ensure two secrets are present
-	isSecretPresent(t, fakeClient, differentPrefixSecret, 2)
-}
-
-// TestSecretWriteWithSamePrefixDifferentData tests secret write() and creates new secret if data of current secret is different
-func TestSecretWriteWithSamePrefixDifferentData(t *testing.T) {
-	f := mocks.NewFake(t, namespace)
-	fakeClient := f.FakeDynClient()
-
-	prefix := "prefix-1"
-	data := map[string][]byte{"key1": []byte("value1")}
-	secretHash, err := buildSecretHash(data)
-	assert.NoError(t, err)
-
-	secret, err := WriteServiceBindingSecret(
-		fakeClient,
-		namespace,
-		prefix,
-		data,
-		secretOwnerReference,
-	)
-	assert.NoError(t, err)
-	assertSecretMetadata(t, secret)
-	assert.Equal(t, secret.GetName(), prefix+"-"+secretHash)
-
-	differentData := map[string][]byte{"differentKey": []byte("differentValue")}
-	differentSecretHash, err := buildSecretHash(differentData)
-	assert.NoError(t, err)
-
-	differentDataSecret, err := WriteServiceBindingSecret(
-		fakeClient,
-		namespace,
-		prefix,
-		differentData,
-		secretOwnerReference,
-	)
-	assert.NoError(t, err)
-	assertSecretMetadata(t, differentDataSecret)
-	assert.NotEqual(t, differentDataSecret.GetName(), secret.GetName())
-	assert.Equal(t, differentDataSecret.GetName(), prefix+"-"+differentSecretHash)
-
-	// Ensure two secrets are present
-	isSecretPresent(t, fakeClient, differentDataSecret, 2)
-}
-
-// TestSecretUpdatedExternally tests if binding secret is repopulated on external update
-func TestSecretUpdatedExternally(t *testing.T) {
-	f := mocks.NewFake(t, namespace)
-	fakeClient := f.FakeDynClient()
-	resourceClient := buildResourceClient(fakeClient, namespace)
-
-	bindingName := "binding"
-	bindingSecretData := map[string][]byte{"key1": []byte("value1")}
-	bindingSecretHash, err := buildSecretHash(bindingSecretData)
-	assert.NoError(t, err)
-
-	bindingSecret, err := WriteServiceBindingSecret(
-		fakeClient,
-		namespace,
-		bindingName,
-		bindingSecretData,
-		secretOwnerReference,
-	)
-	assert.NoError(t, err)
-	assertSecretMetadata(t, bindingSecret)
-	assert.Equal(t, bindingSecret.GetName(), bindingName+"-"+bindingSecretHash)
-
-	bindingSecret.Data = map[string][]byte{"externallyUpdatedKey": []byte("externallyUpdatedValue")}
-	unstructuredSecret, err := runtime.DefaultUnstructuredConverter.ToUnstructured(bindingSecret)
-	require.NoError(t, err)
-
-	updated := unstructured.Unstructured{Object: unstructuredSecret}
-	externallyUpdatedSecret, err := fakeClient.Resource(secretsGVR).Namespace(updated.GetNamespace()).Update(context.TODO(), &updated, metav1.UpdateOptions{})
-	assert.NoError(t, err)
-
-	updatedSecretHash, err := buildSecretHash(bindingSecret.Data)
-	assert.NoError(t, err)
-
-	assert.Equal(t, externallyUpdatedSecret.GetName(), bindingSecret.GetName())
-	// Externally updated secret name will not contain the new updated secret hash
-	assert.NotContains(t, externallyUpdatedSecret.GetName(), updatedSecretHash)
-	assert.Contains(t, externallyUpdatedSecret.GetName(), bindingSecretHash)
-
-	correctedSecret, err := WriteServiceBindingSecret(
-		fakeClient,
-		namespace,
-		bindingName,
-		bindingSecretData,
-		secretOwnerReference,
-	)
-	assert.NoError(t, err)
-	assertSecretMetadata(t, correctedSecret)
-
-	assert.Equal(t, correctedSecret.GetName(), bindingSecret.GetName())
-
-	assert.Equal(t, externallyUpdatedSecret.GetName(), correctedSecret.GetName())
-	assert.NotEqual(t, externallyUpdatedSecret.Object, correctedSecret.Data)
-
-	updatedSecretWithCorrectData, err := getServiceBindingSecret(resourceClient, correctedSecret.GetName(), namespace)
-	assert.NoError(t, err)
-
-	assert.Equal(t, updatedSecretWithCorrectData.GetName(), correctedSecret.GetName())
-
-	assert.Equal(t, updatedSecretWithCorrectData, correctedSecret)
-	isSecretPresent(t, fakeClient, correctedSecret, 1)
-}
-
-// TestKeysSortedDifferently tests secret write() and creates new secret if keys are sorted differently
-func TestKeysSortedDifferently(t *testing.T) {
-	f := mocks.NewFake(t, namespace)
-	fakeClient := f.FakeDynClient()
-
-	prefix := "binding"
-	data := map[string][]byte{"sameKey": []byte("sameValue")}
-	secretHash, err := buildSecretHash(data)
-	assert.NoError(t, err)
-
-	secret, err := WriteServiceBindingSecret(
-		fakeClient,
-		namespace,
-		prefix,
-		data,
-		secretOwnerReference,
-	)
-	assert.NoError(t, err)
-	assertSecretMetadata(t, secret)
-	assert.Equal(t, secret.GetName(), prefix+"-"+secretHash)
-	isSecretPresent(t, fakeClient, secret, 1)
-
-	dataDifferentKeySort := map[string][]byte{"sameKey": []byte("differentValue")}
-	dataDifferentKeySortHash, err := buildSecretHash(dataDifferentKeySort)
-	assert.NoError(t, err)
-
-	secretDifferentSort, err := WriteServiceBindingSecret(
-		fakeClient,
-		namespace,
-		prefix,
-		dataDifferentKeySort,
-		secretOwnerReference,
-	)
-	assert.NoError(t, err)
-	assertSecretMetadata(t, secretDifferentSort)
-	assert.Equal(t, secretDifferentSort.GetName(), prefix+"-"+dataDifferentKeySortHash)
-	isSecretPresent(t, fakeClient, secretDifferentSort, 2)
-}
diff --git a/controllers/secret_test.go b/controllers/secret_test.go
new file mode 100644
index 00000000..9b8a24fd
--- /dev/null
+++ b/controllers/secret_test.go
@@ -0,0 +1,55 @@
+package controllers
+
+import (
+	"github.com/redhat-developer/service-binding-operator/api/v1alpha1"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+
+	"github.com/redhat-developer/service-binding-operator/test/mocks"
+)
+
+var ownerRefController bool = true
+var secretOwnerReference = v1.OwnerReference{
+	Name:       "binding-request",
+	UID:        "c77ca1ae-72d0-4fdd-809f-58fdd37facf3",
+	Kind:       "ServiceBinding",
+	APIVersion: v1alpha1.GroupVersion.String(),
+	Controller: &ownerRefController,
+}
+
+func assertSecretNamespacedName(t *testing.T, u *unstructured.Unstructured, ns, name string) {
+	assert.Equal(t, ns, u.GetNamespace())
+	assert.Equal(t, name, u.GetName())
+	ownerReference := u.GetOwnerReferences()
+	assert.Equal(t, secretOwnerReference, ownerReference[0])
+}
+
+func TestSecretNew(t *testing.T) {
+	ns := "secret"
+	name := "test-secret"
+
+	f := mocks.NewFake(t, ns)
+
+	data := map[string][]byte{"key": []byte("value")}
+
+	s := newSecret(
+		f.FakeDynClient(),
+		ns,
+		name,
+	)
+
+	t.Run("createOrUpdate", func(t *testing.T) {
+		u, err := s.createOrUpdate(data, secretOwnerReference)
+		assert.NoError(t, err)
+		assertSecretNamespacedName(t, u, ns, name)
+	})
+
+	t.Run("Get", func(t *testing.T) {
+		u, err := s.get()
+		assert.NoError(t, err)
+		assertSecretNamespacedName(t, u, ns, name)
+	})
+}
diff --git a/controllers/servicebinder_test.go b/controllers/servicebinder_test.go
index c25c14bd..e6603207 100644
--- a/controllers/servicebinder_test.go
+++ b/controllers/servicebinder_test.go
@@ -462,7 +462,7 @@ func TestServiceBinder_Bind(t *testing.T) {
 			{
 				resource: "secrets",
 				verb:     "update",
-				name:     sbrSingleService.Status.Secret,
+				name:     sbrSingleService.GetName(),
 			},
 			{
 				resource: "databases",
@@ -508,7 +508,7 @@ func TestServiceBinder_Bind(t *testing.T) {
 			{
 				resource: "secrets",
 				verb:     "update",
-				name:     sbrSingleServiceWithMappings.Status.Secret,
+				name:     sbrSingleServiceWithMappings.GetName(),
 				objAssertions: []objAssertionFunc{
 					base64StringEqual("db1", "data", "MY_DB_NAME"),
 				},
diff --git a/controllers/servicecontext_test.go b/controllers/servicecontext_test.go
index 388d968d..0a4255f0 100644
--- a/controllers/servicecontext_test.go
+++ b/controllers/servicecontext_test.go
@@ -1,9 +1,8 @@
 package controllers
 
 import (
-	"testing"
-
 	"github.com/redhat-developer/service-binding-operator/pkg/converter"
+	"testing"
 
 	"github.com/redhat-developer/service-binding-operator/api/v1alpha1"
 	"github.com/redhat-developer/service-binding-operator/pkg/log"
@@ -180,7 +179,6 @@ func TestFindOwnedResourcesCtxs_ConfigMap(t *testing.T) {
 	f.AddMockedUnstructuredSecret("db-credentials")
 
 	cr := mocks.UnstructuredDatabaseCRMock("test", "test")
-	cr.SetUID("123")
 	reference := metav1.OwnerReference{
 		APIVersion:         cr.GetAPIVersion(),
 		Kind:               cr.GetKind(),
@@ -214,6 +212,7 @@ func TestFindOwnedResourcesCtxs_ConfigMap(t *testing.T) {
 		)
 		require.NoError(t, err)
 		require.Len(t, got, 2)
+
 		expected := map[string]interface{}{
 			"": map[string]interface{}{
 				"password": "password",
@@ -221,21 +220,7 @@ func TestFindOwnedResourcesCtxs_ConfigMap(t *testing.T) {
 			},
 		}
 		require.Equal(t, expected, got[0].envVars)
-	})
 
-	t.Run("findOwnedResourcesCtxs returns no items if owner id is empty", func(t *testing.T) {
-		cr.SetUID("")
-		got, err := findOwnedResourcesCtxs(
-			logger,
-			f.FakeDynClient(),
-			cr.GetNamespace(),
-			cr.GetUID(),
-			nameTemplate,
-			false,
-			typeLookup,
-		)
-		require.NoError(t, err)
-		require.Len(t, got, 0)
 	})
 }
 
@@ -260,7 +245,6 @@ func TestFindOwnedResourcesCtxs_Secrets(t *testing.T) {
 		t.Run(tC.desc, func(t *testing.T) {
 			f := mocks.NewFake(t, "test")
 			cr := mocks.UnstructuredDatabaseCRMock("test", "test")
-			cr.SetUID("123")
 			reference := metav1.OwnerReference{
 				APIVersion:         cr.GetAPIVersion(),
 				Kind:               cr.GetKind(),
diff --git a/test/acceptance/features/bindAppToMultipleServices.feature b/test/acceptance/features/bindAppToMultipleServices.feature
index 768f9086..8144ea87 100644
--- a/test/acceptance/features/bindAppToMultipleServices.feature
+++ b/test/acceptance/features/bindAppToMultipleServices.feature
@@ -7,77 +7,52 @@ Feature: Bind a single application to multiple services
     Background:
         Given Namespace [TEST_NAMESPACE] is used
         * Service Binding Operator is running
+        * PostgreSQL DB operator is installed
+
     Scenario: Bind two backend services by creating 2 SBRs to a single application
-        Given Generic test application "myapp-2-sbrs" is running
-        * OLM Operator "backend" is running
-        * The Custom Resource is present
-        """
-        apiVersion: stable.example.com/v1
-        kind: Backend
-        metadata:
-            name: myapp-2-sbrs-service-1
-            annotations:
-                service.binding/host: path={.spec.host}
-        spec:
-            host: foo
-        """
-        * The Custom Resource is present
-        """
-        apiVersion: stable.example.com/v1
-        kind: Backend
-        metadata:
-            name: myapp-2-sbrs-service-2
-            annotations:
-                service.binding/port: path={.spec.port}
-        spec:
-            port: bar
-        """
-        When Service Binding is applied
+        Given Imported Nodejs application "nodejs-app" is running
+        * DB "db-demo-1" is running
+        * DB "db-demo-2" is running
+        * Service Binding is applied
             """
             apiVersion: binding.operators.coreos.com/v1alpha1
             kind: ServiceBinding
             metadata:
-                name: binding1-myapp-2-sbrs
+                name: binding-request-1
             spec:
                 application:
-                    name: myapp-2-sbrs
+                    name: nodejs-app
                     group: apps
                     version: v1
                     resource: deployments
                 services:
-                -   group: stable.example.com
-                    version: v1
-                    kind: Backend
-                    name: myapp-2-sbrs-service-1
+                -   group: postgresql.baiju.dev
+                    version: v1alpha1
+                    kind: Database
+                    name: db-demo-1
             """
-        Then Service Binding "binding1-myapp-2-sbrs" is ready
-        And "myapp-2-sbrs" deployment must contain reference to secret existing in service binding
-        And The application env var "BACKEND_HOST" has value "foo"
-        
         When Service Binding is applied
             """
             apiVersion: binding.operators.coreos.com/v1alpha1
             kind: ServiceBinding
             metadata:
-                name: binding2-myapp-2-sbrs
+                name: binding-request-2
             spec:
                 application:
-                    name: myapp-2-sbrs
+                    name: nodejs-app
                     group: apps
                     version: v1
                     resource: deployments
                 services:
-                -   group: stable.example.com
-                    version: v1
-                    kind: Backend
-                    name: myapp-2-sbrs-service-2
+                -   group: postgresql.baiju.dev
+                    version: v1alpha1
+                    kind: Database
+                    name: db-demo-2
             """
-        Then Service Binding "binding2-myapp-2-sbrs" is ready
-        And "myapp-2-sbrs" deployment must contain reference to secret existing in service binding
-        And The application env var "BACKEND_HOST" has value "foo"
-        And The application env var "BACKEND_PORT" has value "bar" 
-        And The application got redeployed 2 times so far
-        And The application does not get redeployed again with 5 minutes
+        Then Service Binding "binding-request-1" is ready
+        And Service Binding "binding-request-2" is ready
+        And "nodejs-app" deployment must contain SBR name "binding-request-1"
+        And "nodejs-app" deployment must contain SBR name "binding-request-2"
 
     Scenario: Bind two backend services by creating 1 SBR to a single application
         Given Generic test application "myapp-1sbr" is running
diff --git a/test/acceptance/features/bindAppToService.feature b/test/acceptance/features/bindAppToService.feature
index 88ec21ae..a5437391 100644
--- a/test/acceptance/features/bindAppToService.feature
+++ b/test/acceptance/features/bindAppToService.feature
@@ -34,16 +34,16 @@ Feature: Bind an application to a service
         Then Service Binding "binding-request-a-d-s" is ready
         And application should be re-deployed
         And application should be connected to the DB "db-demo-a-d-s"
-        And Secret contains "DATABASE_DBNAME" key with value "db-demo-a-d-s"
-        And Secret contains "DATABASE_USER" key with value "postgres"
-        And Secret contains "DATABASE_PASSWORD" key with value "password"
-        And Secret contains "DATABASE_DB_PASSWORD" key with value "password"
-        And Secret contains "DATABASE_DB_NAME" key with value "db-demo-a-d-s"
-        And Secret contains "DATABASE_DB_PORT" key with value "5432"
-        And Secret contains "DATABASE_DB_USER" key with value "postgres"
-        And Secret contains "DATABASE_DB_HOST" key with dynamic IP addess as the value
-        And Secret contains "DATABASE_DBCONNECTIONIP" key with dynamic IP addess as the value
-        And Secret contains "DATABASE_DBCONNECTIONPORT" key with value "5432"
+        And Secret "binding-request-a-d-s" contains "DATABASE_DBNAME" key with value "db-demo-a-d-s"
+        And Secret "binding-request-a-d-s" contains "DATABASE_USER" key with value "postgres"
+        And Secret "binding-request-a-d-s" contains "DATABASE_PASSWORD" key with value "password"
+        And Secret "binding-request-a-d-s" contains "DATABASE_DB_PASSWORD" key with value "password"
+        And Secret "binding-request-a-d-s" contains "DATABASE_DB_NAME" key with value "db-demo-a-d-s"
+        And Secret "binding-request-a-d-s" contains "DATABASE_DB_PORT" key with value "5432"
+        And Secret "binding-request-a-d-s" contains "DATABASE_DB_USER" key with value "postgres"
+        And Secret "binding-request-a-d-s" contains "DATABASE_DB_HOST" key with dynamic IP addess as the value
+        And Secret "binding-request-a-d-s" contains "DATABASE_DBCONNECTIONIP" key with dynamic IP addess as the value
+        And Secret "binding-request-a-d-s" contains "DATABASE_DBCONNECTIONPORT" key with value "5432"
 
     Scenario: Bind an imported Node.js application to PostgreSQL database in the following order: Application, Service Binding and DB
         Given Imported Nodejs application "nodejs-rest-http-crud-a-s-d" is running
@@ -213,8 +213,8 @@ Feature: Bind an application to a service
         And jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "binding-request-empty-app" should be changed to "False"
         And jq ".status.conditions[] | select(.type=="InjectionReady").reason" of Service Binding "binding-request-empty-app" should be changed to "EmptyApplication"
         And jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "binding-request-empty-app" should be changed to "True"
-        And Secret contains "BACKEND_HOST" key with value "example.common"
-        And Secret contains "BACKEND_USERNAME" key with value "foo"
+        And Secret "binding-request-empty-app" contains "BACKEND_HOST" key with value "example.common"
+        And Secret "binding-request-empty-app" contains "BACKEND_USERNAME" key with value "foo"
 
     Scenario: Backend Service status update gets propagated to the binding secret
         Given OLM Operator "backend" is running
@@ -249,11 +249,10 @@ Feature: Bind an application to a service
                   - name: CustomHost
                     value: '{{ .SBR.spec.host }}'
             """
-        Then Secret name should be updated in Service Binding status
-        And jq ".status.conditions[] | select(.type=="CollectionReady").status" of Service Binding "binding-request-backend" should be changed to "True"
-        And jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "binding-request-backend" should be changed to "False"
-        And jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "binding-request-backend" should be changed to "True"
-        And Secret contains "CustomReady" key with value "<no value>"
+        * jq ".status.conditions[] | select(.type=="CollectionReady").status" of Service Binding "binding-request-backend" should be changed to "True"
+        * jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "binding-request-backend" should be changed to "False"
+        * jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "binding-request-backend" should be changed to "True"
+        * Secret "binding-request-backend" contains "CustomReady" key with value "<no value>"
 
         # Backend status in "backend-demo" is updated
         When The Custom Resource is present
@@ -270,81 +269,9 @@ Feature: Bind an application to a service
             status:
                 ready: true
             """
-        Then Secret name should be updated in Service Binding status
-        Then Secret contains "CustomReady" key with value "true"
+        Then Secret "binding-request-backend" contains "CustomReady" key with value "true"
 
 
-    Scenario: Backend Service status update gets propagated to the application
-        Given OLM Operator "backend" is running
-        * Generic test application "generic-app-demo-volume-mount" is running
-        * The Custom Resource is present
-            """
-            apiVersion: "stable.example.com/v1"
-            kind: Backend
-            metadata:
-                name: backend-demo-volume-mount
-                annotations:
-                    service.binding/host: path={.spec.host}
-                    service.binding/ready: path={.status.ready}
-            spec:
-                host: example.common
-            """
-        * Service Binding is applied
-            """
-            apiVersion: binding.operators.coreos.com/v1alpha1
-            kind: ServiceBinding
-            metadata:
-                name: binding-request-backend-volume-mount
-            spec:
-                bindAsFiles: true
-                services:
-                -   group: stable.example.com
-                    version: v1
-                    kind: Backend
-                    name: backend-demo-volume-mount
-                    id: SBR
-                application:
-                    name: generic-app-demo-volume-mount
-                    group: apps
-                    version: v1
-                    resource: deployments
-            """
-        And jq ".status.conditions[] | select(.type=="CollectionReady").status" of Service Binding "binding-request-backend-volume-mount" should be changed to "True"
-        And jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "binding-request-backend-volume-mount" should be changed to "True"
-        And jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "binding-request-backend-volume-mount" should be changed to "True"
-        And The env var "host" is not available to the application
-        And The env var "ready" is not available to the application
-        And Content of file "/bindings/binding-request-backend-volume-mount/host" in application pod is
-            """
-            example.common
-            """
-
-        # Backend status in "backend-demo" is updated
-        When The Custom Resource is present
-            """
-            apiVersion: "stable.example.com/v1"
-            kind: Backend
-            metadata:
-                name: backend-demo-volume-mount
-                annotations:
-                    service.binding/host: path={.spec.host}
-                    service.binding/ready: path={.status.ready}
-            spec:
-                host: example.common
-            status:
-                ready: true
-            """
-        Then The env var "host" is not available to the application
-        And The env var "ready" is not available to the application
-        And Content of file "/bindings/binding-request-backend-volume-mount/host" in application pod is
-            """
-            example.common
-            """
-        And Content of file "/bindings/binding-request-backend-volume-mount/ready" in application pod is
-            """
-            true
-            """
-
     Scenario: Backend Service new spec status update gets propagated to the binding secret
         Given OLM Operator "backend-new-spec" is running
         * The Custom Resource is present
@@ -377,9 +304,9 @@ Feature: Bind an application to a service
         Then jq ".status.conditions[] | select(.type=="CollectionReady").status" of Service Binding "binding-request-backend-new-spec" should be changed to "True"
         And jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "binding-request-backend-new-spec" should be changed to "False"
         And jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "binding-request-backend-new-spec" should be changed to "True"
-        And Secret contains "BACKEND_HOST" key with value "example.common"
-        And Secret contains "BACKEND_PORTS_FTP" key with value "22"
-        And Secret contains "BACKEND_PORTS_TCP" key with value "8080"
+        And Secret "binding-request-backend-new-spec" contains "BACKEND_HOST" key with value "example.common"
+        And Secret "binding-request-backend-new-spec" contains "BACKEND_PORTS_FTP" key with value "22"
+        And Secret "binding-request-backend-new-spec" contains "BACKEND_PORTS_TCP" key with value "8080"
 
 
     Scenario: Custom environment variable is injected into the application under the declared name ignoring global and service env prefix
@@ -408,7 +335,7 @@ Feature: Bind an application to a service
                       value: 'SOME_VALUE:{{ .postgresDB.status.dbConnectionPort }}:{{ .postgresDB.status.dbName }}'
             """
         Then Service Binding "binding-request-a-d-c" is ready
-        And Secret contains "SOME_KEY" key with value "SOME_VALUE:5432:db-demo-a-d-c"
+        And Secret "binding-request-a-d-c" contains "SOME_KEY" key with value "SOME_VALUE:5432:db-demo-a-d-c"
 
     Scenario: Creating binding secret from the definitions managed in OLM operator descriptors
         Given Backend service CSV is installed
@@ -509,10 +436,10 @@ Feature: Bind an application to a service
         Then jq ".status.conditions[] | select(.type=="CollectionReady").status" of Service Binding "sbr-csv-secret-cm-descriptors" should be changed to "True"
         And jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "sbr-csv-secret-cm-descriptors" should be changed to "False"
         And jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "sbr-csv-secret-cm-descriptors" should be changed to "True"
-        And Secret contains "BACKSERV_DB_HOST" key with value "172.72.2.0"
-        And Secret contains "BACKSERV_DB_PORT" key with value "3306"
-        And Secret contains "BACKSERV_PASSWORD" key with value "secret123"
-        And Secret contains "BACKSERV_USERNAME" key with value "admin"
+        And Secret "sbr-csv-secret-cm-descriptors" contains "BACKSERV_DB_HOST" key with value "172.72.2.0"
+        And Secret "sbr-csv-secret-cm-descriptors" contains "BACKSERV_DB_PORT" key with value "3306"
+        And Secret "sbr-csv-secret-cm-descriptors" contains "BACKSERV_PASSWORD" key with value "secret123"
+        And Secret "sbr-csv-secret-cm-descriptors" contains "BACKSERV_USERNAME" key with value "admin"
 
 
     # This test scenario is disabled until the issue is resolved: https://github.com/redhat-developer/service-binding-operator/issues/656
@@ -586,7 +513,7 @@ Feature: Bind an application to a service
         Then jq ".status.conditions[] | select(.type=="CollectionReady").status" of Service Binding "sbr-csv-attribute" should be changed to "True"
         And jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "sbr-csv-attribute" should be changed to "False"
         And jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "sbr-csv-attribute" should be changed to "True"
-        And Secret contains "BACKSERV_ENV_SVCNAME" key with value "demo-backserv-cr-1"
+        And Secret "sbr-csv-secret-cm-descriptors" contains "BACKSERV_ENV_SVCNAME" key with value "demo-backserv-cr-1"
 
     Scenario: Bind an imported Node.js application to Etcd database
         Given Etcd operator running
@@ -825,49 +752,3 @@ Feature: Bind an application to a service
             """
         Then Service Binding "binding-request-cross-ns-service" is ready
         And The application env var "BACKEND_HOST_CROSS_NS_SERVICE" has value "cross.ns.service.stable.example.com"
-
-    Scenario: Binding secret is repopulated on external update 
-        Given OLM Operator "backend-new-spec" is running
-        * The Custom Resource is present
-            """
-            apiVersion: "stable.example.com/v1"
-            kind: Backend
-            metadata:
-                name: backend-demo
-            spec:
-                host: example.common
-            """
-        * Service Binding is applied
-            """
-            apiVersion: binding.operators.coreos.com/v1alpha1
-            kind: ServiceBinding
-            metadata:
-                name: binding-request-secret-updated-externally
-            spec:
-                services:
-                -   group: stable.example.com
-                    version: v1
-                    kind: Backend
-                    name: backend-demo
-            """
-        Then Secret name should be updated in Service Binding status
-        And jq ".status.conditions[] | select(.type=="CollectionReady").status" of Service Binding "binding-request-secret-updated-externally" should be changed to "True"
-        And jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "binding-request-secret-updated-externally" should be changed to "False"
-        And jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "binding-request-secret-updated-externally" should be changed to "True"
-        And Secret contains "BACKEND_HOST" key with value "example.common"
-
-        * Binding secret is updated
-            """
-            apiVersion: v1
-            kind: Secret
-            metadata:
-                name: binding-request-secret-updated-externally
-            type: Opaque
-            stringData:
-                host2: example2.common
-            """
-        Then jq ".status.conditions[] | select(.type=="CollectionReady").status" of Service Binding "binding-request-secret-updated-externally" should be changed to "True"
-        And jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "binding-request-secret-updated-externally" should be changed to "False"
-        And jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "binding-request-secret-updated-externally" should be changed to "True"
-        And Secret contains "BACKEND_HOST" key with value "example.common"
-        And Secret does not contain "host2"
\ No newline at end of file
diff --git a/test/acceptance/features/bindAppToServiceAnnotations.feature b/test/acceptance/features/bindAppToServiceAnnotations.feature
index e101958e..e4476d96 100644
--- a/test/acceptance/features/bindAppToServiceAnnotations.feature
+++ b/test/acceptance/features/bindAppToServiceAnnotations.feature
@@ -62,8 +62,8 @@ Feature: Bind an application to a service using annotations
         And jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "binding-request-backend-a" should be changed to "False"
         And jq ".status.conditions[] | select(.type=="InjectionReady").reason" of Service Binding "binding-request-backend-a" should be changed to "EmptyApplication"
         And jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "binding-request-backend-a" should be changed to "True"
-        And Secret contains "BACKEND_READY" key with value "true"
-        And Secret contains "BACKEND_HOST" key with value "example.common"
+        And Secret "binding-request-backend-a" contains "BACKEND_READY" key with value "true"
+        And Secret "binding-request-backend-a" contains "BACKEND_HOST" key with value "example.common"
 
     Scenario: Each value in referred map from service resource gets injected into app as separate env variable
         Given Generic test application "rsa-2-service" is running
@@ -353,9 +353,8 @@ Feature: Bind an application to a service using annotations
                     kind: Backend
                     name: backend-demo-2
             """
-        Then Secret name should be updated in Service Binding status
-        And Secret contains "BACKEND_HOST" key with value "example.com"
-        And Secret does not contain "BACKEND_READY"
+        And Secret "binding-request-backend-ann-sb" contains "BACKEND_HOST" key with value "example.com"
+        And Secret "binding-request-backend-ann-sb" does not contain "BACKEND_READY"
         # Backend metadata.annotations for service binding is updated
         When The Custom Resource is present
             """
@@ -371,13 +370,12 @@ Feature: Bind an application to a service using annotations
             status:
                 ready: true
             """
-        Then Secret name should be updated in Service Binding status
-        And jq ".status.conditions[] | select(.type=="CollectionReady").status" of Service Binding "binding-request-backend-ann-sb" should be changed to "True"
+        Then jq ".status.conditions[] | select(.type=="CollectionReady").status" of Service Binding "binding-request-backend-ann-sb" should be changed to "True"
         And jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "binding-request-backend-ann-sb" should be changed to "False"
         And jq ".status.conditions[] | select(.type=="InjectionReady").reason" of Service Binding "binding-request-backend-ann-sb" should be changed to "EmptyApplication"
         And jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "binding-request-backend-ann-sb" should be changed to "True"
-        And Secret contains "BACKEND_READY" key with value "true"
-        And Secret contains "BACKEND_HOST" key with value "example.com"
+        And Secret "binding-request-backend-ann-sb" contains "BACKEND_READY" key with value "true"
+        And Secret "binding-request-backend-ann-sb" contains "BACKEND_HOST" key with value "example.com"
 
 
     @negative
@@ -414,7 +412,7 @@ Feature: Bind an application to a service using annotations
         And jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "binding-request-backend-ann" should be changed to "False"
         And jq ".status.conditions[] | select(.type=="InjectionReady").reason" of Service Binding "binding-request-backend-ann" should be changed to "EmptyApplication"
         And jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "binding-request-backend-ann" should be changed to "True"
-        And Secret is empty
+        And Secret "binding-request-backend-ann" is empty
         # Backend metadata.annotations not pertaining to service binding is updated
         When The Custom Resource is present
             """
@@ -429,7 +427,7 @@ Feature: Bind an application to a service using annotations
             status:
                 ready: true
             """
-        Then Secret is empty
+        Then Secret "binding-request-backend-ann" is empty
 
     @olm
     Scenario: Bind referring service using group version resource
diff --git a/test/acceptance/features/bindKnativeService.feature b/test/acceptance/features/bindKnativeService.feature
index 0cebf5d4..120117a0 100644
--- a/test/acceptance/features/bindKnativeService.feature
+++ b/test/acceptance/features/bindKnativeService.feature
@@ -42,5 +42,5 @@ Feature: Bind knative service to a service
                   value: "{{ .knav.status.dbCredentials.password }}"
             """
         Then Service Binding "binding-request-knative" is ready
-        And deployment must contain reference to binding secret
+        And deployment must contain intermediate secret "binding-request-knative"
         And application should be connected to the DB "db-demo-knative"
diff --git a/test/acceptance/features/examples.feature b/test/acceptance/features/examples.feature
index ef4a7c2e..13553ecc 100644
--- a/test/acceptance/features/examples.feature
+++ b/test/acceptance/features/examples.feature
@@ -54,7 +54,7 @@ Feature: Verify examples provided in Service Binding Operator github repository
         Then jq ".status.conditions[] | select(.type=="CollectionReady").status" of Service Binding "sbr-to-bind-hello-app-to-route" should be changed to "True"
         And jq ".status.conditions[] | select(.type=="InjectionReady").status" of Service Binding "sbr-to-bind-hello-app-to-route" should be changed to "True"
         And jq ".status.conditions[] | select(.type=="Ready").status" of Service Binding "sbr-to-bind-hello-app-to-route" should be changed to "True"
-        And Secret contains "ROUTE_HOST" key with value "example-sbo.apps.ci-ln-smyggvb-d5d6b.origin-ci-int-aws.dev.rhcloud.com"
+        And Secret "sbr-to-bind-hello-app-to-route" contains "ROUTE_HOST" key with value "example-sbo.apps.ci-ln-smyggvb-d5d6b.origin-ci-int-aws.dev.rhcloud.com"
 
     # https://github.com/redhat-developer/service-binding-operator/tree/master/examples/nodejs_postgresql_namespaces
     Scenario: Bind an application to a database running in another namespace
diff --git a/test/acceptance/features/injectSecretAtCustomSchemaPath.feature b/test/acceptance/features/injectSecretAtCustomSchemaPath.feature
index 373a921b..cf9a65f3 100644
--- a/test/acceptance/features/injectSecretAtCustomSchemaPath.feature
+++ b/test/acceptance/features/injectSecretAtCustomSchemaPath.feature
@@ -74,7 +74,7 @@ Feature: Insert service binding to a custom location in application resource
                     id: zzz
             """
         Then Service Binding "binding-request-csp" is ready
-        And Secret has been injected in to CR "demo-appconfig-csp" of kind "AppConfig" at path "{.spec.spec.containers[0].envFrom[0].secretRef.name}"
+        And Secret "binding-request-csp" has been injected in to CR "demo-appconfig-csp" of kind "AppConfig" at path "{.spec.spec.containers[0].envFrom[0].secretRef.name}"
 
     Scenario: Specify secret's path in Service Binding
         Given DB "db-demo-ssp" is running
@@ -110,4 +110,4 @@ Feature: Insert service binding to a custom location in application resource
                     id: zzz
             """
         Then Service Binding "binding-request-ssp" is ready
-        And Secret has been injected in to CR "demo-appconfig-ssp" of kind "AppConfig" at path "{.spec.spec.secret}"
+        And Secret "binding-request-ssp" has been injected in to CR "demo-appconfig-ssp" of kind "AppConfig" at path "{.spec.spec.secret}"
diff --git a/test/acceptance/features/steps/generic_testapp.py b/test/acceptance/features/steps/generic_testapp.py
index 5b258b29..ea9befcb 100644
--- a/test/acceptance/features/steps/generic_testapp.py
+++ b/test/acceptance/features/steps/generic_testapp.py
@@ -2,13 +2,11 @@ from app import App
 import requests
 import json
 import polling2
-from behave import given, step
+from behave import given, step, then
 
 
 class GenericTestApp(App):
 
-    deployment_name_pattern = "{name}"
-
     def __init__(self, name, namespace, app_image="quay.io/redhat-developer/sbo-generic-test-app:20200923"):
         App.__init__(self, name, namespace, app_image, "8080")
 
@@ -21,13 +19,6 @@ class GenericTestApp(App):
         else:
             return None
 
-    def format_pattern(self, pattern):
-        return pattern.format(name=self.name)
-
-    def get_generation(self):
-        deployment_name = self.openshift.get_deployment_name_in_namespace(self.format_pattern(self.deployment_name_pattern), self.namespace)
-        return int(self.openshift.get_resource_info_by_jsonpath("deployment", deployment_name, self.namespace, "{.metadata.generation}"))
-
     def get_file_value(self, file_path):
         resp = polling2.poll(lambda: requests.get(url=f"http://{self.route_url}{file_path}"),
                              check_success=lambda r: r.status_code == 200, step=5, timeout=400, ignore_exceptions=(requests.exceptions.ConnectionError,))
@@ -44,10 +35,6 @@ def is_running(context, application_name, bindingRoot=None):
         application.install(bindingRoot=bindingRoot)
     context.application = application
 
-    # save the generation number
-    context.original_application_generation = application.get_generation()
-    context.latest_application_generation = application.get_generation()
-
 
 @step(u'The application env var "{name}" has value "{value}"')
 def check_env_var_value(context, name, value):
@@ -61,7 +48,7 @@ def check_env_var_existence(context, name):
     assert output, f'Env var "{name}" should not exist'
 
 
-@step(u'Content of file "{file_path}" in application pod is')
+@then(u'Content of file "{file_path}" in application pod is')
 def check_file_value(context, file_path):
     value = context.text.strip()
     polling2.poll(lambda: context.application.get_file_value(file_path) == value, step=5, timeout=400)
diff --git a/test/acceptance/features/steps/steps.py b/test/acceptance/features/steps/steps.py
index 8d5d0b8f..ca34c9c6 100644
--- a/test/acceptance/features/steps/steps.py
+++ b/test/acceptance/features/steps/steps.py
@@ -199,7 +199,6 @@ def sbr_is_applied(context):
     else:
         ns = None
     assert sbr.create(sbr_yaml, ns) is not None, "Service binding not created"
-    context.sb_secret = ""
 
 
 # STEP
@@ -304,40 +303,27 @@ def quarkus_app_is_imported_as_knative_service(context, application_name):
     context.application_type = "knative"
 
 
-def get_sbr_secret_name(context):
-    openshift = Openshift()
-    output = openshift.get_resource_info_by_jsonpath("servicebindings", context.sbr_name, context.namespace.name, "{.status.secret}")
-    assert output is not None, "Failed to fetch secret name from ServiceBinding"
-    return output
-
-
-@step(u'Secret name should be updated in Service Binding status')
-def then_secret_should_be_updated(context):
-    context.sb_secret = polling2.poll(lambda: get_sbr_secret_name(context), step=100, timeout=1000, ignore_exceptions=(ValueError,),
-                                      check_success=lambda v: v is not None and context.sb_secret != v)
+# STEP
 
 
-# STEP
-@then(u'"{app_name}" deployment must contain reference to secret existing in service binding')
-def then_envFrom_contains(context, app_name):
+@then(u'"{app_name}" deployment must contain SBR name "{sbr_name}"')
+def then_envFrom_contains(context, app_name, sbr_name):
     time.sleep(60)
     openshift = Openshift()
-    secret = polling2.poll(lambda: get_sbr_secret_name(context), step=100, timeout=1000, ignore_exceptions=(ValueError,), check_success=lambda v: v is not None)
     result = openshift.get_deployment_envFrom_info(app_name, context.namespace.name)
     # Expected result from 'oc' (openshift client) v4.5
-    expected_result_oc_45 = f'secretRef:map[name:{secret}]'
+    expected_result_oc_45 = f'secretRef:map[name:{sbr_name}]'
     # Expected result from 'oc' (openshift client) v4.6+
-    expected_result_oc_46 = f'{{"secretRef":{{"name":"{secret}"}}}}'
+    expected_result_oc_46 = f'{{"secretRef":{{"name":"{sbr_name}"}}}}'
     assert re.search(re.escape(expected_result_oc_45), result) is not None or re.search(re.escape(expected_result_oc_46), result) is not None, \
-        f'\n{app_name} deployment should contain secretRef: {secret} \nActual secretRef: {result}'
+        f'\n{app_name} deployment should contain secretRef: {sbr_name} \nActual secretRef: {result}'
 
 
 # STEP
-@then(u'deployment must contain reference to binding secret')
-def envFrom_contains_intermediate_secret_name(context):
-    secret = polling2.poll(lambda: get_sbr_secret_name(context), step=100, timeout=1000, ignore_exceptions=(ValueError,), check_success=lambda v: v is not None)
+@then(u'deployment must contain intermediate secret "{intermediate_secret_name}"')
+def envFrom_contains_intermediate_secret_name(context, intermediate_secret_name):
     assert context.application.get_deployment_with_intermediate_secret(
-        secret) is not None, f"There is no deployment with intermediate secret {secret}"
+        intermediate_secret_name) is not None, f"There is no deployment with intermediate secret {intermediate_secret_name}"
 
 
 # STEP
@@ -360,24 +346,22 @@ register_type(NullableString=parse_nullable_string)
 
 
 # STEP
-@step(u'Secret contains "{secret_key}" key with value "{secret_value:NullableString}"')
-def check_secret_key_value(context, secret_key, secret_value):
+@step(u'Secret "{secret_name}" contains "{secret_key}" key with value "{secret_value:NullableString}"')
+def check_secret_key_value(context, secret_name, secret_key, secret_value):
     openshift = Openshift()
-    secret = polling2.poll(lambda: get_sbr_secret_name(context), step=100, timeout=1000, ignore_exceptions=(ValueError,), check_success=lambda v: v is not None)
     json_path = f'{{.data.{secret_key}}}'
-    polling2.poll(lambda: openshift.get_resource_info_by_jsonpath("secrets", secret, context.namespace.name,
+    polling2.poll(lambda: openshift.get_resource_info_by_jsonpath("secrets", secret_name, context.namespace.name,
                                                                   json_path) == secret_value,
                   step=5, timeout=120, ignore_exceptions=(binascii.Error,))
 
 
 # STEP
-@then(u'Secret contains "{secret_key}" key with dynamic IP addess as the value')
-def check_secret_key_with_ip_value(context, secret_key):
+@then(u'Secret "{secret_name}" contains "{secret_key}" key with dynamic IP addess as the value')
+def check_secret_key_with_ip_value(context, secret_name, secret_key):
     openshift = Openshift()
-    secret = polling2.poll(lambda: get_sbr_secret_name(context), step=100, timeout=1000, ignore_exceptions=(ValueError,), check_success=lambda v: v is not None)
     json_path = f'{{.data.{secret_key}}}'
     polling2.poll(lambda: ipaddress.ip_address(
-        openshift.get_resource_info_by_jsonpath("secrets", secret, context.namespace.name, json_path)),
+        openshift.get_resource_info_by_jsonpath("secrets", secret_name, context.namespace.name, json_path)),
         step=5, timeout=120, ignore_exceptions=(ValueError,))
 
 
@@ -426,11 +410,10 @@ def delete_yaml(context):
     assert result is not None, f"Unable to delete CR '{metadata_name}': {output}"
 
 
-@then(u'Secret has been injected in to CR "{cr_name}" of kind "{crd_name}" at path "{json_path}"')
-def verify_injected_secretRef(context, cr_name, crd_name, json_path):
+@then(u'Secret "{secret_ref}" has been injected in to CR "{cr_name}" of kind "{crd_name}" at path "{json_path}"')
+def verify_injected_secretRef(context, secret_ref, cr_name, crd_name, json_path):
     openshift = Openshift()
-    secret = polling2.poll(lambda: get_sbr_secret_name(context), step=100, timeout=1000, ignore_exceptions=(ValueError,), check_success=lambda v: v is not None)
-    polling2.poll(lambda: openshift.get_resource_info_by_jsonpath(crd_name, cr_name, context.namespace.name, json_path) == secret,
+    polling2.poll(lambda: openshift.get_resource_info_by_jsonpath(crd_name, cr_name, context.namespace.name, json_path) == secret_ref,
                   step=5, timeout=400)
 
 
@@ -501,43 +484,23 @@ def validate_persistent_sb(context, sb_name):
         assert False, "Service Binding got updated"
 
 
-@then(u'Secret does not contain "{key}"')
-def check_secret_key(context, key):
+@given(u'Secret "{secret_name}" does not contain "{key}"')
+def check_secret_key(context, secret_name, key):
     openshift = Openshift()
-    secret = polling2.poll(lambda: get_sbr_secret_name(context), step=100, timeout=1000, ignore_exceptions=(ValueError,), check_success=lambda v: v is not None)
     json_path = f'{{.data.{key}}}'
-    polling2.poll(lambda: openshift.get_resource_info_by_jsonpath("secrets", secret, context.namespace.name,
+    polling2.poll(lambda: openshift.get_resource_info_by_jsonpath("secrets", secret_name, context.namespace.name,
                                                                   json_path) == "",
                   step=5, timeout=120, ignore_exceptions=(binascii.Error,))
 
 
-@step(u'Secret is empty')
-def validate_secret_empty(context):
+@step(u'Secret "{secret_name}" is empty')
+def validate_secret_empty(context, secret_name):
     openshift = Openshift()
-    if "sbr_name" in context:
-        secret = polling2.poll(lambda: get_sbr_secret_name(context), step=100, timeout=1000, ignore_exceptions=(ValueError,),
-                               check_success=lambda v: v is not None)
-        try:
-            polling2.poll(lambda: json.loads(
-                openshift.get_resource_info_by_jq("secrets", secret, context.namespace.name, ".data", wait=False)) == "null",
-                          step=5, timeout=20, ignore_exceptions=(json.JSONDecodeError,))
-        except polling2.TimeoutException:
-            pass
-    else:
-        assert False, "sbr_name not in context"
-
-
-@then(u'The application got redeployed {count} times so far')
-def check_generation(context, count):
-    context.latest_application_generation = context.application.get_generation()
-    assert context.latest_application_generation - context.original_application_generation == int(count), "Unexpected number of application redeployments"
-
-
-@then(u'The application does not get redeployed again with {time} minutes')
-def check_no_redeployment(context, time):
     try:
-        polling2.poll(lambda: context.application.get_generation() > context.latest_application_generation, step=5, timeout=int(time)*60)
-        assert False, "Application has redeployed again unexpectedly"
+        polling2.poll(lambda: json.loads(
+            openshift.get_resource_info_by_jq("secrets", secret_name, context.namespace.name, ".data",
+                                              wait=False)) == "null", step=5, timeout=20,
+                      ignore_exceptions=(json.JSONDecodeError,))
     except polling2.TimeoutException:
         pass
 
@@ -547,13 +510,3 @@ def create_deployment(context, app_name, image_ref):
     app = App(app_name, context.namespace.name, image_ref)
     if not app.is_running():
         assert app.install() is True, "Failed to create deployment."
-
-
-@given(u'Binding secret is updated')
-def update_binding_secret(context):
-    openshift = Openshift()
-    secret_yaml = yaml.full_load(context.text)
-    secret_yaml["metadata"]["name"] = context.sb_secret
-    output = openshift.apply(yaml.dump(secret_yaml), context.namespace.name)
-    result = re.search(rf'.*{context.sb_secret}.*(created|unchanged|configured)', output)
-    assert result is not None, f"Unable to apply YAML for binding secret '{context.sb_secret}': {output}"