Repository: redhat-developer/service-binding-operator
Pull request #437 (2020-04-23 15:12:34)

Remove redundant checking
The ApplocationNotFound is not propagated to the reconciler as an error. Remove redundant checking

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 **avni-sharma**
You can assign the PR to them by writing `/assign @avni-sharma` 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":["avni-sharma"]} -->
baijum: /lgtm
/approve
openshift-ci-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/redhat-developer/service-binding-operator/pull/437#issuecomment-618479189" title="Approved">baijum</a>*

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).

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

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

- ~~[OWNERS](https://github.com/redhat-developer/service-binding-operator/blob/master/OWNERS)~~ [baijum]

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":[]} -->

Patch:
diff --git a/deploy/crds/apps.openshift.io_servicebindingrequests_crd.yaml b/deploy/crds/apps.openshift.io_servicebindingrequests_crd.yaml
index 7b6a4688..e1d738ee 100644
--- a/deploy/crds/apps.openshift.io_servicebindingrequests_crd.yaml
+++ b/deploy/crds/apps.openshift.io_servicebindingrequests_crd.yaml
@@ -114,6 +114,8 @@ spec:
                   type: string
                 version:
                   type: string
+                envVarPrefix:
+                  type: string
               required:
               - group
               - kind
@@ -138,6 +140,8 @@ spec:
                     type: string
                   version:
                     type: string
+                  envVarPrefix:
+                    type: string
                 required:
                 - group
                 - kind
diff --git a/pkg/apis/apps/v1alpha1/servicebindingrequest_types.go b/pkg/apis/apps/v1alpha1/servicebindingrequest_types.go
index 7ecb280b..858f2f5c 100644
--- a/pkg/apis/apps/v1alpha1/servicebindingrequest_types.go
+++ b/pkg/apis/apps/v1alpha1/servicebindingrequest_types.go
@@ -66,7 +66,8 @@ type BackingServiceSelector struct {
 	metav1.GroupVersionKind `json:",inline"`
 	ResourceRef             string `json:"resourceRef"`
 	// +optional
-	Namespace *string `json:"namespace,omitempty"`
+	Namespace    *string `json:"namespace,omitempty"`
+	EnvVarPrefix *string `json:"envVarPrefix,omitempty"`
 }
 
 // BoundApplication defines the application workloads to which the binding secret has
diff --git a/pkg/controller/servicebindingrequest/binding.go b/pkg/controller/servicebindingrequest/binding.go
index 8e35e8f2..760db507 100644
--- a/pkg/controller/servicebindingrequest/binding.go
+++ b/pkg/controller/servicebindingrequest/binding.go
@@ -328,7 +328,7 @@ func BuildServiceBinder(options *ServiceBinderOptions) (*ServiceBinder, error) {
 
 	// read bindable data from the specified resources
 	if options.DetectBindingResources {
-		err := retriever.ReadBindableResourcesData(&plan.SBR, rs)
+		err := retriever.ReadBindableResourcesData(&plan.SBR, plan.GetRelatedResources())
 		if err != nil {
 			return nil, err
 		}
@@ -336,7 +336,7 @@ func BuildServiceBinder(options *ServiceBinderOptions) (*ServiceBinder, error) {
 
 	// read bindable data from the CRDDescription found by the planner
 	for _, r := range plan.GetRelatedResources() {
-		err = retriever.ReadCRDDescriptionData(r.CR, r.CRDDescription)
+		err = retriever.ReadCRDDescriptionData(r.EnvVarPrefix, r.CR, r.CRDDescription)
 		if err != nil {
 			return nil, err
 		}
diff --git a/pkg/controller/servicebindingrequest/planner.go b/pkg/controller/servicebindingrequest/planner.go
index 642213a5..fc5dc5a9 100644
--- a/pkg/controller/servicebindingrequest/planner.go
+++ b/pkg/controller/servicebindingrequest/planner.go
@@ -144,6 +144,7 @@ func (p *Planner) Plan() (*Plan, error) {
 		r := &RelatedResource{
 			CRDDescription: crdDescription,
 			CR:             cr,
+			EnvVarPrefix:   s.EnvVarPrefix,
 		}
 		relatedResources = append(relatedResources, r)
 		p.logger.Debug("Resolved related resource", "RelatedResource", r)
diff --git a/pkg/controller/servicebindingrequest/reconciler.go b/pkg/controller/servicebindingrequest/reconciler.go
index 0c6df2a8..32b9f5dd 100644
--- a/pkg/controller/servicebindingrequest/reconciler.go
+++ b/pkg/controller/servicebindingrequest/reconciler.go
@@ -155,8 +155,6 @@ func (r *Reconciler) Reconcile(request reconcile.Request) (reconcile.Result, err
 			var reason string
 			if errors.Is(err, EmptyBackingServiceSelectorsErr) {
 				reason = "EmptyBackingServiceSelectors"
-			} else if errors.Is(err, ApplicationNotFound) {
-				reason = "ApplicationUnavailable"
 			} else {
 				reason = "EmptyApplicationSelector"
 			}
diff --git a/pkg/controller/servicebindingrequest/related_resources.go b/pkg/controller/servicebindingrequest/related_resources.go
index 3f0dfb72..288aba56 100644
--- a/pkg/controller/servicebindingrequest/related_resources.go
+++ b/pkg/controller/servicebindingrequest/related_resources.go
@@ -9,6 +9,7 @@ import (
 type RelatedResource struct {
 	CRDDescription *v1alpha1.CRDDescription
 	CR             *unstructured.Unstructured
+	EnvVarPrefix   *string
 }
 
 // RelatedResources contains a collection of SBR related resources.
diff --git a/pkg/controller/servicebindingrequest/retrieve_decoupled.go b/pkg/controller/servicebindingrequest/retrieve_decoupled.go
index cedc88e5..286a9ac9 100644
--- a/pkg/controller/servicebindingrequest/retrieve_decoupled.go
+++ b/pkg/controller/servicebindingrequest/retrieve_decoupled.go
@@ -36,11 +36,11 @@ func (r *Retriever) Get() (map[string][]byte, error) {
 // ReadBindableResourcesData reads all related resources of a given sbr
 func (r *Retriever) ReadBindableResourcesData(
 	sbr *v1alpha1.ServiceBindingRequest,
-	crs []*unstructured.Unstructured,
+	relatedResources RelatedResources,
 ) error {
 	r.logger.Info("Detecting extra resources for binding...")
-	for _, cr := range crs {
-		b := NewDetectBindableResources(sbr, cr, []schema.GroupVersionResource{
+	for _, rs := range ([]*RelatedResource)(relatedResources) {
+		b := NewDetectBindableResources(sbr, rs.CR, []schema.GroupVersionResource{
 			{Group: "", Version: "v1", Resource: "configmaps"},
 			{Group: "", Version: "v1", Resource: "services"},
 			{Group: "route.openshift.io", Version: "v1", Resource: "routes"},
@@ -51,36 +51,36 @@ func (r *Retriever) ReadBindableResourcesData(
 			return err
 		}
 		for k, v := range vals {
-			r.storeInto(cr, k, []byte(fmt.Sprintf("%v", v)))
+			r.storeInto(rs.EnvVarPrefix, rs.CR, k, []byte(fmt.Sprintf("%v", v)))
 		}
 	}
 
 	return nil
 }
 
-func (r *Retriever) storeInto(cr *unstructured.Unstructured, key string, value []byte) {
-	r.store(cr, key, value)
+func (r *Retriever) storeInto(envVarPrefix *string, cr *unstructured.Unstructured, key string, value []byte) {
+	r.store(envVarPrefix, cr, key, value)
 }
 
-func (r *Retriever) copyFrom(u *unstructured.Unstructured, path string, fieldPath string, descriptors []string) error {
-	if err := r.read(u, path, fieldPath, descriptors); err != nil {
+func (r *Retriever) copyFrom(envVarPrefix *string, u *unstructured.Unstructured, path string, fieldPath string, descriptors []string) error {
+	if err := r.read(envVarPrefix, u, path, fieldPath, descriptors); err != nil {
 		return err
 	}
 	return nil
 }
 
 // ReadCRDDescriptionData reads data related to given crdDescription
-func (r *Retriever) ReadCRDDescriptionData(u *unstructured.Unstructured, crdDescription *olmv1alpha1.CRDDescription) error {
+func (r *Retriever) ReadCRDDescriptionData(envVarPrefix *string, u *unstructured.Unstructured, crdDescription *olmv1alpha1.CRDDescription) error {
 	r.logger.Info("Looking for spec-descriptors in 'spec'...")
 	for _, specDescriptor := range crdDescription.SpecDescriptors {
-		if err := r.copyFrom(u, "spec", specDescriptor.Path, specDescriptor.XDescriptors); err != nil {
+		if err := r.copyFrom(envVarPrefix, u, "spec", specDescriptor.Path, specDescriptor.XDescriptors); err != nil {
 			return err
 		}
 	}
 
 	r.logger.Info("Looking for status-descriptors in 'status'...")
 	for _, statusDescriptor := range crdDescription.StatusDescriptors {
-		if err := r.copyFrom(u, "status", statusDescriptor.Path, statusDescriptor.XDescriptors); err != nil {
+		if err := r.copyFrom(envVarPrefix, u, "status", statusDescriptor.Path, statusDescriptor.XDescriptors); err != nil {
 			return err
 		}
 	}
diff --git a/pkg/controller/servicebindingrequest/retriever.go b/pkg/controller/servicebindingrequest/retriever.go
index 0a5d50b0..b59055ab 100644
--- a/pkg/controller/servicebindingrequest/retriever.go
+++ b/pkg/controller/servicebindingrequest/retriever.go
@@ -76,7 +76,7 @@ func (r *Retriever) getCRKey(u *unstructured.Unstructured, section string, key s
 // read attributes from CR, where place means which top level key name contains the "path" actual
 // value, and parsing x-descriptors in order to either directly read CR data, or read items from
 // a secret.
-func (r *Retriever) read(cr *unstructured.Unstructured, place, path string, xDescriptors []string) error {
+func (r *Retriever) read(envVarPrefix *string, cr *unstructured.Unstructured, place, path string, xDescriptors []string) error {
 	log := r.logger.WithValues(
 		"CR.Section", place,
 		"CRDDescription.Path", path,
@@ -114,7 +114,7 @@ func (r *Retriever) read(cr *unstructured.Unstructured, place, path string, xDes
 			r.markVisitedPaths(r.extractSecretItemName(xDescriptor), pathValue, place)
 			r.VolumeKeys = append(r.VolumeKeys, pathValue)
 		} else if strings.HasPrefix(xDescriptor, attributePrefix) {
-			r.store(cr, path, []byte(pathValue))
+			r.store(envVarPrefix, cr, path, []byte(pathValue))
 		} else {
 			log.Debug("Defaulting....")
 		}
@@ -122,14 +122,14 @@ func (r *Retriever) read(cr *unstructured.Unstructured, place, path string, xDes
 
 	for name, items := range secrets {
 		// loading secret items all-at-once
-		err := r.readSecret(cr, name, items, place, path)
+		err := r.readSecret(envVarPrefix, cr, name, items, place, path)
 		if err != nil {
 			return err
 		}
 	}
 	for name, items := range configMaps {
 		// add the function readConfigMap
-		err := r.readConfigMap(cr, name, items, place, path)
+		err := r.readConfigMap(envVarPrefix, cr, name, items, place, path)
 		if err != nil {
 			return err
 		}
@@ -167,7 +167,7 @@ func (r *Retriever) markVisitedPaths(name, keyPath, fromPath string) {
 
 // readSecret based in secret name and list of items, read a secret from the same namespace informed
 // in plan instance.
-func (r *Retriever) readSecret(cr *unstructured.Unstructured, name string, items []string, fromPath string, path string) error {
+func (r *Retriever) readSecret(envVarPrefix *string, cr *unstructured.Unstructured, name string, items []string, fromPath string, path string) error {
 	log := r.logger.WithValues("Secret.Name", name, "Secret.Items", items)
 	log.Debug("Reading secret items...")
 
@@ -197,7 +197,13 @@ func (r *Retriever) readSecret(cr *unstructured.Unstructured, name string, items
 		// update cache after reading configmap/secret in cache
 		r.cache[fromPath].(map[string]interface{})[path].(map[string]interface{})[k] = string(data)
 		// making sure key name has a secret reference
-		r.store(cr, fmt.Sprintf("secret_%s", k), data)
+		if envVarPrefix != nil && *envVarPrefix == "" {
+			r.store(envVarPrefix, cr, k, data)
+
+		} else {
+			r.store(envVarPrefix, cr, fmt.Sprintf("secret_%s", k), data)
+
+		}
 	}
 
 	r.Objects = append(r.Objects, secret)
@@ -206,7 +212,7 @@ func (r *Retriever) readSecret(cr *unstructured.Unstructured, name string, items
 
 // readConfigMap based in configMap name and list of items, read a configMap from the same namespace informed
 // in plan instance.
-func (r *Retriever) readConfigMap(cr *unstructured.Unstructured, name string, items []string, fromPath string, path string) error {
+func (r *Retriever) readConfigMap(envVarPrefix *string, cr *unstructured.Unstructured, name string, items []string, fromPath string, path string) error {
 	log := r.logger.WithValues("ConfigMap.Name", name, "ConfigMap.Items", items)
 	log.Debug("Reading ConfigMap items...")
 
@@ -235,7 +241,11 @@ func (r *Retriever) readConfigMap(cr *unstructured.Unstructured, name string, it
 		// update cache after reading configmap/secret in cache
 		r.cache[fromPath].(map[string]interface{})[path].(map[string]interface{})[k] = value
 		// making sure key name has a configMap reference
-		r.store(cr, fmt.Sprintf("configMap_%s", k), []byte(value))
+		if envVarPrefix != nil && *envVarPrefix == "" {
+			r.store(envVarPrefix, cr, k, []byte(value))
+		} else {
+			r.store(envVarPrefix, cr, fmt.Sprintf("configMap_%s", k), []byte(value))
+		}
 	}
 
 	r.Objects = append(r.Objects, u)
@@ -243,13 +253,25 @@ func (r *Retriever) readConfigMap(cr *unstructured.Unstructured, name string, it
 }
 
 // store key and value, formatting key to look like an environment variable.
-func (r *Retriever) store(u *unstructured.Unstructured, key string, value []byte) {
+func (r *Retriever) store(envVarPrefix *string, u *unstructured.Unstructured, key string, value []byte) {
 	key = strings.ReplaceAll(key, ":", "_")
 	key = strings.ReplaceAll(key, ".", "_")
-	if r.bindingPrefix == "" {
-		key = fmt.Sprintf("%s_%s", u.GetKind(), key)
+	if envVarPrefix == nil {
+		if r.bindingPrefix == "" {
+			key = fmt.Sprintf("%s_%s", u.GetKind(), key)
+		} else {
+			key = fmt.Sprintf("%s_%s_%s", r.bindingPrefix, u.GetKind(), key)
+		}
+	} else if *envVarPrefix == "" {
+		if r.bindingPrefix != "" {
+			key = fmt.Sprintf("%s_%s", r.bindingPrefix, key)
+		}
 	} else {
-		key = fmt.Sprintf("%s_%s_%s", r.bindingPrefix, u.GetKind(), key)
+		if r.bindingPrefix != "" {
+			key = fmt.Sprintf("%s_%s_%s", r.bindingPrefix, *envVarPrefix, key)
+		} else {
+			key = fmt.Sprintf("%s_%s", *envVarPrefix, key)
+		}
 	}
 	key = strings.ToUpper(key)
 	r.data[key] = value


Test patch:
diff --git a/pkg/controller/servicebindingrequest/retriever_test.go b/pkg/controller/servicebindingrequest/retriever_test.go
index 607e833a..0f3411fd 100644
--- a/pkg/controller/servicebindingrequest/retriever_test.go
+++ b/pkg/controller/servicebindingrequest/retriever_test.go
@@ -16,6 +16,8 @@ func TestRetriever(t *testing.T) {
 	ns := "testing"
 	backingServiceNs := "backing-servicec-ns"
 	crName := "db-testing"
+	testEnvVarPrefix := "TEST_PREFIX"
+	emptyEnvVarPrefix := ""
 
 	f := mocks.NewFake(t, ns)
 	f.AddMockedUnstructuredCSV("csv")
@@ -56,24 +58,24 @@ func TestRetriever(t *testing.T) {
 
 	t.Run("read", func(t *testing.T) {
 		// reading from secret, from status attribute
-		err := retriever.read(cr, "status", "dbCredentials", []string{
+		err := retriever.read(&testEnvVarPrefix, cr, "status", "dbCredentials", []string{
 			"binding:env:object:secret:user",
 			"binding:env:object:secret:password",
 		})
 		require.NoError(t, err)
 
 		t.Logf("retriever.data '%#v'", retriever.data)
-		require.Contains(t, retriever.data, "SERVICE_BINDING_DATABASE_SECRET_USER")
-		require.Contains(t, retriever.data, "SERVICE_BINDING_DATABASE_SECRET_PASSWORD")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_TEST_PREFIX_SECRET_USER")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_TEST_PREFIX_SECRET_PASSWORD")
 
 		// reading from spec attribute
-		err = retriever.read(cr, "spec", "image", []string{
+		err = retriever.read(&testEnvVarPrefix, cr, "spec", "image", []string{
 			"binding:env:attribute",
 		})
 		require.NoError(t, err)
 
 		t.Logf("retriever.data '%#v'", retriever.data)
-		require.Contains(t, retriever.data, "SERVICE_BINDING_DATABASE_IMAGE")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_TEST_PREFIX_IMAGE")
 
 	})
 
@@ -85,30 +87,86 @@ func TestRetriever(t *testing.T) {
 	t.Run("readSecret", func(t *testing.T) {
 		retriever.data = make(map[string][]byte)
 
-		err := retriever.readSecret(cr, "db-credentials", []string{"user", "password"}, "spec", "dbConfigMap")
+		err := retriever.readSecret(&testEnvVarPrefix, cr, "db-credentials", []string{"user", "password"}, "spec", "dbConfigMap")
 		require.NoError(t, err)
 
-		require.Contains(t, retriever.data, "SERVICE_BINDING_DATABASE_SECRET_USER")
-		require.Contains(t, retriever.data, "SERVICE_BINDING_DATABASE_SECRET_PASSWORD")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_TEST_PREFIX_SECRET_USER")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_TEST_PREFIX_SECRET_PASSWORD")
 	})
 
 	t.Run("store", func(t *testing.T) {
-		retriever.store(cr, "test", []byte("test"))
-		require.Contains(t, retriever.data, "SERVICE_BINDING_DATABASE_TEST")
-		require.Equal(t, []byte("test"), retriever.data["SERVICE_BINDING_DATABASE_TEST"])
+		retriever.store(&testEnvVarPrefix, cr, "test", []byte("test"))
+		require.Contains(t, retriever.data, "SERVICE_BINDING_TEST_PREFIX_TEST")
+		require.Equal(t, []byte("test"), retriever.data["SERVICE_BINDING_TEST_PREFIX_TEST"])
 	})
 
-	t.Run("empty prefix", func(t *testing.T) {
+	t.Run("non-empty SBR prefix and nil service prefix", func(t *testing.T) {
+		retriever = NewRetriever(fakeDynClient, plan, "SERVICE_BINDING")
+		require.NotNil(t, retriever)
+		retriever.data = make(map[string][]byte)
+
+		err := retriever.readSecret(nil, cr, "db-credentials", []string{"user", "password"}, "spec", "dbConfigMap")
+		require.NoError(t, err)
+
+		require.Contains(t, retriever.data, "SERVICE_BINDING_DATABASE_SECRET_USER")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_DATABASE_SECRET_PASSWORD")
+	})
+	t.Run("empty SBR prefix and nil service prefix", func(t *testing.T) {
 		retriever = NewRetriever(fakeDynClient, plan, "")
 		require.NotNil(t, retriever)
 		retriever.data = make(map[string][]byte)
 
-		err := retriever.readSecret(cr, "db-credentials", []string{"user", "password"}, "spec", "dbConfigMap")
+		err := retriever.readSecret(nil, cr, "db-credentials", []string{"user", "password"}, "spec", "dbConfigMap")
 		require.NoError(t, err)
 
 		require.Contains(t, retriever.data, "DATABASE_SECRET_USER")
 		require.Contains(t, retriever.data, "DATABASE_SECRET_PASSWORD")
 	})
+
+	t.Run("non-empty SBR prefix and non-empty service prefix", func(t *testing.T) {
+		retriever = NewRetriever(fakeDynClient, plan, "SERVICE_BINDING")
+		require.NotNil(t, retriever)
+		retriever.data = make(map[string][]byte)
+
+		err := retriever.readSecret(&testEnvVarPrefix, cr, "db-credentials", []string{"user", "password"}, "spec", "dbConfigMap")
+		require.NoError(t, err)
+
+		require.Contains(t, retriever.data, "SERVICE_BINDING_TEST_PREFIX_SECRET_USER")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_TEST_PREFIX_SECRET_PASSWORD")
+	})
+	t.Run("non-empty SBR prefix and empty service prefix", func(t *testing.T) {
+		retriever = NewRetriever(fakeDynClient, plan, "SERVICE_BINDING")
+		require.NotNil(t, retriever)
+		retriever.data = make(map[string][]byte)
+
+		err := retriever.readSecret(&emptyEnvVarPrefix, cr, "db-credentials", []string{"user", "password"}, "spec", "dbConfigMap")
+		require.NoError(t, err)
+
+		require.Contains(t, retriever.data, "SERVICE_BINDING_USER")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_PASSWORD")
+	})
+	t.Run("empty SBR prefix and non-empty service prefix", func(t *testing.T) {
+		retriever = NewRetriever(fakeDynClient, plan, "")
+		require.NotNil(t, retriever)
+		retriever.data = make(map[string][]byte)
+
+		err := retriever.readSecret(&testEnvVarPrefix, cr, "db-credentials", []string{"user", "password"}, "spec", "dbConfigMap")
+		require.NoError(t, err)
+
+		require.Contains(t, retriever.data, "TEST_PREFIX_SECRET_USER")
+		require.Contains(t, retriever.data, "TEST_PREFIX_SECRET_PASSWORD")
+	})
+	t.Run("empty SBR prefix and empty service prefix", func(t *testing.T) {
+		retriever = NewRetriever(fakeDynClient, plan, "")
+		require.NotNil(t, retriever)
+		retriever.data = make(map[string][]byte)
+
+		err := retriever.readSecret(&emptyEnvVarPrefix, cr, "db-credentials", []string{"user", "password"}, "spec", "dbConfigMap")
+		require.NoError(t, err)
+
+		require.Contains(t, retriever.data, "USER")
+		require.Contains(t, retriever.data, "PASSWORD")
+	})
 }
 
 func TestRetrieverWithNestedCRKey(t *testing.T) {
@@ -168,6 +226,8 @@ func TestRetrieverWithConfigMap(t *testing.T) {
 
 	ns := "testing"
 	crName := "db-testing"
+	testEnvVarPrefix := "TEST_PREFIX"
+	emptyEnvVarPrefix := ""
 
 	f := mocks.NewFake(t, ns)
 	f.AddMockedUnstructuredCSV("csv")
@@ -197,15 +257,15 @@ func TestRetrieverWithConfigMap(t *testing.T) {
 
 	t.Run("read", func(t *testing.T) {
 		// reading from configMap, from status attribute
-		err = retriever.read(cr, "spec", "dbConfigMap", []string{
+		err = retriever.read(&testEnvVarPrefix, cr, "spec", "dbConfigMap", []string{
 			"binding:env:object:configmap:user",
 			"binding:env:object:configmap:password",
 		})
 		require.NoError(t, err)
 
 		t.Logf("retriever.data '%#v'", retriever.data)
-		require.Contains(t, retriever.data, "SERVICE_BINDING_DATABASE_CONFIGMAP_USER")
-		require.Contains(t, retriever.data, "SERVICE_BINDING_DATABASE_CONFIGMAP_PASSWORD")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_TEST_PREFIX_CONFIGMAP_USER")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_TEST_PREFIX_CONFIGMAP_PASSWORD")
 	})
 
 	t.Run("extractConfigMapItemName", func(t *testing.T) {
@@ -216,10 +276,78 @@ func TestRetrieverWithConfigMap(t *testing.T) {
 	t.Run("readConfigMap", func(t *testing.T) {
 		retriever.data = make(map[string][]byte)
 
-		err := retriever.readConfigMap(cr, crName, []string{"user", "password"}, "spec", "dbConfigMap")
+		err := retriever.readConfigMap(&testEnvVarPrefix, cr, crName, []string{"user", "password"}, "spec", "dbConfigMap")
+		require.NoError(t, err)
+
+		require.Contains(t, retriever.data, ("SERVICE_BINDING_TEST_PREFIX_CONFIGMAP_USER"))
+		require.Contains(t, retriever.data, ("SERVICE_BINDING_TEST_PREFIX_CONFIGMAP_PASSWORD"))
+	})
+
+	t.Run("non-empty SBR prefix and nil service prefix", func(t *testing.T) {
+		retriever = NewRetriever(fakeDynClient, plan, "SERVICE_BINDING")
+		require.NotNil(t, retriever)
+		retriever.data = make(map[string][]byte)
+
+		err := retriever.readConfigMap(nil, cr, crName, []string{"user", "password"}, "spec", "dbConfigMap")
+		require.NoError(t, err)
+
+		require.Contains(t, retriever.data, "SERVICE_BINDING_DATABASE_CONFIGMAP_USER")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_DATABASE_CONFIGMAP_PASSWORD")
+	})
+	t.Run("empty SBR prefix and nil service prefix", func(t *testing.T) {
+		retriever = NewRetriever(fakeDynClient, plan, "")
+		require.NotNil(t, retriever)
+		retriever.data = make(map[string][]byte)
+
+		err := retriever.readConfigMap(nil, cr, crName, []string{"user", "password"}, "spec", "dbConfigMap")
+		require.NoError(t, err)
+
+		require.Contains(t, retriever.data, "DATABASE_CONFIGMAP_USER")
+		require.Contains(t, retriever.data, "DATABASE_CONFIGMAP_PASSWORD")
+	})
+
+	t.Run("non-empty SBR prefix and non-empty service prefix", func(t *testing.T) {
+		retriever = NewRetriever(fakeDynClient, plan, "SERVICE_BINDING")
+		require.NotNil(t, retriever)
+		retriever.data = make(map[string][]byte)
+
+		err := retriever.readConfigMap(&testEnvVarPrefix, cr, crName, []string{"user", "password"}, "spec", "dbConfigMap")
+		require.NoError(t, err)
+
+		require.Contains(t, retriever.data, "SERVICE_BINDING_TEST_PREFIX_CONFIGMAP_USER")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_TEST_PREFIX_CONFIGMAP_PASSWORD")
+	})
+	t.Run("non-empty SBR prefix and empty service prefix", func(t *testing.T) {
+		retriever = NewRetriever(fakeDynClient, plan, "SERVICE_BINDING")
+		require.NotNil(t, retriever)
+		retriever.data = make(map[string][]byte)
+
+		err := retriever.readConfigMap(&emptyEnvVarPrefix, cr, crName, []string{"user", "password"}, "spec", "dbConfigMap")
+		require.NoError(t, err)
+
+		require.Contains(t, retriever.data, "SERVICE_BINDING_USER")
+		require.Contains(t, retriever.data, "SERVICE_BINDING_PASSWORD")
+	})
+	t.Run("empty SBR prefix and non-empty service prefix", func(t *testing.T) {
+		retriever = NewRetriever(fakeDynClient, plan, "")
+		require.NotNil(t, retriever)
+		retriever.data = make(map[string][]byte)
+
+		err := retriever.readConfigMap(&testEnvVarPrefix, cr, crName, []string{"user", "password"}, "spec", "dbConfigMap")
+		require.NoError(t, err)
+
+		require.Contains(t, retriever.data, "TEST_PREFIX_CONFIGMAP_USER")
+		require.Contains(t, retriever.data, "TEST_PREFIX_CONFIGMAP_PASSWORD")
+	})
+	t.Run("empty SBR prefix and empty service prefix", func(t *testing.T) {
+		retriever = NewRetriever(fakeDynClient, plan, "")
+		require.NotNil(t, retriever)
+		retriever.data = make(map[string][]byte)
+
+		err := retriever.readConfigMap(&emptyEnvVarPrefix, cr, crName, []string{"user", "password"}, "spec", "dbConfigMap")
 		require.NoError(t, err)
 
-		require.Contains(t, retriever.data, ("SERVICE_BINDING_DATABASE_CONFIGMAP_USER"))
-		require.Contains(t, retriever.data, ("SERVICE_BINDING_DATABASE_CONFIGMAP_PASSWORD"))
+		require.Contains(t, retriever.data, "USER")
+		require.Contains(t, retriever.data, "PASSWORD")
 	})
 }