Skip to content

Commit 26e5f5c

Browse files
committed
Revert to a string BindingPhase
This effectively reverts crossplane/crossplane#325. I still think it would be ideal to represent BindingState as an int with a sane zero value that marshaled to a JSON string, but it is currently impossible to override the type of the field that is used when generating an OpenAPI spec per kubernetes-sigs/controller-tools#155. Until that issue is closed it seems better to simply make this a string with a meaningless zero value. Signed-off-by: Nic Cope <[email protected]>
1 parent e187596 commit 26e5f5c

File tree

6 files changed

+66
-189
lines changed

6 files changed

+66
-189
lines changed

pkg/apis/core/v1alpha1/bindingphase.go

+10-37
Original file line numberDiff line numberDiff line change
@@ -14,60 +14,33 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
//go:generate go run ../../../../vendor/golang.org/x/tools/cmd/stringer/stringer.go ../../../../vendor/golang.org/x/tools/cmd/stringer/importer19.go -type=BindingPhase -trimprefix BindingPhase
18-
1917
package v1alpha1
2018

21-
import (
22-
"encoding/json"
23-
24-
"github.com/pkg/errors"
25-
)
26-
27-
// BindingPhase is to identify the current binding status of given resources
28-
type BindingPhase int
29-
30-
// MarshalJSON returns a JSON representation of a BindingPhase.
31-
func (p BindingPhase) MarshalJSON() ([]byte, error) {
32-
return json.Marshal(p.String())
33-
}
34-
35-
// UnmarshalJSON returns a BindingPhase from its JSON representation.
36-
func (p *BindingPhase) UnmarshalJSON(b []byte) error {
37-
var ps string
38-
if err := json.Unmarshal(b, &ps); err != nil {
39-
return err
40-
}
41-
switch ps {
42-
case BindingPhaseUnbindable.String():
43-
*p = BindingPhaseUnbindable
44-
case BindingPhaseUnbound.String():
45-
*p = BindingPhaseUnbound
46-
case BindingPhaseBound.String():
47-
*p = BindingPhaseBound
48-
default:
49-
return errors.Errorf("unknown binding state %s", ps)
50-
}
51-
return nil
52-
}
19+
// BindingPhase represents the current binding phase of a resource or claim.
20+
type BindingPhase string
5321

5422
// Binding phases.
5523
const (
24+
// BindingPhaseUnknown resources cannot be bound to another resource because
25+
// they are in an unknown binding phase.
26+
BindingPhaseUnknown BindingPhase = ""
27+
5628
// BindingPhaseUnbindable resources cannot be bound to another resource, for
5729
// example because they are currently unavailable, or being created.
58-
BindingPhaseUnbindable BindingPhase = iota
30+
BindingPhaseUnbindable BindingPhase = "Unbindable"
5931

6032
// BindingPhaseUnbound resources are available for binding to another
6133
// resource.
62-
BindingPhaseUnbound
34+
BindingPhaseUnbound BindingPhase = "Unbound"
6335

6436
// BindingPhaseBound resources are bound to another resource.
65-
BindingPhaseBound
37+
BindingPhaseBound BindingPhase = "Bound"
6638
)
6739

6840
// A BindingStatus represents the bindability and binding of a resource.
6941
type BindingStatus struct {
7042
// Phase represents the binding phase of the resource.
43+
// +kubebuilder:validation:Enum=Unbindable,Unbound,Bound
7144
Phase BindingPhase `json:"bindingPhase,omitempty"`
7245
}
7346

pkg/apis/core/v1alpha1/bindingphase_string.go

-16
This file was deleted.

pkg/apis/core/v1alpha1/bindingphase_test.go

-133
This file was deleted.

pkg/resource/reconciler.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ func (r *ClaimReconciler) Reconcile(req reconcile.Request) (reconcile.Result, er
351351
}
352352
}
353353

354-
if managed.GetBindingPhase() == v1alpha1.BindingPhaseUnbindable {
354+
if !IsBindable(managed) && !IsBound(managed) {
355355
// If this claim was not already binding we'll be requeued due to the
356356
// status update. Otherwise there's no need to requeue. We should be
357357
// watching both the resource claims and the resources we own, so we'll
@@ -360,7 +360,7 @@ func (r *ClaimReconciler) Reconcile(req reconcile.Request) (reconcile.Result, er
360360
return reconcile.Result{Requeue: false}, errors.Wrap(r.client.Status().Update(ctx, claim), errUpdateClaimStatus)
361361
}
362362

363-
if managed.GetBindingPhase() == v1alpha1.BindingPhaseUnbound {
363+
if IsBindable(managed) {
364364
if err := r.managed.PropagateConnection(ctx, claim, managed); err != nil {
365365
// If we didn't hit this error last time we'll be requeued implicitly
366366
// due to the status update. Otherwise we want to retry after a brief

pkg/resource/reconciler_test.go

+42-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ func TestReconcile(t *testing.T) {
381381
},
382382
want: want{result: reconcile.Result{RequeueAfter: aShortWait}},
383383
},
384-
"ManagedIsUnbindable": {
384+
"ManagedIsInUnknownBindingPhase": {
385385
args: args{
386386
m: &MockManager{
387387
c: &test.MockClient{
@@ -393,6 +393,9 @@ func TestReconcile(t *testing.T) {
393393
*o = *cm
394394
return nil
395395
case *MockManaged:
396+
// We do not explicitly set a BindingPhase here
397+
// because the zero value of BindingPhase is
398+
// BindingPhaseUnknown.
396399
mg := &MockManaged{}
397400
mg.SetCreationTimestamp(now)
398401
*o = *mg
@@ -418,6 +421,44 @@ func TestReconcile(t *testing.T) {
418421
},
419422
want: want{result: reconcile.Result{Requeue: false}},
420423
},
424+
"ManagedIsInUnbindableBindingPhase": {
425+
args: args{
426+
m: &MockManager{
427+
c: &test.MockClient{
428+
MockGet: test.NewMockGetFn(nil, func(o runtime.Object) error {
429+
switch o := o.(type) {
430+
case *MockClaim:
431+
cm := &MockClaim{}
432+
cm.SetResourceReference(&corev1.ObjectReference{})
433+
*o = *cm
434+
return nil
435+
case *MockManaged:
436+
mg := &MockManaged{}
437+
mg.SetCreationTimestamp(now)
438+
mg.SetBindingPhase(v1alpha1.BindingPhaseUnbindable)
439+
*o = *mg
440+
return nil
441+
default:
442+
return errUnexpected
443+
}
444+
}),
445+
MockStatusUpdate: test.NewMockStatusUpdateFn(nil, func(got runtime.Object) error {
446+
want := &MockClaim{}
447+
want.SetResourceReference(&corev1.ObjectReference{})
448+
want.SetConditions(Binding(), v1alpha1.ReconcileSuccess())
449+
if diff := cmp.Diff(want, got, test.EquateConditions()); diff != "" {
450+
t.Errorf("-want, +got:\n%s", diff)
451+
}
452+
return nil
453+
}),
454+
},
455+
s: MockSchemeWith(&MockClaim{}, &MockManaged{}),
456+
},
457+
of: ClaimKind(MockGVK(&MockClaim{})),
458+
with: ManagedKind(MockGVK(&MockManaged{})),
459+
},
460+
want: want{result: reconcile.Result{Requeue: false}},
461+
},
421462
"PropagateConnectionError": {
422463
args: args{
423464
m: &MockManager{

pkg/resource/resource.go

+12
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,15 @@ func SetBindable(b Bindable) {
115115
}
116116
b.SetBindingPhase(v1alpha1.BindingPhaseUnbound)
117117
}
118+
119+
// IsBindable returns true if the supplied Bindable is ready for binding to
120+
// another Bindable, such as a resource claim or managed resource.
121+
func IsBindable(b Bindable) bool {
122+
return b.GetBindingPhase() == v1alpha1.BindingPhaseUnbound
123+
}
124+
125+
// IsBound returns true if the supplied Bindable is bound to another Bindable,
126+
// such as a resource claim or managed resource.
127+
func IsBound(b Bindable) bool {
128+
return b.GetBindingPhase() == v1alpha1.BindingPhaseBound
129+
}

0 commit comments

Comments
 (0)