Skip to content

Commit 936ca4c

Browse files
committed
WIP
1 parent eab8773 commit 936ca4c

File tree

4 files changed

+276
-41
lines changed

4 files changed

+276
-41
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package status_test
2+
3+
import (
4+
"context"
5+
"errors"
6+
"testing"
7+
8+
"github.com/go-logr/logr"
9+
. "github.com/onsi/gomega"
10+
apierrors "k8s.io/apimachinery/pkg/api/errors"
11+
"k8s.io/apimachinery/pkg/runtime/schema"
12+
"k8s.io/apimachinery/pkg/types"
13+
"sigs.k8s.io/controller-runtime/pkg/client"
14+
"sigs.k8s.io/gateway-api/apis/v1beta1"
15+
16+
"github.com/nginxinc/nginx-gateway-fabric/internal/framework/controller/controllerfakes"
17+
"github.com/nginxinc/nginx-gateway-fabric/internal/framework/status"
18+
"github.com/nginxinc/nginx-gateway-fabric/internal/framework/status/statusfakes"
19+
)
20+
21+
func TestConditionWithContextFunc_GetFails(t *testing.T) {
22+
g := NewWithT(t)
23+
fakeStatusUpdater := &statusfakes.FakeStatusUpdater{}
24+
fakeGetter := &controllerfakes.FakeGetter{}
25+
fakeGetter.GetReturns(errors.New("failed to get resource"))
26+
f := status.ConditionWithContextFunc(
27+
fakeGetter,
28+
fakeStatusUpdater,
29+
types.NamespacedName{},
30+
&v1beta1.GatewayClass{},
31+
logr.New(nil),
32+
func(client.Object) {})
33+
boolean, err := f(context.Background())
34+
g.Expect(err).ToNot(HaveOccurred())
35+
g.Expect(boolean).To(BeFalse())
36+
}
37+
38+
func TestConditionWithContextFunc_GetFailsIsNotFound(t *testing.T) {
39+
g := NewWithT(t)
40+
fakeStatusUpdater := &statusfakes.FakeStatusUpdater{}
41+
fakeGetter := &controllerfakes.FakeGetter{}
42+
fakeGetter.GetReturns(apierrors.NewNotFound(schema.GroupResource{}, "not found"))
43+
f := status.ConditionWithContextFunc(
44+
fakeGetter,
45+
fakeStatusUpdater,
46+
types.NamespacedName{},
47+
&v1beta1.GatewayClass{},
48+
logr.New(nil),
49+
func(client.Object) {})
50+
boolean, err := f(context.Background())
51+
g.Expect(err).ToNot(HaveOccurred())
52+
g.Expect(boolean).To(BeTrue())
53+
}
54+
55+
func TestConditionWithContextFunc_UpdateFails(t *testing.T) {
56+
g := NewWithT(t)
57+
fakeStatusUpdater := &statusfakes.FakeStatusUpdater{}
58+
fakeGetter := &controllerfakes.FakeGetter{}
59+
fakeStatusUpdater.UpdateReturns(errors.New("failed to update resource"))
60+
f := status.ConditionWithContextFunc(
61+
fakeGetter,
62+
fakeStatusUpdater,
63+
types.NamespacedName{},
64+
&v1beta1.GatewayClass{},
65+
logr.New(nil),
66+
func(client.Object) {})
67+
boolean, err := f(context.Background())
68+
g.Expect(err).ToNot(HaveOccurred())
69+
g.Expect(boolean).To(BeFalse())
70+
}
71+
72+
func TestConditionWithContextFunc_NothingFails(t *testing.T) {
73+
g := NewWithT(t)
74+
fakeStatusUpdater := &statusfakes.FakeStatusUpdater{}
75+
fakeGetter := &controllerfakes.FakeGetter{}
76+
f := status.ConditionWithContextFunc(
77+
fakeGetter,
78+
fakeStatusUpdater,
79+
types.NamespacedName{},
80+
&v1beta1.GatewayClass{},
81+
logr.New(nil),
82+
func(client.Object) {})
83+
boolean, err := f(context.Background())
84+
g.Expect(err).ToNot(HaveOccurred())
85+
g.Expect(boolean).To(BeTrue())
86+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package status
2+
3+
import (
4+
"context"
5+
6+
"sigs.k8s.io/controller-runtime/pkg/client"
7+
)
8+
9+
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . StatusUpdater
10+
11+
// StatusUpdater updates a resource from the k8s API.
12+
// It allows us to mock the client.Reader.Status.Update method.
13+
//
14+
// nolint:revive
15+
type StatusUpdater interface {
16+
// Update is from client.StatusClient.SubResourceWriter.
17+
Update(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) error
18+
}

internal/framework/status/statusfakes/fake_status_updater.go

Lines changed: 117 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/framework/status/updater.go

Lines changed: 55 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"sigs.k8s.io/gateway-api/apis/v1beta1"
1616

1717
ngfAPI "github.com/nginxinc/nginx-gateway-fabric/apis/v1alpha1"
18+
"github.com/nginxinc/nginx-gateway-fabric/internal/framework/controller"
1819
)
1920

2021
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Updater
@@ -242,47 +243,7 @@ func (upd *UpdaterImpl) writeStatuses(
242243
Cap: time.Millisecond * 3000,
243244
},
244245
// Function returns true if the condition is satisfied, or an error if the loop should be aborted.
245-
func(ctx context.Context) (bool, error) {
246-
// The function handles errors by reporting them in the logs.
247-
// We need to get the latest version of the resource.
248-
// Otherwise, the Update status API call can fail.
249-
// Note: the default client uses a cache for reads, so we're not making an unnecessary API call here.
250-
// the default is configurable in the Manager options.
251-
if err := upd.cfg.Client.Get(ctx, nsname, obj); err != nil {
252-
// apierrors.IsNotFound(err) can happen when the resource is deleted,
253-
// so no need to retry or return an error.
254-
if apierrors.IsNotFound(err) {
255-
upd.cfg.Logger.V(1).Info(
256-
"Resource was not found when trying to update status",
257-
"error", err,
258-
"namespace", nsname.Namespace,
259-
"name", nsname.Name,
260-
"kind", obj.GetObjectKind().GroupVersionKind().Kind)
261-
return true, nil
262-
}
263-
upd.cfg.Logger.V(1).Info(
264-
"Encountered error when getting resource to update status",
265-
"error", err,
266-
"namespace", nsname.Namespace,
267-
"name", nsname.Name,
268-
"kind", obj.GetObjectKind().GroupVersionKind().Kind)
269-
return false, nil
270-
}
271-
272-
statusSetter(obj)
273-
274-
if err := upd.cfg.Client.Status().Update(ctx, obj); err != nil {
275-
upd.cfg.Logger.V(1).Info(
276-
"Encountered error updating status",
277-
"error", err,
278-
"namespace", nsname.Namespace,
279-
"name", nsname.Name,
280-
"kind", obj.GetObjectKind().GroupVersionKind().Kind)
281-
return false, nil
282-
}
283-
284-
return true, nil
285-
},
246+
ConditionWithContextFunc(upd.cfg.Client, upd.cfg.Client.Status(), nsname, obj, upd.cfg.Logger, statusSetter),
286247
)
287248
if err != nil && !errors.Is(err, context.Canceled) {
288249
upd.cfg.Logger.Error(
@@ -293,3 +254,56 @@ func (upd *UpdaterImpl) writeStatuses(
293254
"kind", obj.GetObjectKind().GroupVersionKind().Kind)
294255
}
295256
}
257+
258+
// ConditionWithContextFunc returns a function which will be used in wait.ExponentialBackoffWithContext.
259+
// Exported for testing purposes.
260+
func ConditionWithContextFunc(
261+
getter controller.Getter,
262+
updater StatusUpdater,
263+
nsname types.NamespacedName,
264+
obj client.Object,
265+
logger logr.Logger,
266+
statusSetter func(client.Object),
267+
) func(ctx context.Context) (bool, error) {
268+
return func(ctx context.Context) (bool, error) {
269+
// The function handles errors by reporting them in the logs.
270+
// We need to get the latest version of the resource.
271+
// Otherwise, the Update status API call can fail.
272+
// Note: the default client uses a cache for reads, so we're not making an unnecessary API call here.
273+
// the default is configurable in the Manager options.
274+
if err := getter.Get(ctx, nsname, obj); err != nil {
275+
// apierrors.IsNotFound(err) can happen when the resource is deleted,
276+
// so no need to retry or return an error.
277+
if apierrors.IsNotFound(err) {
278+
logger.V(1).Info(
279+
"Resource was not found when trying to update status",
280+
"error", err,
281+
"namespace", nsname.Namespace,
282+
"name", nsname.Name,
283+
"kind", obj.GetObjectKind().GroupVersionKind().Kind)
284+
return true, nil
285+
}
286+
logger.V(1).Info(
287+
"Encountered error when getting resource to update status",
288+
"error", err,
289+
"namespace", nsname.Namespace,
290+
"name", nsname.Name,
291+
"kind", obj.GetObjectKind().GroupVersionKind().Kind)
292+
return false, nil
293+
}
294+
295+
statusSetter(obj)
296+
297+
if err := updater.Update(ctx, obj); err != nil {
298+
logger.V(1).Info(
299+
"Encountered error updating status",
300+
"error", err,
301+
"namespace", nsname.Namespace,
302+
"name", nsname.Name,
303+
"kind", obj.GetObjectKind().GroupVersionKind().Kind)
304+
return false, nil
305+
}
306+
307+
return true, nil
308+
}
309+
}

0 commit comments

Comments
 (0)