Repository: redhat-developer/service-binding-operator
Pull request #363 (2020-03-06 04:14:41)

Provide bound app's info in status as a GVK
.. to look like

```
status:
  applications:
    - group: apps
      kind: Deployment
      name: nodejs-rest-http-crud
      version: v1
  bindingStatus: BindingSuccess
  conditions:
    - lastHeartbeatTime: '2020-03-06T04:51:31Z'
      lastTransitionTime: '2020-03-06T04:51:31Z'
      status: 'True'
      type: Ready
  secret: nodejs-rest-http-crud-d-demo-database-postgresql-d
```
https://issues.redhat.com/browse/APPSVC-323

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

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

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=redhat-developer&repo=service-binding-operator&pr=363). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:sbose78). 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: /retest
openshift-ci-robot: @sbose78: The following test **failed**, say `/retest` to rerun all failed tests:

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

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=redhat-developer&repo=service-binding-operator&pr=363). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:sbose78). 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 -->
codecov[bot]: # [Codecov](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/363?src=pr&el=h1) Report
> Merging [#363](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/363?src=pr&el=desc) into [master](https://codecov.io/gh/redhat-developer/service-binding-operator/commit/12f25eecc40fe13cb0764920473d502727abf4c4?src=pr&el=desc) will **increase** coverage by `0.24%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/363/graphs/tree.svg?width=650&token=CICBeVWlrC&height=150&src=pr)](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/363?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #363      +/-   ##
==========================================
+ Coverage   63.04%   63.28%   +0.24%     
==========================================
  Files          21       21              
  Lines        1372     1381       +9     
==========================================
+ Hits          865      874       +9     
  Misses        378      378              
  Partials      129      129
```


| [Impacted Files](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/363?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/controller/servicebindingrequest/binding.go](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/363/diff?src=pr&el=tree#diff-cGtnL2NvbnRyb2xsZXIvc2VydmljZWJpbmRpbmdyZXF1ZXN0L2JpbmRpbmcuZ28=) | `69.53% <100%> (+1.93%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/363?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/363?src=pr&el=footer). Last update [12f25ee...4a6b3c9](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/363?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/README.md b/README.md
index 5a3a7295..1725c67f 100644
--- a/README.md
+++ b/README.md
@@ -92,3 +92,4 @@ The following example scenarios are available:
 
 [Binding an Imported app with an In-cluster Operator Managed ETCD Database](examples/nodejs_etcd_operator/README.md)
 
+[Binding an Imported app to an Off-cluster Operator Managed IBM Cloud Service](examples/nodejs_ibmcloud_operator/README.md)
diff --git a/deploy/crds/apps.openshift.io_servicebindingrequests_crd.yaml b/deploy/crds/apps.openshift.io_servicebindingrequests_crd.yaml
index ebfab03b..b3d8fa8f 100644
--- a/deploy/crds/apps.openshift.io_servicebindingrequests_crd.yaml
+++ b/deploy/crds/apps.openshift.io_servicebindingrequests_crd.yaml
@@ -17,7 +17,8 @@ spec:
     status: {}
   validation:
     openAPIV3Schema:
-      description: Expresses intent to bind an operator-backed service with a Deployment
+      description: ServiceBindingRequest expresses intent to bind an operator-backed
+        service with an application workload.
       properties:
         apiVersion:
           description: 'APIVersion defines the versioned schema of this representation
@@ -252,11 +253,28 @@ spec:
         status:
           description: ServiceBindingRequestStatus defines the observed state of ServiceBindingRequest
           properties:
-            applicationObjects:
+            applications:
               description: ApplicationObjects contains all the application objects
                 filtered by label
               items:
-                type: string
+                description: BoundApplication defines the application workloads to
+                  which the binding secret has injected.
+                properties:
+                  group:
+                    type: string
+                  kind:
+                    type: string
+                  name:
+                    description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
+                      TODO: Add other useful fields. apiVersion, kind, uid?'
+                    type: string
+                  version:
+                    type: string
+                required:
+                - group
+                - kind
+                - version
+                type: object
               type: array
             bindingStatus:
               description: BindingStatus is the status of the service binding request.
diff --git a/go.mod b/go.mod
index 19d24589..e352cb7c 100644
--- a/go.mod
+++ b/go.mod
@@ -25,6 +25,7 @@ require (
 	k8s.io/code-generator v0.0.0
 	k8s.io/gengo v0.0.0-20191010091904-7fa3014cb28f
 	k8s.io/kube-openapi v0.0.0-20190918143330-0270cf2f1c1d
+	k8s.io/kubernetes v1.16.2
 	knative.dev/pkg v0.0.0-20191221032535-9fda5bd59a67 // indirect
 	knative.dev/serving v0.9.0
 	sigs.k8s.io/controller-runtime v0.4.0
diff --git a/go.sum b/go.sum
index 9ff25860..cebff7ca 100644
--- a/go.sum
+++ b/go.sum
@@ -568,13 +568,12 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM
 github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
 github.com/opencontainers/runc v1.0.0-rc2.0.20190611121236-6cc515888830/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
 github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-
-github.com/openshift/custom-resource-status v0.0.0-20190822192428-e62f2f3b79f3 h1:XuAys09+XqT5/FjdR23G/UtbBLII89dFe9XIi73EKIQ=
-github.com/openshift/custom-resource-status v0.0.0-20190822192428-e62f2f3b79f3/go.mod h1:GDjWl0tX6FNIj82vIxeudWeSx2Ff6nDZ8uJn0ohUFvo=
 github.com/opencontainers/selinux v1.2.2/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
 github.com/openshift/api v3.9.1-0.20190924102528-32369d4db2ad+incompatible h1:6il8W875Oq9vycPkRV5TteLP9IfMEX3lyOl5yN+CtdI=
 github.com/openshift/api v3.9.1-0.20190924102528-32369d4db2ad+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY=
 github.com/openshift/client-go v0.0.0-20190923180330-3b6373338c9b/go.mod h1:6rzn+JTr7+WYS2E1TExP4gByoABxMznR6y2SnUIkmxk=
+github.com/openshift/custom-resource-status v0.0.0-20190822192428-e62f2f3b79f3 h1:XuAys09+XqT5/FjdR23G/UtbBLII89dFe9XIi73EKIQ=
+github.com/openshift/custom-resource-status v0.0.0-20190822192428-e62f2f3b79f3/go.mod h1:GDjWl0tX6FNIj82vIxeudWeSx2Ff6nDZ8uJn0ohUFvo=
 github.com/openshift/origin v0.0.0-20160503220234-8f127d736703/go.mod h1:0Rox5r9C8aQn6j1oAOQ0c1uC86mYbUFObzjBRvUKHII=
 github.com/openshift/prom-label-proxy v0.1.1-0.20191016113035-b8153a7f39f1/go.mod h1:p5MuxzsYP1JPsNGwtjtcgRHHlGziCJJfztff91nNixw=
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
@@ -1051,6 +1050,7 @@ k8s.io/kube-scheduler v0.0.0-20191016114748-65049c67a58b/go.mod h1:BgDUHHC5Wl0xc
 k8s.io/kube-state-metrics v1.7.2 h1:6vdtgXrrRRMSgnyDmgua+qvgCYv954JNfxXAtDkeLVQ=
 k8s.io/kube-state-metrics v1.7.2/go.mod h1:U2Y6DRi07sS85rmVPmBFlmv+2peBcL8IWGjM+IjYA/E=
 k8s.io/kubectl v0.0.0-20191016120415-2ed914427d51/go.mod h1:gL826ZTIfD4vXTGlmzgTbliCAT9NGiqpCqK2aNYv5MQ=
+k8s.io/kubelet v0.0.0-20191016114556-7841ed97f1b2 h1:YXArqZfchiY+62+AyWPWE59wICh7xnAEowHGWggxBXs=
 k8s.io/kubelet v0.0.0-20191016114556-7841ed97f1b2/go.mod h1:SBvrtLbuePbJygVXGGCMtWKH07+qrN2dE1iMnteSG8E=
 k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
 k8s.io/kubernetes v1.16.0/go.mod h1:nlP2zevWKRGKuaaVbKIwozU0Rjg9leVDXkL4YTtjmVs=
diff --git a/pkg/apis/apps/v1alpha1/servicebindingrequest_types.go b/pkg/apis/apps/v1alpha1/servicebindingrequest_types.go
index e8857536..325bc8a0 100644
--- a/pkg/apis/apps/v1alpha1/servicebindingrequest_types.go
+++ b/pkg/apis/apps/v1alpha1/servicebindingrequest_types.go
@@ -3,6 +3,7 @@ package v1alpha1
 import (
 	conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1"
 	corev1 "k8s.io/api/core/v1"
+	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
@@ -54,7 +55,7 @@ type ServiceBindingRequestStatus struct {
 	// Secret is the name of the intermediate secret
 	Secret string `json:"secret,omitempty"`
 	// ApplicationObjects contains all the application objects filtered by label
-	ApplicationObjects []string `json:"applicationObjects,omitempty"`
+	ApplicationObjects []BoundApplication `json:"applications,omitempty"`
 }
 
 // BackingServiceSelector defines the selector based on resource name, version, and resource kind
@@ -64,6 +65,13 @@ type BackingServiceSelector struct {
 	ResourceRef             string `json:"resourceRef"`
 }
 
+// BoundApplication defines the application workloads to which the binding secret has
+// injected.
+type BoundApplication struct {
+	metav1.GroupVersionKind `json:",inline"`
+	v1.LocalObjectReference `json:",inline"`
+}
+
 // ApplicationSelector defines the selector based on labels and GVR
 // +k8s:openapi-gen=true
 type ApplicationSelector struct {
@@ -75,7 +83,8 @@ type ApplicationSelector struct {
 
 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 
-// Expresses intent to bind an operator-backed service with a Deployment
+// ServiceBindingRequest expresses intent to bind an operator-backed service with
+// an application workload.
 // +k8s:openapi-gen=true
 // +operator-sdk:gen-csv:customresourcedefinitions.displayName="Service Binding Request"
 // +kubebuilder:subresource:status
diff --git a/pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go
index 27ad41ff..c21ef38f 100644
--- a/pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go
@@ -50,6 +50,24 @@ func (in *BackingServiceSelector) DeepCopy() *BackingServiceSelector {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *BoundApplication) DeepCopyInto(out *BoundApplication) {
+	*out = *in
+	out.GroupVersionKind = in.GroupVersionKind
+	out.LocalObjectReference = in.LocalObjectReference
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BoundApplication.
+func (in *BoundApplication) DeepCopy() *BoundApplication {
+	if in == nil {
+		return nil
+	}
+	out := new(BoundApplication)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *ServiceBindingRequest) DeepCopyInto(out *ServiceBindingRequest) {
 	*out = *in
@@ -153,7 +171,7 @@ func (in *ServiceBindingRequestStatus) DeepCopyInto(out *ServiceBindingRequestSt
 	}
 	if in.ApplicationObjects != nil {
 		in, out := &in.ApplicationObjects, &out.ApplicationObjects
-		*out = make([]string, len(*in))
+		*out = make([]BoundApplication, len(*in))
 		copy(*out, *in)
 	}
 	return
diff --git a/pkg/apis/apps/v1alpha1/zz_generated.openapi.go b/pkg/apis/apps/v1alpha1/zz_generated.openapi.go
index fef38066..df176e18 100644
--- a/pkg/apis/apps/v1alpha1/zz_generated.openapi.go
+++ b/pkg/apis/apps/v1alpha1/zz_generated.openapi.go
@@ -106,7 +106,7 @@ func schema_pkg_apis_apps_v1alpha1_ServiceBindingRequest(ref common.ReferenceCal
 	return common.OpenAPIDefinition{
 		Schema: spec.Schema{
 			SchemaProps: spec.SchemaProps{
-				Description: "Expresses intent to bind an operator-backed service with a Deployment",
+				Description: "ServiceBindingRequest expresses intent to bind an operator-backed service with an application workload.",
 				Type:        []string{"object"},
 				Properties: map[string]spec.Schema{
 					"kind": {
@@ -255,15 +255,14 @@ func schema_pkg_apis_apps_v1alpha1_ServiceBindingRequestStatus(ref common.Refere
 							Format:      "",
 						},
 					},
-					"applicationObjects": {
+					"applications": {
 						SchemaProps: spec.SchemaProps{
 							Description: "ApplicationObjects contains all the application objects filtered by label",
 							Type:        []string{"array"},
 							Items: &spec.SchemaOrArray{
 								Schema: &spec.Schema{
 									SchemaProps: spec.SchemaProps{
-										Type:   []string{"string"},
-										Format: "",
+										Ref: ref("./pkg/apis/apps/v1alpha1.BoundApplication"),
 									},
 								},
 							},
@@ -273,6 +272,6 @@ func schema_pkg_apis_apps_v1alpha1_ServiceBindingRequestStatus(ref common.Refere
 			},
 		},
 		Dependencies: []string{
-			"github.com/openshift/custom-resource-status/conditions/v1.Condition"},
+			"./pkg/apis/apps/v1alpha1.BoundApplication", "github.com/openshift/custom-resource-status/conditions/v1.Condition"},
 	}
 }
diff --git a/pkg/controller/servicebindingrequest/binding.go b/pkg/controller/servicebindingrequest/binding.go
index 87d77aac..32c8169d 100644
--- a/pkg/controller/servicebindingrequest/binding.go
+++ b/pkg/controller/servicebindingrequest/binding.go
@@ -3,7 +3,6 @@ package servicebindingrequest
 import (
 	"context"
 	"errors"
-	"fmt"
 
 	conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1"
 	"gotest.tools/assert/cmp"
@@ -270,11 +269,21 @@ func (b *ServiceBinder) setApplicationObjects(
 	sbrStatus *v1alpha1.ServiceBindingRequestStatus,
 	objs []*unstructured.Unstructured,
 ) {
-	names := []string{}
+	boundApps := []v1alpha1.BoundApplication{}
 	for _, obj := range objs {
-		names = append(names, fmt.Sprintf("%s/%s", obj.GetNamespace(), obj.GetName()))
+		boundApp := v1alpha1.BoundApplication{
+			GroupVersionKind: v1.GroupVersionKind{
+				Group:   obj.GroupVersionKind().Group,
+				Version: obj.GroupVersionKind().Version,
+				Kind:    obj.GetKind(),
+			},
+			LocalObjectReference: corev1.LocalObjectReference{
+				Name: obj.GetName(),
+			},
+		}
+		boundApps = append(boundApps, boundApp)
 	}
-	sbrStatus.ApplicationObjects = names
+	sbrStatus.ApplicationObjects = boundApps
 }
 
 // buildPlan creates a new plan.


Test patch:
diff --git a/pkg/controller/servicebindingrequest/reconciler_test.go b/pkg/controller/servicebindingrequest/reconciler_test.go
index 58c911e0..c9a24bde 100644
--- a/pkg/controller/servicebindingrequest/reconciler_test.go
+++ b/pkg/controller/servicebindingrequest/reconciler_test.go
@@ -2,11 +2,14 @@ package servicebindingrequest
 
 import (
 	"context"
-	"fmt"
+	"reflect"
 	"testing"
 
+	"github.com/redhat-developer/service-binding-operator/pkg/apis/apps/v1alpha1"
 	"github.com/stretchr/testify/require"
 	appsv1 "k8s.io/api/apps/v1"
+	corev1 "k8s.io/api/core/v1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/controller-runtime/pkg/reconcile"
@@ -91,8 +94,17 @@ func TestApplicationSelectorByName(t *testing.T) {
 
 		require.Equal(t, BindingSuccess, sbrOutput.Status.BindingStatus)
 		require.Equal(t, 1, len(sbrOutput.Status.ApplicationObjects))
-		expectedStatus := fmt.Sprintf("%s/%s", reconcilerNs, reconcilerName)
-		require.Equal(t, expectedStatus, sbrOutput.Status.ApplicationObjects[0])
+		expectedStatus := v1alpha1.BoundApplication{
+			GroupVersionKind: v1.GroupVersionKind{
+				Group:   deploymentsGVR.Group,
+				Version: deploymentsGVR.Version,
+				Kind:    "Deployment",
+			},
+			LocalObjectReference: corev1.LocalObjectReference{
+				Name: namespacedName.Name,
+			},
+		}
+		require.True(t, reflect.DeepEqual(expectedStatus, sbrOutput.Status.ApplicationObjects[0]))
 	})
 }
 
@@ -140,8 +152,17 @@ func TestReconcilerReconcileUsingSecret(t *testing.T) {
 		require.Equal(t, reconcilerName, sbrOutput.Status.Secret)
 
 		require.Equal(t, 1, len(sbrOutput.Status.ApplicationObjects))
-		expectedStatus := fmt.Sprintf("%s/%s", reconcilerNs, reconcilerName)
-		require.Equal(t, expectedStatus, sbrOutput.Status.ApplicationObjects[0])
+		expectedStatus := v1alpha1.BoundApplication{
+			GroupVersionKind: v1.GroupVersionKind{
+				Group:   deploymentsGVR.Group,
+				Version: deploymentsGVR.Version,
+				Kind:    "Deployment",
+			},
+			LocalObjectReference: corev1.LocalObjectReference{
+				Name: namespacedName.Name,
+			},
+		}
+		require.True(t, reflect.DeepEqual(expectedStatus, sbrOutput.Status.ApplicationObjects[0]))
 	})
 }