Skip to content
This repository was archived by the owner on May 6, 2022. It is now read-only.

Commit fc2d41a

Browse files
pmoriearschles
authored andcommitted
Make it possible to bind only to bindable serviceclasses (#744)
1 parent 67f76a2 commit fc2d41a

File tree

3 files changed

+95
-14
lines changed

3 files changed

+95
-14
lines changed

pkg/controller/controller.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ const (
268268
errorUnbindCallReason string = "UnbindCallFailed"
269269
errorWithOngoingAsyncOperation string = "ErrorAsyncOperationInProgress"
270270
errorWithOngoingAsyncOperationMessage string = "Another operation for this service instance is in progress. "
271+
errorNonbindableServiceClassReason string = "ErrorNonbindableServiceClass"
271272

272273
successInjectedBindResultReason string = "InjectedBindResult"
273274
successInjectedBindResultMessage string = "Injected bind result"
@@ -1196,6 +1197,20 @@ func (c *controller) reconcileBinding(binding *v1alpha1.Binding) error {
11961197
return err
11971198
}
11981199

1200+
if !serviceClass.Bindable {
1201+
s := fmt.Sprintf("Binding \"%s/%s\" references a non-bindable ServiceClass %q", binding.Namespace, binding.Name, instance.Spec.ServiceClassName)
1202+
glog.Warning(s)
1203+
c.updateBindingCondition(
1204+
binding,
1205+
v1alpha1.BindingConditionReady,
1206+
v1alpha1.ConditionFalse,
1207+
errorNonbindableServiceClassReason,
1208+
s,
1209+
)
1210+
c.recorder.Event(binding, api.EventTypeWarning, errorNonbindableServiceClassReason, s)
1211+
return err
1212+
}
1213+
11991214
if binding.DeletionTimestamp == nil { // Add or update
12001215
glog.V(4).Infof("Adding/Updating Binding %v/%v", binding.Namespace, binding.Name)
12011216

pkg/controller/controller_test.go

Lines changed: 79 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,23 @@ import (
4646
)
4747

4848
const (
49-
serviceClassGUID = "SCGUID"
50-
planGUID = "PGUID"
51-
instanceGUID = "IGUID"
52-
bindingGUID = "BGUID"
53-
54-
testBrokerName = "test-broker"
55-
testServiceClassName = "test-serviceclass"
56-
testPlanName = "test-plan"
57-
testInstanceName = "test-instance"
58-
testBindingName = "test-binding"
59-
testNamespace = "test-ns"
60-
testBindingSecretName = "test-secret"
61-
testOperation = "test-operation"
49+
serviceClassGUID = "SCGUID"
50+
planGUID = "PGUID"
51+
nonbindableServiceClassGUID = "UNBINDABLE-SERVICE"
52+
nonbindablePlanGUID = "UNBINDABLE-PLAN"
53+
instanceGUID = "IGUID"
54+
bindingGUID = "BGUID"
55+
56+
testBrokerName = "test-broker"
57+
testServiceClassName = "test-serviceclass"
58+
testNonbindableServiceClassName = "test-unbindable-serviceclass"
59+
testPlanName = "test-plan"
60+
testNonbindablePlanName = "test-unbindable-plan"
61+
testInstanceName = "test-instance"
62+
testBindingName = "test-binding"
63+
testNamespace = "test-ns"
64+
testBindingSecretName = "test-secret"
65+
testOperation = "test-operation"
6266
)
6367

6468
const testCatalog = `{
@@ -206,12 +210,13 @@ func getTestBrokerWithStatus(status v1alpha1.ConditionStatus) *v1alpha1.Broker {
206210
return broker
207211
}
208212

209-
// service class wired to the result of getTestBroker()
213+
// a bindable service class wired to the result of getTestBroker()
210214
func getTestServiceClass() *v1alpha1.ServiceClass {
211215
return &v1alpha1.ServiceClass{
212216
ObjectMeta: metav1.ObjectMeta{Name: testServiceClassName},
213217
BrokerName: testBrokerName,
214218
OSBGUID: serviceClassGUID,
219+
Bindable: true,
215220
Plans: []v1alpha1.ServicePlan{{
216221
Name: testPlanName,
217222
OSBFree: true,
@@ -220,6 +225,21 @@ func getTestServiceClass() *v1alpha1.ServiceClass {
220225
}
221226
}
222227

228+
// an unbindable service class wired to the result of getTestBroker()
229+
func getTestNonbindableServiceClass() *v1alpha1.ServiceClass {
230+
return &v1alpha1.ServiceClass{
231+
ObjectMeta: metav1.ObjectMeta{Name: testNonbindableServiceClassName},
232+
BrokerName: testBrokerName,
233+
OSBGUID: nonbindableServiceClassGUID,
234+
Bindable: false,
235+
Plans: []v1alpha1.ServicePlan{{
236+
Name: testNonbindablePlanName,
237+
OSBFree: true,
238+
OSBGUID: nonbindablePlanGUID,
239+
}},
240+
}
241+
}
242+
223243
// broker catalog that provides the service class named in of
224244
// getTestServiceClass()
225245
func getTestCatalog() *brokerapi.Catalog {
@@ -229,6 +249,7 @@ func getTestCatalog() *brokerapi.Catalog {
229249
Name: testServiceClassName,
230250
ID: serviceClassGUID,
231251
Description: "a test service",
252+
Bindable: true,
232253
Plans: []brokerapi.ServicePlan{
233254
{
234255
Name: testPlanName,
@@ -254,6 +275,15 @@ func getTestInstance() *v1alpha1.Instance {
254275
}
255276
}
256277

278+
// an isntance referencing the result of getTestNonbindableServiceClass
279+
func getTestNonbindableInstance() *v1alpha1.Instance {
280+
i := getTestInstance()
281+
i.Spec.ServiceClassName = testNonbindableServiceClassName
282+
i.Spec.PlanName = testNonbindablePlanName
283+
284+
return i
285+
}
286+
257287
// getTestInstanceAsync returns an instance in async mode
258288
func getTestInstanceAsyncProvisioning(operation string) *v1alpha1.Instance {
259289
instance := getTestInstance()
@@ -1981,6 +2011,41 @@ func TestReconcileBindingWithParameters(t *testing.T) {
19812011
}
19822012
}
19832013

2014+
func TestReconcileBindingNonbindableServiceClass(t *testing.T) {
2015+
_, fakeCatalogClient, fakeBrokerClient, testController, sharedInformers := newTestController(t)
2016+
2017+
fakeBrokerClient.CatalogClient.RetCatalog = getTestCatalog()
2018+
2019+
sharedInformers.Brokers().Informer().GetStore().Add(getTestBroker())
2020+
sharedInformers.ServiceClasses().Informer().GetStore().Add(getTestNonbindableServiceClass())
2021+
sharedInformers.Instances().Informer().GetStore().Add(getTestNonbindableInstance())
2022+
2023+
binding := &v1alpha1.Binding{
2024+
ObjectMeta: metav1.ObjectMeta{Name: testBindingName, Namespace: testNamespace},
2025+
Spec: v1alpha1.BindingSpec{
2026+
InstanceRef: v1.LocalObjectReference{Name: testInstanceName},
2027+
OSBGUID: bindingGUID,
2028+
},
2029+
}
2030+
2031+
testController.reconcileBinding(binding)
2032+
2033+
actions := fakeCatalogClient.Actions()
2034+
assertNumberOfActions(t, actions, 1)
2035+
2036+
// There should only be one action that says binding was created
2037+
updatedBinding := assertUpdateStatus(t, actions[0], binding)
2038+
assertBindingReadyFalse(t, updatedBinding, errorNonbindableServiceClassReason)
2039+
2040+
events := getRecordedEvents(testController)
2041+
assertNumEvents(t, events, 1)
2042+
2043+
expectedEvent := api.EventTypeWarning + " " + errorNonbindableServiceClassReason + ` Binding "test-ns/test-binding" references a non-bindable ServiceClass "test-unbindable-serviceclass"`
2044+
if e, a := expectedEvent, events[0]; e != a {
2045+
t.Fatalf("Received unexpected event: %v", a)
2046+
}
2047+
}
2048+
19842049
func TestReconcileBindingFailsWithInstanceAsyncOngoing(t *testing.T) {
19852050
fakeKubeClient, fakeCatalogClient, fakeBrokerClient, testController, sharedInformers := newTestController(t)
19862051

test/integration/controller_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ func TestBasicFlows(t *testing.T) {
8080
Name: testServiceClassName,
8181
ID: "12345",
8282
Description: "a test service",
83+
Bindable: true,
8384
Plans: []brokerapi.ServicePlan{
8485
{
8586
Name: testPlanName,

0 commit comments

Comments
 (0)