Skip to content
This repository was archived by the owner on Jun 26, 2024. It is now read-only.

Commit 89cdc44

Browse files
pmacikbaijum
andauthored
Detect bindable resource based on status attribute (#1270) (#1357)
Signed-off-by: Baiju Muthukadan <[email protected]> Signed-off-by: Baiju Muthukadan <[email protected]> Signed-off-by: Baiju Muthukadan <[email protected]> Co-authored-by: Baiju Muthukadan <[email protected]>
1 parent 7614578 commit 89cdc44

File tree

3 files changed

+113
-21
lines changed

3 files changed

+113
-21
lines changed

pkg/reconcile/pipeline/context/service/crd_test.go

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
. "github.com/onsi/ginkgo"
55
. "github.com/onsi/ginkgo/extensions/table"
66
. "github.com/onsi/gomega"
7-
"github.com/redhat-developer/service-binding-operator/pkg/binding"
87
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
98
"k8s.io/apimachinery/pkg/runtime"
109
"k8s.io/client-go/dynamic/fake"
@@ -31,17 +30,6 @@ var _ = Describe("CRD", func() {
3130
mockCtrl.Finish()
3231
})
3332

34-
It("should be bindable if marked as provisioned service", func() {
35-
u := &unstructured.Unstructured{}
36-
annotations := map[string]string{
37-
binding.ProvisionedServiceAnnotationKey: "true",
38-
}
39-
u.SetAnnotations(annotations)
40-
crd := &customResourceDefinition{resource: u, client: client}
41-
42-
Expect(crd.IsBindable()).To(BeTrue())
43-
})
44-
4533
DescribeTable("should be bindable if has binding annotation", func(annKey string) {
4634
u := &unstructured.Unstructured{}
4735
annotations := map[string]string{
@@ -70,4 +58,76 @@ var _ = Describe("CRD", func() {
7058
crd := &customResourceDefinition{resource: u, client: client}
7159
Expect(crd.IsBindable()).To(BeFalse())
7260
})
61+
62+
It("should be bindable if the status has binding.name attribute", func() {
63+
u := &unstructured.Unstructured{
64+
Object: map[string]interface{}{
65+
"kind": "BackingService",
66+
"apiVersion": "app1.example.org/v1alpha1",
67+
"metadata": map[string]interface{}{
68+
"name": "back1",
69+
},
70+
"spec": map[string]interface{}{
71+
"versions": []map[string]interface{}{
72+
{
73+
"schema": map[string]interface{}{
74+
"openAPIV3Schema": map[string]interface{}{
75+
"properties": map[string]interface{}{
76+
"status": map[string]interface{}{
77+
"properties": map[string]interface{}{
78+
"binding": map[string]interface{}{
79+
"properties": map[string]interface{}{
80+
"name": map[string]interface{}{
81+
"type": "string",
82+
},
83+
},
84+
},
85+
},
86+
},
87+
},
88+
},
89+
},
90+
},
91+
},
92+
},
93+
}}
94+
crd := &customResourceDefinition{resource: u, client: client}
95+
Expect(crd.IsBindable()).To(BeTrue())
96+
})
97+
It("should not be bindable if the status has binding.name with attribute value", func() {
98+
u := &unstructured.Unstructured{
99+
Object: map[string]interface{}{
100+
"kind": "BackingService",
101+
"apiVersion": "app1.example.org/v1alpha1",
102+
"metadata": map[string]interface{}{
103+
"name": "back1",
104+
},
105+
"spec": map[string]interface{}{
106+
"versions": []map[string]interface{}{
107+
{
108+
"schema": map[string]interface{}{
109+
"openAPIV3Schema": map[string]interface{}{
110+
"properties": map[string]interface{}{
111+
"status": map[string]interface{}{
112+
"properties": map[string]interface{}{
113+
"binding": map[string]interface{}{
114+
"properties": map[string]interface{}{
115+
"name": map[string]interface{}{
116+
"type": "not-string", // correct: string
117+
},
118+
},
119+
},
120+
},
121+
},
122+
},
123+
},
124+
},
125+
},
126+
},
127+
},
128+
}}
129+
crd := &customResourceDefinition{resource: u, client: client}
130+
Expect(crd.IsBindable()).To(BeFalse())
131+
})
132+
73133
})

pkg/reconcile/pipeline/context/service/service.go

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,21 @@ package service
22

33
import (
44
"context"
5+
"reflect"
6+
"strings"
57

68
"github.com/redhat-developer/service-binding-operator/pkg/binding"
79
"github.com/redhat-developer/service-binding-operator/pkg/binding/registry"
810
"github.com/redhat-developer/service-binding-operator/pkg/client/kubernetes"
911
"github.com/redhat-developer/service-binding-operator/pkg/reconcile/pipeline"
1012

11-
"reflect"
12-
1313
"github.com/redhat-developer/service-binding-operator/pkg/util"
1414
"k8s.io/apimachinery/pkg/api/errors"
1515
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1616
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1717
"k8s.io/apimachinery/pkg/runtime/schema"
1818
"k8s.io/client-go/dynamic"
19+
"k8s.io/client-go/util/jsonpath"
1920
)
2021

2122
var _ pipeline.Service = &service{}
@@ -234,17 +235,45 @@ func (c *customResourceDefinition) kind() string {
234235
return ""
235236
}
236237

238+
// getValuesByJSONPath returns values from the given map matching the provided JSONPath
239+
// 'path' argument takes JSONPath expressions enclosed by curly braces {}
240+
// see https://kubernetes.io/docs/reference/kubectl/jsonpath/ for more details
241+
// It returns zero or more filtered values back,
242+
// or error if the jsonpath is invalid or it cannot be applied on the given map
243+
func getValuesByJSONPath(obj map[string]interface{}, path string) ([]reflect.Value, error) {
244+
j := jsonpath.New("")
245+
err := j.Parse(path)
246+
if err != nil {
247+
return nil, err
248+
}
249+
result, err := j.FindResults(obj)
250+
if err != nil {
251+
return nil, err
252+
}
253+
if len(result) > 1 {
254+
w := strings.Builder{}
255+
for i := range result {
256+
if err := j.PrintResults(&w, result[i]); err != nil {
257+
return nil, err
258+
}
259+
}
260+
return []reflect.Value{reflect.ValueOf(w.String())}, nil
261+
}
262+
return result[0], nil
263+
}
264+
237265
func (c *customResourceDefinition) IsBindable() (bool, error) {
266+
267+
value, err := getValuesByJSONPath(c.resource.Object, "{..schema.openAPIV3Schema.properties.status.properties.binding.properties.name.type}")
268+
if err == nil && len(value) > 0 && value[0].Interface().(string) == "string" {
269+
return true, nil
270+
}
271+
238272
annotations := make(map[string]string)
239273
util.MergeMaps(annotations, c.resource.GetAnnotations())
240274
if len(annotations) == 0 {
241275
return false, nil
242276
}
243-
val, found := annotations[binding.ProvisionedServiceAnnotationKey]
244-
if found && val == "true" {
245-
return true, nil
246-
}
247-
248277
for k := range annotations {
249278
if ok, err := binding.IsServiceBindingAnnotation(k); ok && err == nil {
250279
return true, nil

test/acceptance/resources/backend_crd.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,11 @@ spec:
6161
properties:
6262
dbCredentials:
6363
type: string
64-
bindings:
65-
type: string
64+
binding:
65+
type: object
66+
properties:
67+
name:
68+
type: string
6669
data:
6770
type: object
6871
properties:

0 commit comments

Comments
 (0)