-
Notifications
You must be signed in to change notification settings - Fork 98
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement Status Updater Retrying on Failures (#1062)
Implement retries on status update failure. Problem: NGF will not retry on status update failure, thus there is a chance that some resources will not have up-to-do statuses. Solution: Add retry logic when status update fails with a small exponential backoff after each retry. Also, added logic to allow for a graceful exit of the status updater when the NGF pod context is cancelled.
- Loading branch information
Showing
5 changed files
with
343 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package status | ||
|
||
import ( | ||
"context" | ||
|
||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . K8sUpdater | ||
|
||
// K8sUpdater updates a resource from the k8s API. | ||
// It allows us to mock the client.Reader.Status.Update method. | ||
type K8sUpdater interface { | ||
// Update is from client.StatusClient.SubResourceWriter. | ||
Update(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) error | ||
} |
117 changes: 117 additions & 0 deletions
117
internal/framework/status/statusfakes/fake_k8s_updater.go
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package status_test | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"testing" | ||
|
||
. "github.com/onsi/gomega" | ||
apierrors "k8s.io/apimachinery/pkg/api/errors" | ||
"k8s.io/apimachinery/pkg/runtime/schema" | ||
"k8s.io/apimachinery/pkg/types" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
"sigs.k8s.io/controller-runtime/pkg/log/zap" | ||
"sigs.k8s.io/gateway-api/apis/v1beta1" | ||
|
||
"github.com/nginxinc/nginx-gateway-fabric/internal/framework/controller/controllerfakes" | ||
"github.com/nginxinc/nginx-gateway-fabric/internal/framework/status" | ||
"github.com/nginxinc/nginx-gateway-fabric/internal/framework/status/statusfakes" | ||
) | ||
|
||
func TestNewRetryUpdateFunc(t *testing.T) { | ||
tests := []struct { | ||
getReturns error | ||
updateReturns error | ||
name string | ||
expConditionPassed bool | ||
}{ | ||
{ | ||
getReturns: errors.New("failed to get resource"), | ||
updateReturns: nil, | ||
name: "get fails", | ||
expConditionPassed: false, | ||
}, | ||
{ | ||
getReturns: apierrors.NewNotFound(schema.GroupResource{}, "not found"), | ||
updateReturns: nil, | ||
name: "get fails and apierrors is not found", | ||
expConditionPassed: true, | ||
}, | ||
{ | ||
getReturns: nil, | ||
updateReturns: errors.New("failed to update resource"), | ||
name: "update fails", | ||
expConditionPassed: false, | ||
}, | ||
{ | ||
getReturns: nil, | ||
updateReturns: nil, | ||
name: "nothing fails", | ||
expConditionPassed: true, | ||
}, | ||
} | ||
|
||
fakeStatusUpdater := &statusfakes.FakeK8sUpdater{} | ||
fakeGetter := &controllerfakes.FakeGetter{} | ||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
g := NewWithT(t) | ||
fakeStatusUpdater.UpdateReturns(test.updateReturns) | ||
fakeGetter.GetReturns(test.getReturns) | ||
f := status.NewRetryUpdateFunc( | ||
fakeGetter, | ||
fakeStatusUpdater, | ||
types.NamespacedName{}, | ||
&v1beta1.GatewayClass{}, | ||
zap.New(), | ||
func(client.Object) {}) | ||
conditionPassed, err := f(context.Background()) | ||
|
||
// The function should always return nil. | ||
g.Expect(err).ToNot(HaveOccurred()) | ||
g.Expect(conditionPassed).To(Equal(test.expConditionPassed)) | ||
}) | ||
} | ||
} |
Oops, something went wrong.