Make APIFinalizer interface compatible with all Kubernetes resources
Signed-off-by: Muvaffak Onus <onus.muvaffak@gmail.com>
This commit is contained in:
parent
f9d4e859f4
commit
fbeeb71921
|
@ -190,29 +190,3 @@ func (a *APIStatusBinder) Unbind(ctx context.Context, _ resource.Claim, mg resou
|
|||
|
||||
return errors.Wrap(resource.IgnoreNotFound(a.client.Delete(ctx, mg)), errDeleteManaged)
|
||||
}
|
||||
|
||||
// An APIClaimFinalizer adds and removes finalizers to and from a claim.
|
||||
type APIClaimFinalizer struct {
|
||||
client client.Client
|
||||
finalizer string
|
||||
}
|
||||
|
||||
// NewAPIClaimFinalizer returns a new APIClaimFinalizer.
|
||||
func NewAPIClaimFinalizer(c client.Client, finalizer string) *APIClaimFinalizer {
|
||||
return &APIClaimFinalizer{client: c, finalizer: finalizer}
|
||||
}
|
||||
|
||||
// AddFinalizer to the supplied Claim.
|
||||
func (a *APIClaimFinalizer) AddFinalizer(ctx context.Context, cm resource.Claim) error {
|
||||
if meta.FinalizerExists(cm, a.finalizer) {
|
||||
return nil
|
||||
}
|
||||
meta.AddFinalizer(cm, a.finalizer)
|
||||
return errors.Wrap(a.client.Update(ctx, cm), errUpdateClaim)
|
||||
}
|
||||
|
||||
// RemoveFinalizer from the supplied Claim.
|
||||
func (a *APIClaimFinalizer) RemoveFinalizer(ctx context.Context, cm resource.Claim) error {
|
||||
meta.RemoveFinalizer(cm, a.finalizer)
|
||||
return errors.Wrap(resource.IgnoreNotFound(a.client.Update(ctx, cm)), errUpdateClaim)
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ var (
|
|||
_ ManagedCreator = &APIManagedCreator{}
|
||||
_ Binder = &APIBinder{}
|
||||
_ Binder = &APIStatusBinder{}
|
||||
_ ClaimFinalizer = &APIClaimFinalizer{}
|
||||
)
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
|
@ -575,6 +574,7 @@ func TestUnbind(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatusUnbind(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
|
@ -717,119 +717,3 @@ func TestStatusUnbind(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestClaimRemoveFinalizer(t *testing.T) {
|
||||
finalizer := "veryfinal"
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
cm resource.Claim
|
||||
}
|
||||
|
||||
type want struct {
|
||||
err error
|
||||
cm resource.Claim
|
||||
}
|
||||
|
||||
errBoom := errors.New("boom")
|
||||
|
||||
cases := map[string]struct {
|
||||
client client.Client
|
||||
args args
|
||||
want want
|
||||
}{
|
||||
"UpdateClaimError": {
|
||||
client: &test.MockClient{MockUpdate: test.NewMockUpdateFn(errBoom)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
cm: &fake.Claim{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{finalizer}}},
|
||||
},
|
||||
want: want{
|
||||
err: errors.Wrap(errBoom, errUpdateClaim),
|
||||
cm: &fake.Claim{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
},
|
||||
},
|
||||
"Successful": {
|
||||
client: &test.MockClient{MockUpdate: test.NewMockUpdateFn(nil)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
cm: &fake.Claim{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{finalizer}}},
|
||||
},
|
||||
want: want{
|
||||
err: nil,
|
||||
cm: &fake.Claim{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
api := NewAPIClaimFinalizer(tc.client, finalizer)
|
||||
err := api.RemoveFinalizer(tc.args.ctx, tc.args.cm)
|
||||
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
|
||||
t.Errorf("api.Finalize(...): -want error, +got error:\n%s", diff)
|
||||
}
|
||||
if diff := cmp.Diff(tc.want.cm, tc.args.cm, test.EquateConditions()); diff != "" {
|
||||
t.Errorf("api.Finalize(...) Claim: -want, +got:\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIClaimFinalizerAdder(t *testing.T) {
|
||||
finalizer := "veryfinal"
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
cm resource.Claim
|
||||
}
|
||||
|
||||
type want struct {
|
||||
err error
|
||||
cm resource.Claim
|
||||
}
|
||||
|
||||
errBoom := errors.New("boom")
|
||||
|
||||
cases := map[string]struct {
|
||||
client client.Client
|
||||
args args
|
||||
want want
|
||||
}{
|
||||
"UpdateClaimError": {
|
||||
client: &test.MockClient{MockUpdate: test.NewMockUpdateFn(errBoom)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
cm: &fake.Claim{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
},
|
||||
want: want{
|
||||
err: errors.Wrap(errBoom, errUpdateClaim),
|
||||
cm: &fake.Claim{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{finalizer}}},
|
||||
},
|
||||
},
|
||||
"Successful": {
|
||||
client: &test.MockClient{MockUpdate: test.NewMockUpdateFn(nil)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
cm: &fake.Claim{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
},
|
||||
want: want{
|
||||
err: nil,
|
||||
cm: &fake.Claim{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{finalizer}}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
api := NewAPIClaimFinalizer(tc.client, finalizer)
|
||||
err := api.AddFinalizer(tc.args.ctx, tc.args.cm)
|
||||
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
|
||||
t.Errorf("api.Initialize(...): -want error, +got error:\n%s", diff)
|
||||
}
|
||||
if diff := cmp.Diff(tc.want.cm, tc.args.cm, test.EquateConditions()); diff != "" {
|
||||
t.Errorf("api.Initialize(...) Claim: -want, +got:\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,31 +134,6 @@ func (b BinderFns) Unbind(ctx context.Context, cm resource.Claim, mg resource.Ma
|
|||
return b.UnbindFn(ctx, cm, mg)
|
||||
}
|
||||
|
||||
// A ClaimFinalizer finalizes the deletion of a resource claim.
|
||||
type ClaimFinalizer interface {
|
||||
// AddFinalizer to the supplied Claim.
|
||||
AddFinalizer(ctx context.Context, cm resource.Claim) error
|
||||
|
||||
// RemoveFinalizer from the supplied Claim.
|
||||
RemoveFinalizer(ctx context.Context, cm resource.Claim) error
|
||||
}
|
||||
|
||||
// A ClaimFinalizerFns satisfy the ClaimFinalizer interface.
|
||||
type ClaimFinalizerFns struct {
|
||||
AddFinalizerFn func(ctx context.Context, cm resource.Claim) error
|
||||
RemoveFinalizerFn func(ctx context.Context, cm resource.Claim) error
|
||||
}
|
||||
|
||||
// AddFinalizer to the supplied Claim.
|
||||
func (f ClaimFinalizerFns) AddFinalizer(ctx context.Context, cm resource.Claim) error {
|
||||
return f.AddFinalizerFn(ctx, cm)
|
||||
}
|
||||
|
||||
// RemoveFinalizer from the supplied Claim.
|
||||
func (f ClaimFinalizerFns) RemoveFinalizer(ctx context.Context, cm resource.Claim) error {
|
||||
return f.RemoveFinalizerFn(ctx, cm)
|
||||
}
|
||||
|
||||
// A Reconciler reconciles resource claims by creating exactly one kind of
|
||||
// concrete managed resource. Each resource claim kind should create an instance
|
||||
// of this controller for each managed resource kind they can bind to, using
|
||||
|
@ -199,14 +174,14 @@ func defaultCRManaged(m manager.Manager) crManaged {
|
|||
}
|
||||
|
||||
type crClaim struct {
|
||||
ClaimFinalizer
|
||||
resource.Finalizer
|
||||
Binder
|
||||
}
|
||||
|
||||
func defaultCRClaim(m manager.Manager) crClaim {
|
||||
return crClaim{
|
||||
ClaimFinalizer: NewAPIClaimFinalizer(m.GetClient(), claimFinalizerName),
|
||||
Binder: NewAPIStatusBinder(m.GetClient(), m.GetScheme()),
|
||||
Finalizer: resource.NewAPIFinalizer(m.GetClient(), claimFinalizerName),
|
||||
Binder: NewAPIStatusBinder(m.GetClient(), m.GetScheme()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,9 +223,9 @@ func WithBinder(b Binder) ReconcilerOption {
|
|||
|
||||
// WithClaimFinalizer specifies which ClaimFinalizer should be used to finalize
|
||||
// claims when they are deleted.
|
||||
func WithClaimFinalizer(f ClaimFinalizer) ReconcilerOption {
|
||||
func WithClaimFinalizer(f resource.Finalizer) ReconcilerOption {
|
||||
return func(r *Reconciler) {
|
||||
r.claim.ClaimFinalizer = f
|
||||
r.claim.Finalizer = f
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ func TestReconciler(t *testing.T) {
|
|||
with: resource.ManagedKind(fake.GVK(&fake.Managed{})),
|
||||
o: []ReconcilerOption{
|
||||
WithBinder(BinderFns{UnbindFn: func(_ context.Context, _ resource.Claim, _ resource.Managed) error { return nil }}),
|
||||
WithClaimFinalizer(ClaimFinalizerFns{RemoveFinalizerFn: func(_ context.Context, _ resource.Claim) error { return nil }}),
|
||||
WithClaimFinalizer(resource.FinalizerFns{RemoveFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{Requeue: false}},
|
||||
|
@ -247,7 +247,7 @@ func TestReconciler(t *testing.T) {
|
|||
with: resource.ManagedKind(fake.GVK(&fake.Managed{})),
|
||||
o: []ReconcilerOption{
|
||||
WithBinder(BinderFns{UnbindFn: func(_ context.Context, _ resource.Claim, _ resource.Managed) error { return nil }}),
|
||||
WithClaimFinalizer(ClaimFinalizerFns{RemoveFinalizerFn: func(_ context.Context, _ resource.Claim) error { return errBoom }}),
|
||||
WithClaimFinalizer(resource.FinalizerFns{RemoveFinalizerFn: func(_ context.Context, _ resource.Object) error { return errBoom }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{RequeueAfter: aShortWait}},
|
||||
|
@ -275,7 +275,7 @@ func TestReconciler(t *testing.T) {
|
|||
with: resource.ManagedKind(fake.GVK(&fake.Managed{})),
|
||||
o: []ReconcilerOption{
|
||||
WithBinder(BinderFns{UnbindFn: func(_ context.Context, _ resource.Claim, _ resource.Managed) error { return nil }}),
|
||||
WithClaimFinalizer(ClaimFinalizerFns{RemoveFinalizerFn: func(_ context.Context, _ resource.Claim) error { return nil }}),
|
||||
WithClaimFinalizer(resource.FinalizerFns{RemoveFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{Requeue: false}},
|
||||
|
@ -421,8 +421,8 @@ func TestReconciler(t *testing.T) {
|
|||
WithManagedConfigurators(ManagedConfiguratorFn(
|
||||
func(_ context.Context, _ resource.Claim, _ resource.Class, _ resource.Managed) error { return nil },
|
||||
)),
|
||||
WithClaimFinalizer(ClaimFinalizerFns{
|
||||
AddFinalizerFn: func(_ context.Context, _ resource.Claim) error { return nil }},
|
||||
WithClaimFinalizer(resource.FinalizerFns{
|
||||
AddFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil }},
|
||||
),
|
||||
WithManagedCreator(ManagedCreatorFn(
|
||||
func(_ context.Context, _ resource.Claim, _ resource.Class, _ resource.Managed) error { return errBoom },
|
||||
|
@ -599,8 +599,8 @@ func TestReconciler(t *testing.T) {
|
|||
WithManagedConnectionPropagator(resource.ManagedConnectionPropagatorFn(
|
||||
func(_ context.Context, _ resource.LocalConnectionSecretOwner, _ resource.Managed) error { return nil },
|
||||
)),
|
||||
WithClaimFinalizer(ClaimFinalizerFns{
|
||||
AddFinalizerFn: func(_ context.Context, _ resource.Claim) error { return errBoom }},
|
||||
WithClaimFinalizer(resource.FinalizerFns{
|
||||
AddFinalizerFn: func(_ context.Context, _ resource.Object) error { return errBoom }},
|
||||
),
|
||||
},
|
||||
},
|
||||
|
@ -646,8 +646,8 @@ func TestReconciler(t *testing.T) {
|
|||
WithManagedConnectionPropagator(resource.ManagedConnectionPropagatorFn(
|
||||
func(_ context.Context, _ resource.LocalConnectionSecretOwner, _ resource.Managed) error { return nil },
|
||||
)),
|
||||
WithClaimFinalizer(ClaimFinalizerFns{
|
||||
AddFinalizerFn: func(_ context.Context, _ resource.Claim) error { return nil }},
|
||||
WithClaimFinalizer(resource.FinalizerFns{
|
||||
AddFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil }},
|
||||
),
|
||||
WithBinder(BinderFns{
|
||||
BindFn: func(_ context.Context, _ resource.Claim, _ resource.Managed) error { return errBoom },
|
||||
|
|
|
@ -34,32 +34,6 @@ const (
|
|||
errUpdateManagedStatus = "cannot update managed resource status"
|
||||
)
|
||||
|
||||
// An APIFinalizer adds and removes finalizers to and from a resource.
|
||||
type APIFinalizer struct {
|
||||
client client.Client
|
||||
finalizer string
|
||||
}
|
||||
|
||||
// NewAPIFinalizer returns a new APIFinalizer.
|
||||
func NewAPIFinalizer(c client.Client, finalizer string) *APIFinalizer {
|
||||
return &APIFinalizer{client: c, finalizer: finalizer}
|
||||
}
|
||||
|
||||
// AddFinalizer to the supplied Managed resource.
|
||||
func (a *APIFinalizer) AddFinalizer(ctx context.Context, mg resource.Managed) error {
|
||||
if meta.FinalizerExists(mg, a.finalizer) {
|
||||
return nil
|
||||
}
|
||||
meta.AddFinalizer(mg, a.finalizer)
|
||||
return errors.Wrap(a.client.Update(ctx, mg), errUpdateManaged)
|
||||
}
|
||||
|
||||
// RemoveFinalizer from the supplied Managed resource.
|
||||
func (a *APIFinalizer) RemoveFinalizer(ctx context.Context, mg resource.Managed) error {
|
||||
meta.RemoveFinalizer(mg, a.finalizer)
|
||||
return errors.Wrap(resource.IgnoreNotFound(a.client.Update(ctx, mg)), errUpdateManaged)
|
||||
}
|
||||
|
||||
// NameAsExternalName writes the name of the managed resource to
|
||||
// the external name annotation field in order to be used as name of
|
||||
// the external resource in provider.
|
||||
|
|
|
@ -34,126 +34,9 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
_ Finalizer = &APIFinalizer{}
|
||||
_ Initializer = &NameAsExternalName{}
|
||||
)
|
||||
|
||||
func TestManagedRemoveFinalizer(t *testing.T) {
|
||||
finalizer := "veryfinal"
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
mg resource.Managed
|
||||
}
|
||||
|
||||
type want struct {
|
||||
err error
|
||||
mg resource.Managed
|
||||
}
|
||||
|
||||
errBoom := errors.New("boom")
|
||||
|
||||
cases := map[string]struct {
|
||||
client client.Client
|
||||
args args
|
||||
want want
|
||||
}{
|
||||
"UpdateManagedError": {
|
||||
client: &test.MockClient{MockUpdate: test.NewMockUpdateFn(errBoom)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
mg: &fake.Managed{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{finalizer}}},
|
||||
},
|
||||
want: want{
|
||||
err: errors.Wrap(errBoom, errUpdateManaged),
|
||||
mg: &fake.Managed{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
},
|
||||
},
|
||||
"Successful": {
|
||||
client: &test.MockClient{MockUpdate: test.NewMockUpdateFn(nil)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
mg: &fake.Managed{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{finalizer}}},
|
||||
},
|
||||
want: want{
|
||||
err: nil,
|
||||
mg: &fake.Managed{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
api := NewAPIFinalizer(tc.client, finalizer)
|
||||
err := api.RemoveFinalizer(tc.args.ctx, tc.args.mg)
|
||||
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
|
||||
t.Errorf("api.RemoveFinalizer(...): -want error, +got error:\n%s", diff)
|
||||
}
|
||||
if diff := cmp.Diff(tc.want.mg, tc.args.mg, test.EquateConditions()); diff != "" {
|
||||
t.Errorf("api.RemoveFinalizer(...) Managed: -want, +got:\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIFinalizerAdder(t *testing.T) {
|
||||
finalizer := "veryfinal"
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
mg resource.Managed
|
||||
}
|
||||
|
||||
type want struct {
|
||||
err error
|
||||
mg resource.Managed
|
||||
}
|
||||
|
||||
errBoom := errors.New("boom")
|
||||
|
||||
cases := map[string]struct {
|
||||
client client.Client
|
||||
args args
|
||||
want want
|
||||
}{
|
||||
"UpdateManagedError": {
|
||||
client: &test.MockClient{MockUpdate: test.NewMockUpdateFn(errBoom)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
mg: &fake.Managed{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
},
|
||||
want: want{
|
||||
err: errors.Wrap(errBoom, errUpdateManaged),
|
||||
mg: &fake.Managed{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{finalizer}}},
|
||||
},
|
||||
},
|
||||
"Successful": {
|
||||
client: &test.MockClient{MockUpdate: test.NewMockUpdateFn(nil)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
mg: &fake.Managed{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
},
|
||||
want: want{
|
||||
err: nil,
|
||||
mg: &fake.Managed{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{finalizer}}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
api := NewAPIFinalizer(tc.client, finalizer)
|
||||
err := api.AddFinalizer(tc.args.ctx, tc.args.mg)
|
||||
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
|
||||
t.Errorf("api.Initialize(...): -want error, +got error:\n%s", diff)
|
||||
}
|
||||
if diff := cmp.Diff(tc.want.mg, tc.args.mg, test.EquateConditions()); diff != "" {
|
||||
t.Errorf("api.Initialize(...) Managed: -want, +got:\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNameAsExternalName(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
|
|
|
@ -130,31 +130,6 @@ func (cc InitializerChain) Initialize(ctx context.Context, mg resource.Managed)
|
|||
return nil
|
||||
}
|
||||
|
||||
// A Finalizer finalizes the deletion of a resource claim.
|
||||
type Finalizer interface {
|
||||
// AddFinalizer to the supplied Managed resource.
|
||||
AddFinalizer(ctx context.Context, mg resource.Managed) error
|
||||
|
||||
// RemoveFinalizer from the supplied Managed resource.
|
||||
RemoveFinalizer(ctx context.Context, mg resource.Managed) error
|
||||
}
|
||||
|
||||
// A FinalizerFns satisfy the Finalizer interface.
|
||||
type FinalizerFns struct {
|
||||
AddFinalizerFn func(ctx context.Context, mg resource.Managed) error
|
||||
RemoveFinalizerFn func(ctx context.Context, mg resource.Managed) error
|
||||
}
|
||||
|
||||
// AddFinalizer to the supplied Managed resource.
|
||||
func (f FinalizerFns) AddFinalizer(ctx context.Context, mg resource.Managed) error {
|
||||
return f.AddFinalizerFn(ctx, mg)
|
||||
}
|
||||
|
||||
// RemoveFinalizer from the supplied Managed resource.
|
||||
func (f FinalizerFns) RemoveFinalizer(ctx context.Context, mg resource.Managed) error {
|
||||
return f.RemoveFinalizerFn(ctx, mg)
|
||||
}
|
||||
|
||||
// A InitializerFn is a function that satisfies the Initializer
|
||||
// interface.
|
||||
type InitializerFn func(ctx context.Context, mg resource.Managed) error
|
||||
|
@ -333,7 +308,7 @@ type Reconciler struct {
|
|||
|
||||
type mrManaged struct {
|
||||
ConnectionPublisher
|
||||
Finalizer
|
||||
resource.Finalizer
|
||||
Initializer
|
||||
ReferenceResolver
|
||||
}
|
||||
|
@ -341,7 +316,7 @@ type mrManaged struct {
|
|||
func defaultMRManaged(m manager.Manager) mrManaged {
|
||||
return mrManaged{
|
||||
ConnectionPublisher: NewAPISecretPublisher(m.GetClient(), m.GetScheme()),
|
||||
Finalizer: NewAPIFinalizer(m.GetClient(), managedFinalizerName),
|
||||
Finalizer: resource.NewAPIFinalizer(m.GetClient(), managedFinalizerName),
|
||||
Initializer: NewNameAsExternalName(m.GetClient()),
|
||||
ReferenceResolver: NewAPIReferenceResolver(m.GetClient()),
|
||||
}
|
||||
|
@ -417,7 +392,7 @@ func WithInitializers(i ...Initializer) ReconcilerOption {
|
|||
|
||||
// WithFinalizer specifies how the Reconciler should add and remove
|
||||
// finalizers to and from the managed resource.
|
||||
func WithFinalizer(f Finalizer) ReconcilerOption {
|
||||
func WithFinalizer(f resource.Finalizer) ReconcilerOption {
|
||||
return func(r *Reconciler) {
|
||||
r.managed.Finalizer = f
|
||||
}
|
||||
|
|
|
@ -396,7 +396,7 @@ func TestReconciler(t *testing.T) {
|
|||
return c, nil
|
||||
})),
|
||||
WithConnectionPublishers(),
|
||||
WithFinalizer(FinalizerFns{RemoveFinalizerFn: func(_ context.Context, _ resource.Managed) error { return errBoom }}),
|
||||
WithFinalizer(resource.FinalizerFns{RemoveFinalizerFn: func(_ context.Context, _ resource.Object) error { return errBoom }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{RequeueAfter: defaultManagedShortWait}},
|
||||
|
@ -427,7 +427,7 @@ func TestReconciler(t *testing.T) {
|
|||
return c, nil
|
||||
})),
|
||||
WithConnectionPublishers(),
|
||||
WithFinalizer(FinalizerFns{RemoveFinalizerFn: func(_ context.Context, _ resource.Managed) error { return nil }}),
|
||||
WithFinalizer(resource.FinalizerFns{RemoveFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{Requeue: false}},
|
||||
|
@ -488,7 +488,7 @@ func TestReconciler(t *testing.T) {
|
|||
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
|
||||
WithExternalConnecter(&NopConnecter{}),
|
||||
WithConnectionPublishers(),
|
||||
WithFinalizer(FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Managed) error { return errBoom }}),
|
||||
WithFinalizer(resource.FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Object) error { return errBoom }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{RequeueAfter: defaultManagedShortWait}},
|
||||
|
@ -528,7 +528,7 @@ func TestReconciler(t *testing.T) {
|
|||
return c, nil
|
||||
})),
|
||||
WithConnectionPublishers(),
|
||||
WithFinalizer(FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Managed) error { return nil }}),
|
||||
WithFinalizer(resource.FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{RequeueAfter: defaultManagedShortWait}},
|
||||
|
@ -579,7 +579,7 @@ func TestReconciler(t *testing.T) {
|
|||
return nil
|
||||
},
|
||||
}),
|
||||
WithFinalizer(FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Managed) error { return nil }}),
|
||||
WithFinalizer(resource.FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{RequeueAfter: defaultManagedShortWait}},
|
||||
|
@ -609,7 +609,7 @@ func TestReconciler(t *testing.T) {
|
|||
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
|
||||
WithExternalConnecter(&NopConnecter{}),
|
||||
WithConnectionPublishers(),
|
||||
WithFinalizer(FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Managed) error { return nil }}),
|
||||
WithFinalizer(resource.FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{RequeueAfter: defaultManagedShortWait}},
|
||||
|
@ -646,7 +646,7 @@ func TestReconciler(t *testing.T) {
|
|||
return c, nil
|
||||
})),
|
||||
WithConnectionPublishers(),
|
||||
WithFinalizer(FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Managed) error { return nil }}),
|
||||
WithFinalizer(resource.FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{RequeueAfter: defaultManagedLongWait}},
|
||||
|
@ -686,7 +686,7 @@ func TestReconciler(t *testing.T) {
|
|||
return c, nil
|
||||
})),
|
||||
WithConnectionPublishers(),
|
||||
WithFinalizer(FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Managed) error { return nil }}),
|
||||
WithFinalizer(resource.FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{RequeueAfter: defaultManagedShortWait}},
|
||||
|
@ -737,7 +737,7 @@ func TestReconciler(t *testing.T) {
|
|||
return nil
|
||||
},
|
||||
}),
|
||||
WithFinalizer(FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Managed) error { return nil }}),
|
||||
WithFinalizer(resource.FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{RequeueAfter: defaultManagedShortWait}},
|
||||
|
@ -777,7 +777,7 @@ func TestReconciler(t *testing.T) {
|
|||
return c, nil
|
||||
})),
|
||||
WithConnectionPublishers(),
|
||||
WithFinalizer(FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Managed) error { return nil }}),
|
||||
WithFinalizer(resource.FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Object) error { return nil }}),
|
||||
},
|
||||
},
|
||||
want: want{result: reconcile.Result{RequeueAfter: defaultManagedLongWait}},
|
||||
|
|
|
@ -37,6 +37,8 @@ const (
|
|||
errSecretConflict = "cannot establish control of existing connection secret"
|
||||
errUpdateSecret = "cannot update connection secret"
|
||||
errCreateOrUpdateSecret = "cannot create or update connection secret"
|
||||
|
||||
errUpdateObject = "cannot update object"
|
||||
)
|
||||
|
||||
// An APIManagedConnectionPropagator propagates connection details by reading
|
||||
|
@ -176,3 +178,48 @@ func (a *APIUpdatingApplicator) Apply(ctx context.Context, o runtime.Object, ao
|
|||
|
||||
return errors.Wrap(a.client.Update(ctx, o), "cannot update object")
|
||||
}
|
||||
|
||||
// An APIFinalizer adds and removes finalizers to and from a resource.
|
||||
type APIFinalizer struct {
|
||||
client client.Client
|
||||
finalizer string
|
||||
}
|
||||
|
||||
// NewAPIFinalizer returns a new APIFinalizer.
|
||||
func NewAPIFinalizer(c client.Client, finalizer string) *APIFinalizer {
|
||||
return &APIFinalizer{client: c, finalizer: finalizer}
|
||||
}
|
||||
|
||||
// AddFinalizer to the supplied Managed resource.
|
||||
func (a *APIFinalizer) AddFinalizer(ctx context.Context, obj Object) error {
|
||||
if meta.FinalizerExists(obj, a.finalizer) {
|
||||
return nil
|
||||
}
|
||||
meta.AddFinalizer(obj, a.finalizer)
|
||||
return errors.Wrap(a.client.Update(ctx, obj), errUpdateObject)
|
||||
}
|
||||
|
||||
// RemoveFinalizer from the supplied Managed resource.
|
||||
func (a *APIFinalizer) RemoveFinalizer(ctx context.Context, obj Object) error {
|
||||
if !meta.FinalizerExists(obj, a.finalizer) {
|
||||
return nil
|
||||
}
|
||||
meta.RemoveFinalizer(obj, a.finalizer)
|
||||
return errors.Wrap(IgnoreNotFound(a.client.Update(ctx, obj)), errUpdateObject)
|
||||
}
|
||||
|
||||
// A FinalizerFns satisfy the Finalizer interface.
|
||||
type FinalizerFns struct {
|
||||
AddFinalizerFn func(ctx context.Context, obj Object) error
|
||||
RemoveFinalizerFn func(ctx context.Context, obj Object) error
|
||||
}
|
||||
|
||||
// AddFinalizer to the supplied resource.
|
||||
func (f FinalizerFns) AddFinalizer(ctx context.Context, obj Object) error {
|
||||
return f.AddFinalizerFn(ctx, obj)
|
||||
}
|
||||
|
||||
// RemoveFinalizer from the supplied resource.
|
||||
func (f FinalizerFns) RemoveFinalizer(ctx context.Context, obj Object) error {
|
||||
return f.RemoveFinalizerFn(ctx, obj)
|
||||
}
|
||||
|
|
|
@ -490,3 +490,119 @@ func TestAPIUpdatingApplicator(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestManagedRemoveFinalizer(t *testing.T) {
|
||||
finalizer := "veryfinal"
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
obj Object
|
||||
}
|
||||
|
||||
type want struct {
|
||||
err error
|
||||
obj Object
|
||||
}
|
||||
|
||||
errBoom := errors.New("boom")
|
||||
|
||||
cases := map[string]struct {
|
||||
client client.Client
|
||||
args args
|
||||
want want
|
||||
}{
|
||||
"UpdateError": {
|
||||
client: &test.MockClient{MockUpdate: test.NewMockUpdateFn(errBoom)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
obj: &fake.Object{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{finalizer}}},
|
||||
},
|
||||
want: want{
|
||||
err: errors.Wrap(errBoom, errUpdateObject),
|
||||
obj: &fake.Object{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
},
|
||||
},
|
||||
"Successful": {
|
||||
client: &test.MockClient{MockUpdate: test.NewMockUpdateFn(nil)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
obj: &fake.Object{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{finalizer}}},
|
||||
},
|
||||
want: want{
|
||||
err: nil,
|
||||
obj: &fake.Object{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
api := NewAPIFinalizer(tc.client, finalizer)
|
||||
err := api.RemoveFinalizer(tc.args.ctx, tc.args.obj)
|
||||
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
|
||||
t.Errorf("api.RemoveFinalizer(...): -want error, +got error:\n%s", diff)
|
||||
}
|
||||
if diff := cmp.Diff(tc.want.obj, tc.args.obj, test.EquateConditions()); diff != "" {
|
||||
t.Errorf("api.RemoveFinalizer(...) Managed: -want, +got:\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIFinalizerAdder(t *testing.T) {
|
||||
finalizer := "veryfinal"
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
obj Object
|
||||
}
|
||||
|
||||
type want struct {
|
||||
err error
|
||||
obj Object
|
||||
}
|
||||
|
||||
errBoom := errors.New("boom")
|
||||
|
||||
cases := map[string]struct {
|
||||
client client.Client
|
||||
args args
|
||||
want want
|
||||
}{
|
||||
"UpdateError": {
|
||||
client: &test.MockClient{MockUpdate: test.NewMockUpdateFn(errBoom)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
obj: &fake.Object{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
},
|
||||
want: want{
|
||||
err: errors.Wrap(errBoom, errUpdateObject),
|
||||
obj: &fake.Object{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{finalizer}}},
|
||||
},
|
||||
},
|
||||
"Successful": {
|
||||
client: &test.MockClient{MockUpdate: test.NewMockUpdateFn(nil)},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
obj: &fake.Object{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
},
|
||||
want: want{
|
||||
err: nil,
|
||||
obj: &fake.Object{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{finalizer}}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
api := NewAPIFinalizer(tc.client, finalizer)
|
||||
err := api.AddFinalizer(tc.args.ctx, tc.args.obj)
|
||||
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
|
||||
t.Errorf("api.Initialize(...): -want error, +got error:\n%s", diff)
|
||||
}
|
||||
if diff := cmp.Diff(tc.want.obj, tc.args.obj, test.EquateConditions()); diff != "" {
|
||||
t.Errorf("api.Initialize(...) Managed: -want, +got:\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ limitations under the License.
|
|||
package resource
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
@ -101,6 +103,12 @@ type WorkloadReferencer interface {
|
|||
SetWorkloadReference(v1alpha1.TypedReference)
|
||||
}
|
||||
|
||||
// A Finalizer manages the finalizers on the resource.
|
||||
type Finalizer interface {
|
||||
AddFinalizer(ctx context.Context, obj Object) error
|
||||
RemoveFinalizer(ctx context.Context, obj Object) error
|
||||
}
|
||||
|
||||
// An Object is a Kubernetes object.
|
||||
type Object interface {
|
||||
metav1.Object
|
||||
|
|
Loading…
Reference in New Issue