Repository: redhat-developer/service-binding-operator
Pull request #83 (2019-07-22 08:26:38)

Bind secret values as files into the container
Based on x-descriptor value in the CSV file, the secret values will be mounted as files inside the container.

Ref: https://jira.coreos.com/browse/ODC-1324

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 **baijum**
You can assign the PR to them by writing `/assign @baijum` 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":["baijum"]} -->
openshift-ci-robot: @baijum: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/e2e | 4f0fb88b36d420dfc708b2dfb29bccbdad9808c0 | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/redhat-developer_service-binding-operator/83/pull-ci-redhat-developer-service-binding-operator-master-e2e/200) | `/test e2e`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=redhat-developer&repo=service-binding-operator&pr=83). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:baijum). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/redhat-developer/service-binding-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
openshift-ci-robot: @baijum: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/e2e | b9d2b89a65b735b0c10cfe8a11725662e03b11ea | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/redhat-developer_service-binding-operator/83/pull-ci-redhat-developer-service-binding-operator-master-e2e/202) | `/test e2e`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=redhat-developer&repo=service-binding-operator&pr=83). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:baijum). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/redhat-developer/service-binding-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
openshift-ci-robot: @baijum: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/e2e | b50dbebd2a0ccf9c03e435e7ee71d8adc2e61557 | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/redhat-developer_service-binding-operator/83/pull-ci-redhat-developer-service-binding-operator-master-e2e/208) | `/test e2e`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=redhat-developer&repo=service-binding-operator&pr=83). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:baijum). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/redhat-developer/service-binding-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
baijum: /test e2e
openshift-ci-robot: @baijum: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/e2e | b50dbebd2a0ccf9c03e435e7ee71d8adc2e61557 | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/redhat-developer_service-binding-operator/83/pull-ci-redhat-developer-service-binding-operator-master-e2e/214) | `/test e2e`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=redhat-developer&repo=service-binding-operator&pr=83). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:baijum). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/redhat-developer/service-binding-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
sbose78: @baijum @otaviof @pmacik @Avni-Sharma 

Please confirm that this is the implementation we are heading towards:

Based on,

```
urn:alm:descriptor:servicebinding:volumemount:secret:username
urn:alm:descriptor:servicebinding:volumemount:secret:username
```

The DeploymentConfig's container spec would look like:

```
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/servicebindingCRname"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: service-binding-secret
      items:
      - key: username
        path: username
      - key: password
        path: password
```

This will enable these paths to be readable inside the container 
- /servicebindingCRname/username
- /servicebindingCRname/password
openshift-ci-robot: @baijum: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/e2e | 7029682196ac92c2876d301ca2929d4cae78e57b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/redhat-developer_service-binding-operator/83/pull-ci-redhat-developer-service-binding-operator-master-e2e/218) | `/test e2e`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=redhat-developer&repo=service-binding-operator&pr=83). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:baijum). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/redhat-developer/service-binding-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
baijum: /test e2e
openshift-ci-robot: @baijum: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/e2e | 935a50dc49bc80180f09481339f56367567c479a | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/redhat-developer_service-binding-operator/83/pull-ci-redhat-developer-service-binding-operator-master-e2e/223) | `/test e2e`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=redhat-developer&repo=service-binding-operator&pr=83). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:baijum). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/redhat-developer/service-binding-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
baijum: /test e2e
baijum: /hold
openshift-ci-robot: @baijum: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/e2e | 4237e56daef48f78308393774d506f0534d214b6 | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/redhat-developer_service-binding-operator/83/pull-ci-redhat-developer-service-binding-operator-master-e2e/233) | `/test e2e`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=redhat-developer&repo=service-binding-operator&pr=83). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:baijum). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/redhat-developer/service-binding-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
baijum: /test e2e
Avni-Sharma: /lgtm
baijum: /hold

I will wait for Shoubhik's approval
sbose78: @baijum Why are we using a different intermediary secret? If we used
```
volumes:
  - name: foo
    secret:
      secretName: service-binding-secret
      items:
      - key: username
        path: username
      - key: password
        path: password
```

We could ensure everything doesn't get mounted, and that should let us use a single intermediate secret for both volume mounts and `envFrom`... ?
baijum: > @baijum Why are we using a different intermediary secret? If we used
> 
> ```
> volumes:
>   - name: foo
>     secret:
>       secretName: service-binding-secret
>       items:
>       - key: username
>         path: username
>       - key: password
>         path: password
> ```
> 
> We could ensure everything doesn't get mounted, and that should let us use a single intermediate secret for both volume mounts and `envFrom`... ?

Ok, I will change the code based on this suggestion here itself.
sbose78: Thank you! Let me know if you bump into any design issues there. 
openshift-ci-robot: New changes are detected. LGTM label has been removed.
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: > Thank you! Let me know if you bump into any design issues there.

I have done this here: 6c768412f4c4f9bc271bf7cacd7552ae3101fddd

When creating env vars from secret there is no way to exclude certain values. So all values in the secret object will create an env var including that was meant for volume mount.
sbose78: > When creating env vars from secret there is no way to exclude certain values. So all values in the secret object will create an env var including that was meant for volume mount.

Unwanted byproduct :)
but we can live with that for now!
sbose78: /lgtm
sbose78: /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/83#issuecomment-516258076" title="Approved">sbose78</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)~~ [sbose78]

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":[]} -->
openshift-ci-robot: New changes are detected. LGTM label has been removed.
Avni-Sharma: /lgtm
baijum: /hold cancel

Patch:
diff --git a/deploy/crds/apps_v1alpha1_servicebindingrequest_cr.yaml b/deploy/crds/apps_v1alpha1_servicebindingrequest_cr.yaml
index 6a2d62fe..c1fbbd86 100644
--- a/deploy/crds/apps_v1alpha1_servicebindingrequest_cr.yaml
+++ b/deploy/crds/apps_v1alpha1_servicebindingrequest_cr.yaml
@@ -4,9 +4,10 @@ kind: ServiceBindingRequest
 metadata:
   name: example-servicebindingrequest
 spec:
+  mountPathPrefix: "/var/credentials"
   backingServiceSelector:
     resourceRef: pg-instance
-    resourceName: database.example.org
+    resourceName: databases.example.org
     resourceVersion: v1alpha1
   applicationSelector:
     matchLabels:
diff --git a/pkg/controller/servicebindingrequest/reconciler.go b/pkg/controller/servicebindingrequest/reconciler.go
index 1434f64d..6aa9058c 100644
--- a/pkg/controller/servicebindingrequest/reconciler.go
+++ b/pkg/controller/servicebindingrequest/reconciler.go
@@ -42,6 +42,49 @@ func (r *Reconciler) appendEnvFrom(envList []corev1.EnvFromSource, secret string
 	})
 }
 
+// appendVolumeMounts append volume mounts pointing to volumes created using secret
+func (r *Reconciler) appendVolumeMounts(vmList []corev1.VolumeMount, volumeName, mountPath string) []corev1.VolumeMount {
+	for _, vm := range vmList {
+		if vm.Name == volumeName {
+			// volume name already referenced
+			return vmList
+		}
+	}
+
+	return append(vmList, corev1.VolumeMount{
+		Name:      volumeName,
+		MountPath: mountPath,
+	})
+}
+
+// appendVolumes append volumes
+func (r *Reconciler) appendVolumes(volumeList []corev1.Volume, data map[string][]byte, volumeKeys []string, volumeName, secretName string) []corev1.Volume {
+	for _, vm := range volumeList {
+		if vm.Name == volumeName {
+			// volume name already referenced
+			return volumeList
+		}
+	}
+
+	items := []corev1.KeyToPath{}
+	for _, k := range volumeKeys {
+		items = append(items, corev1.KeyToPath{
+			Key:  k,
+			Path: k,
+		})
+	}
+
+	return append(volumeList, corev1.Volume{
+		Name: volumeName,
+		VolumeSource: corev1.VolumeSource{
+			Secret: &corev1.SecretVolumeSource{
+				SecretName: secretName,
+				Items:      items,
+			},
+		},
+	})
+}
+
 // Reconcile a ServiceBindingRequest by the following steps:
 // 1. Inspecting SBR in order to identify backend service. The service is composed by a CRD name and
 //    kind, and by inspecting "connects-to" label identify the name of service instance;
@@ -113,11 +156,24 @@ func (r *Reconciler) Reconcile(request reconcile.Request) (reconcile.Result, err
 				Info("Inspecting DeploymentConfig object...")
 
 			for i, c := range deploymentConfigObj.Spec.Template.Spec.Containers {
-				logger.Info("Adding EnvFrom to container")
-				deploymentConfigObj.Spec.Template.Spec.Containers[i].EnvFrom = r.appendEnvFrom(
-					c.EnvFrom, instance.GetName())
+				if len(retriever.data) > 0 {
+					logger.Info("Adding EnvFrom to container")
+					deploymentConfigObj.Spec.Template.Spec.Containers[i].EnvFrom = r.appendEnvFrom(
+						c.EnvFrom, instance.GetName())
+				}
+				if len(retriever.volumeKeys) > 0 {
+					logger.Info("Adding VolumeMounts to container")
+					mountPath := "/var/data"
+					if instance.Spec.MountPathPrefix != "" {
+						mountPath = instance.Spec.MountPathPrefix
+					}
+					deploymentConfigObj.Spec.Template.Spec.Containers[i].VolumeMounts = r.appendVolumeMounts(
+						c.VolumeMounts, instance.GetName(), mountPath)
+					logger.Info("Adding Volumes to pod")
+					deploymentConfigObj.Spec.Template.Spec.Volumes = r.appendVolumes(
+						deploymentConfigObj.Spec.Template.Spec.Volumes, retriever.data, retriever.volumeKeys, instance.GetName(), instance.GetName())
+				}
 			}
-
 			logger.Info("Updating DeploymentConfig object")
 			err = r.client.Update(ctx, &deploymentConfigObj)
 			if err != nil {
@@ -144,9 +200,24 @@ func (r *Reconciler) Reconcile(request reconcile.Request) (reconcile.Result, err
 			logger.Info("Inspecting Deploymen object...")
 
 			for i, c := range deploymentObj.Spec.Template.Spec.Containers {
-				logger.Info("Adding EnvFrom to container")
-				deploymentObj.Spec.Template.Spec.Containers[i].EnvFrom = r.appendEnvFrom(
-					c.EnvFrom, instance.GetName())
+				if len(retriever.data) > 0 {
+					logger.Info("Adding EnvFrom to container")
+					deploymentObj.Spec.Template.Spec.Containers[i].EnvFrom = r.appendEnvFrom(
+						c.EnvFrom, instance.GetName())
+				}
+				if len(retriever.volumeKeys) > 0 {
+					logger.Info("Adding VolumeMounts to container")
+					mountPath := "/var/data"
+					if instance.Spec.MountPathPrefix != "" {
+						mountPath = instance.Spec.MountPathPrefix
+					}
+					deploymentObj.Spec.Template.Spec.Containers[i].VolumeMounts = r.appendVolumeMounts(
+						c.VolumeMounts, instance.GetName(), mountPath)
+					logger.Info("Adding Volumes to pod")
+					deploymentObj.Spec.Template.Spec.Volumes = r.appendVolumes(
+						deploymentObj.Spec.Template.Spec.Volumes, retriever.data, retriever.volumeKeys, instance.GetName(), instance.GetName())
+				}
+
 			}
 
 			logger.Info("Updating Deployment object")
diff --git a/pkg/controller/servicebindingrequest/retriever.go b/pkg/controller/servicebindingrequest/retriever.go
index 36780dfc..a0ad90ec 100644
--- a/pkg/controller/servicebindingrequest/retriever.go
+++ b/pkg/controller/servicebindingrequest/retriever.go
@@ -17,18 +17,21 @@ import (
 
 // Retriever reads all data referred in plan instance, and store in a secret.
 type Retriever struct {
-	ctx    context.Context   // request context
-	client client.Client     // Kubernetes API client
-	plan   *planner.Plan     // plan instance
-	logger logr.Logger       // logger instance
-	data   map[string][]byte // data retrieved
+	ctx        context.Context   // request context
+	client     client.Client     // Kubernetes API client
+	plan       *planner.Plan     // plan instance
+	logger     logr.Logger       // logger instance
+	data       map[string][]byte // data retrieved
+	volumeKeys []string
 }
 
 const (
-	bindingPrefix   = "SERVICE_BINDING"
-	basePrefix      = "urn:alm:descriptor:servicebindingrequest:env:object"
-	secretPrefix    = basePrefix + ":secret"
-	configMapPrefix = basePrefix + ":configmap"
+	bindingPrefix           = "SERVICE_BINDING"
+	basePrefix              = "urn:alm:descriptor:servicebindingrequest:env:object"
+	secretPrefix            = basePrefix + ":secret"
+	configMapPrefix         = basePrefix + ":configmap"
+	attributePrefix         = "urn:alm:descriptor:servicebindingrequest:env:attribute"
+	volumeMountSecretPrefix = "urn:alm:descriptor:servicebindingrequest:volumemount:secret"
 )
 
 // getNestedValue retrieve value from dotted key path
@@ -76,6 +79,7 @@ func (r *Retriever) read(place, path string, xDescriptors []string) error {
 
 	// holds the secret name and items
 	secrets := make(map[string][]string)
+
 	// holds the configMap name and items
 	configMaps := make(map[string][]string)
 	for _, xDescriptor := range xDescriptors {
@@ -90,7 +94,10 @@ func (r *Retriever) read(place, path string, xDescriptors []string) error {
 			secrets[pathValue] = append(secrets[pathValue], r.extractSecretItemName(xDescriptor))
 		} else if strings.HasPrefix(xDescriptor, configMapPrefix) {
 			configMaps[pathValue] = append(configMaps[pathValue], r.extractConfigMapItemName(xDescriptor))
-		} else {
+		} else if strings.HasPrefix(xDescriptor, volumeMountSecretPrefix) {
+			secrets[pathValue] = append(secrets[pathValue], r.extractSecretItemName(xDescriptor))
+			r.volumeKeys = append(r.volumeKeys, pathValue)
+		} else if strings.HasPrefix(xDescriptor, attributePrefix) {
 			r.store(path, []byte(pathValue))
 		}
 	}
@@ -221,10 +228,11 @@ func (r *Retriever) Retrieve() error {
 // NewRetriever instantiate a new retriever instance.
 func NewRetriever(ctx context.Context, client client.Client, plan *planner.Plan) *Retriever {
 	return &Retriever{
-		ctx:    ctx,
-		client: client,
-		logger: logf.Log.WithName("retriever"),
-		plan:   plan,
-		data:   make(map[string][]byte),
+		ctx:        ctx,
+		client:     client,
+		logger:     logf.Log.WithName("retriever"),
+		plan:       plan,
+		data:       make(map[string][]byte),
+		volumeKeys: []string{},
 	}
 }


Test patch:
diff --git a/pkg/controller/servicebindingrequest/reconciler_test.go b/pkg/controller/servicebindingrequest/reconciler_test.go
index d2eb58a6..c6c745fe 100644
--- a/pkg/controller/servicebindingrequest/reconciler_test.go
+++ b/pkg/controller/servicebindingrequest/reconciler_test.go
@@ -27,13 +27,12 @@ const (
 	reconcilerName = "binding-request"
 )
 
-var reconciler *Reconciler
-var reconcilerFakeClient client.Client
-
 // TestReconcilerNew this method acts as a "new" call would, but in this scenario bootstraping the
 // types and requirements to test Reconcile.
 func TestReconcilerNew(t *testing.T) {
 	logf.SetLogger(logf.ZapLogger(true))
+	var reconciler *Reconciler
+	var reconcilerFakeClient client.Client
 
 	s := scheme.Scheme
 	resourceRef := "db-testing"
@@ -62,27 +61,99 @@ func TestReconcilerNew(t *testing.T) {
 	objs := []runtime.Object{&sbr, &csvList, &crList, &dbSecret, &d}
 	reconcilerFakeClient = fake.NewFakeClientWithScheme(s, objs...)
 	reconciler = &Reconciler{client: reconcilerFakeClient, scheme: s}
+
+	t.Run("reconcile", func(t *testing.T) {
+		req := reconcile.Request{
+			NamespacedName: types.NamespacedName{
+				Namespace: reconcilerNs,
+				Name:      reconcilerName,
+			},
+		}
+
+		res, err := reconciler.Reconcile(req)
+		assert.Nil(t, err)
+		assert.False(t, res.Requeue)
+
+		namespacedName := types.NamespacedName{Namespace: reconcilerNs, Name: reconcilerName}
+		d := extv1beta1.Deployment{}
+		require.Nil(t, reconcilerFakeClient.Get(context.TODO(), namespacedName, &d))
+
+		containers := d.Spec.Template.Spec.Containers
+		assert.Equal(t, 1, len(containers))
+		assert.Equal(t, 1, len(containers[0].EnvFrom))
+		assert.NotNil(t, containers[0].EnvFrom[0].SecretRef)
+		assert.Equal(t, reconcilerName, containers[0].EnvFrom[0].SecretRef.Name)
+
+	})
+
 }
 
-func TestReconcilerReconcile(t *testing.T) {
-	req := reconcile.Request{
-		NamespacedName: types.NamespacedName{
-			Namespace: reconcilerNs,
-			Name:      reconcilerName,
-		},
+// TestReconcilerVolumeMount method acts as a "new" call would, but in this scenario bootstraping the
+// types and requirements to test Reconcile.
+func TestReconcilerVolumeMount(t *testing.T) {
+	logf.SetLogger(logf.ZapLogger(true))
+	var reconciler *Reconciler
+	var reconcilerFakeClient client.Client
+
+	s := scheme.Scheme
+	resourceRef := "db-testing"
+	matchLabels := map[string]string{
+		"connects-to": "database",
+		"environment": "planner",
 	}
 
-	res, err := reconciler.Reconcile(req)
-	assert.Nil(t, err)
-	assert.False(t, res.Requeue)
+	sbr := mocks.ServiceBindingRequestMock(reconcilerNs, reconcilerName, resourceRef, matchLabels)
+	s.AddKnownTypes(v1alpha1.SchemeGroupVersion, &sbr)
+
+	require.Nil(t, olmv1alpha1.AddToScheme(s))
+	csvList := mocks.ClusterServiceVersionListVolumeMountMock(reconcilerNs, "cluster-service-version-list")
+	s.AddKnownTypes(olmv1alpha1.SchemeGroupVersion, &csvList)
+
+	require.Nil(t, pgapis.AddToScheme(s))
+	crList := mocks.DatabaseCRListMock(reconcilerNs, resourceRef)
+	s.AddKnownTypes(pgv1alpha1.SchemeGroupVersion, &crList)
+
+	dbSecret := mocks.SecretMock(reconcilerNs, "db-credentials")
+
+	require.Nil(t, extv1beta1.AddToScheme(s))
+	d := mocks.DeploymentMock(reconcilerNs, reconcilerName, matchLabels)
+	s.AddKnownTypes(extv1beta1.SchemeGroupVersion, &d)
+
+	objs := []runtime.Object{&sbr, &csvList, &crList, &dbSecret, &d}
+	reconcilerFakeClient = fake.NewFakeClientWithScheme(s, objs...)
+	reconciler = &Reconciler{client: reconcilerFakeClient, scheme: s}
+
+	t.Run("reconcile", func(t *testing.T) {
+		req := reconcile.Request{
+			NamespacedName: types.NamespacedName{
+				Namespace: reconcilerNs,
+				Name:      reconcilerName,
+			},
+		}
+
+		res, err := reconciler.Reconcile(req)
+		assert.Nil(t, err)
+		assert.False(t, res.Requeue)
+
+		namespacedName := types.NamespacedName{Namespace: reconcilerNs, Name: reconcilerName}
+		d := extv1beta1.Deployment{}
+		require.Nil(t, reconcilerFakeClient.Get(context.TODO(), namespacedName, &d))
+
+		containers := d.Spec.Template.Spec.Containers
+		assert.Equal(t, 1, len(containers))
+		assert.Equal(t, 1, len(containers[0].EnvFrom))
+		assert.NotNil(t, containers[0].EnvFrom[0].SecretRef)
+		assert.Equal(t, reconcilerName, containers[0].EnvFrom[0].SecretRef.Name)
+
+		assert.Equal(t, 1, len(containers[0].VolumeMounts))
+		assert.Equal(t, "/var/redhat", containers[0].VolumeMounts[0].MountPath)
+		assert.Equal(t, reconcilerName, containers[0].VolumeMounts[0].Name)
+
+		volumes := d.Spec.Template.Spec.Volumes
+		assert.Equal(t, 1, len(volumes))
+		assert.Equal(t, reconcilerName, volumes[0].Name)
+		assert.Equal(t, reconcilerName, volumes[0].VolumeSource.Secret.SecretName)
 
-	namespacedName := types.NamespacedName{Namespace: reconcilerNs, Name: reconcilerName}
-	d := extv1beta1.Deployment{}
-	require.Nil(t, reconcilerFakeClient.Get(context.TODO(), namespacedName, &d))
+	})
 
-	containers := d.Spec.Template.Spec.Containers
-	assert.Equal(t, 1, len(containers))
-	assert.Equal(t, 1, len(containers[0].EnvFrom))
-	assert.NotNil(t, containers[0].EnvFrom[0].SecretRef)
-	assert.Equal(t, reconcilerName, containers[0].EnvFrom[0].SecretRef.Name)
 }
diff --git a/test/mocks/mocks.go b/test/mocks/mocks.go
index aea5bcc9..56d14e8c 100644
--- a/test/mocks/mocks.go
+++ b/test/mocks/mocks.go
@@ -109,6 +109,69 @@ func CRDDescriptionConfigMapMock() olmv1alpha1.CRDDescription {
 	}
 }
 
+// ClusterServiceVersionVolumeMountMock based on PostgreSQL operator.
+func ClusterServiceVersionVolumeMountMock(ns, name string) olmv1alpha1.ClusterServiceVersion {
+	strategy := olminstall.StrategyDetailsDeployment{
+		DeploymentSpecs: []olminstall.StrategyDeploymentSpec{{
+			Name: "deployment",
+			Spec: appsv1.DeploymentSpec{},
+		}},
+	}
+
+	strategyJSON, _ := json.Marshal(strategy)
+
+	return olmv1alpha1.ClusterServiceVersion{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      name,
+		},
+		Spec: olmv1alpha1.ClusterServiceVersionSpec{
+			DisplayName: "mock-database-csv",
+			InstallStrategy: olmv1alpha1.NamedInstallStrategy{
+				StrategyName:    "deployment",
+				StrategySpecRaw: strategyJSON,
+			},
+			CustomResourceDefinitions: olmv1alpha1.CustomResourceDefinitions{
+				Owned: []olmv1alpha1.CRDDescription{CRDDescriptionVolumeMountMock()},
+			},
+		},
+	}
+}
+
+// ClusterServiceVersionListVolumeMountMock returns a list with a single CSV object inside, reusing mock.
+func ClusterServiceVersionListVolumeMountMock(ns, name string) olmv1alpha1.ClusterServiceVersionList {
+	return olmv1alpha1.ClusterServiceVersionList{
+		Items: []olmv1alpha1.ClusterServiceVersion{ClusterServiceVersionVolumeMountMock(ns, name)},
+	}
+}
+
+// CRDDescriptionVolumeMountMock ...
+func CRDDescriptionVolumeMountMock() olmv1alpha1.CRDDescription {
+	return olmv1alpha1.CRDDescription{
+		Name:        fmt.Sprintf("%s.%s", CRDKind, CRDName),
+		DisplayName: CRDKind,
+		Description: "mock-crd-description",
+		Kind:        CRDKind,
+		Version:     CRDVersion,
+		SpecDescriptors: []olmv1alpha1.SpecDescriptor{{
+			DisplayName:  "Database Name",
+			Description:  "Database Name",
+			Path:         "dbName",
+			XDescriptors: []string{"urn:alm:descriptor:servicebindingrequest:env:attribute"},
+		}},
+		StatusDescriptors: []olmv1alpha1.StatusDescriptor{{
+			DisplayName: "DB Password Credentials",
+			Description: "Database credentials secret",
+			Path:        "dbCredentials",
+			XDescriptors: []string{
+				"urn:alm:descriptor:io.kubernetes:Secret",
+				"urn:alm:descriptor:servicebindingrequest:volumemount:secret:user",
+				"urn:alm:descriptor:servicebindingrequest:volumemount:secret:password",
+			},
+		}},
+	}
+}
+
 // DatabaseCRMock based on PostgreSQL operator, returning a instantiated object.
 func DatabaseCRMock(ns, name string) pgv1alpha1.Database {
 	return pgv1alpha1.Database{
@@ -177,6 +240,7 @@ func ServiceBindingRequestMock(
 			Name:      name,
 		},
 		Spec: v1alpha1.ServiceBindingRequestSpec{
+			MountPathPrefix: "/var/redhat",
 			BackingServiceSelector: v1alpha1.BackingServiceSelector{
 				ResourceKind:    CRDName,
 				ResourceVersion: CRDVersion,