-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
internal: added helper for status update
- Loading branch information
Showing
2 changed files
with
138 additions
and
0 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,80 @@ | ||
// Copyright 2025 The Atlas Operator Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package result | ||
|
||
import ( | ||
"errors" | ||
"time" | ||
|
||
ctrl "sigs.k8s.io/controller-runtime" | ||
) | ||
|
||
// Transient checks if the error is transient and returns a result | ||
// that indicates whether the request should be retried. | ||
func Transient(err error) (r ctrl.Result, _ error) { | ||
if t := (*transientError)(nil); errors.As(err, &t) { | ||
return Retry(t.after) | ||
} | ||
// Permanent errors are not returned as errors because they cause | ||
// the controller to requeue indefinitely. Instead, they should be | ||
// reported as a status condition. | ||
return OK() | ||
} | ||
|
||
// OK returns a successful result | ||
func OK() (ctrl.Result, error) { | ||
return ctrl.Result{}, nil | ||
} | ||
|
||
// Failed returns a failed result | ||
func Failed() (ctrl.Result, error) { | ||
return Retry(0) | ||
} | ||
|
||
// Retry requeues the request after the specified number of seconds | ||
func Retry(after int) (ctrl.Result, error) { | ||
return ctrl.Result{ | ||
Requeue: true, | ||
RequeueAfter: time.Second * time.Duration(after), | ||
}, nil | ||
} | ||
|
||
// transientError is an error that should be retried. | ||
type transientError struct { | ||
err error | ||
after int | ||
} | ||
|
||
func (t *transientError) Error() string { return t.err.Error() } | ||
func (t *transientError) Unwrap() error { return t.err } | ||
|
||
// TransientError wraps an error to indicate that it should be retried. | ||
func TransientError(err error) error { | ||
return TransientErrorAfter(err, 5) | ||
} | ||
|
||
// TransientErrorAfter wraps an error to indicate that it should be retried after | ||
// the given duration. | ||
func TransientErrorAfter(err error, after int) error { | ||
if err == nil { | ||
return nil | ||
} | ||
return &transientError{err: err, after: after} | ||
} | ||
|
||
func isTransient(err error) bool { | ||
var t *transientError | ||
return errors.As(err, &t) | ||
} |
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,58 @@ | ||
// Copyright 2025 The Atlas Operator Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package status | ||
|
||
import ( | ||
"context" | ||
|
||
ctrl "sigs.k8s.io/controller-runtime" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
type ( | ||
// OptionBuilder is an interface that can be implemented | ||
// by any type that can provide a list of options | ||
OptionBuilder[T any] interface { | ||
GetOptions() []Option[T] | ||
} | ||
// Option is an interface that can be implemented by any type | ||
// that can apply an option to a resource and return a result | ||
Option[T any] interface { | ||
ApplyOption(o T) | ||
GetResult() (ctrl.Result, error) | ||
} | ||
) | ||
|
||
// Update takes the options provided by the given option builder, applies them all and then updates the resource | ||
func Update[T client.Object](ctx context.Context, sw client.StatusWriter, obj T, b OptionBuilder[T]) (r ctrl.Result, err error) { | ||
opts := b.GetOptions() | ||
for _, o := range opts { | ||
o.ApplyOption(obj) | ||
} | ||
if err := sw.Update(ctx, obj); err != nil { | ||
return ctrl.Result{}, err | ||
} | ||
for _, o := range opts { | ||
if r, err = o.GetResult(); err != nil { | ||
return r, err | ||
} | ||
} | ||
for _, o := range opts { | ||
if r, _ := o.GetResult(); r.Requeue || r.RequeueAfter > 0 { | ||
return r, nil | ||
} | ||
} | ||
return ctrl.Result{}, nil | ||
} |