Skip to content

Commit 2e5e80a

Browse files
committed
add new component State: DeletionPending
1 parent 5c7bcd9 commit 2e5e80a

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

pkg/component/reconcile.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,27 @@ import (
4141
// TODO: make a can-i check before emitting events to deployment target (e.g. in the client factory when creating the client)
4242
// TODO: allow to override namespace auto-creation and adoption policy settings on a per-component level
4343
// (e.g. through annotations or another interface that components could optionally implement)
44+
// TODO: allow some timeout feature, such that component will go into error state if not ready within the given timeout
45+
// (e.g. through a TimeoutConfiguration interface that components could optionally implement)
4446
// TODO: run admission webhooks (if present) in reconcile (e.g. as post-read hook)
4547

4648
const (
4749
readyConditionReasonNew = "FirstSeen"
48-
readyConditionPending = "Pending"
50+
readyConditionReasonPending = "Pending"
4951
readyConditionReasonProcessing = "Processing"
5052
readyConditionReasonReady = "Ready"
5153
readyConditionReasonError = "Error"
54+
readyConditionReasonDeletionPending = "DeletionPending"
5255
readyConditionReasonDeletionBlocked = "DeletionBlocked"
5356
readyConditionReasonDeletionProcessing = "DeletionProcessing"
5457
)
5558

59+
// TODO: should we pass cluster.Client to hooks instead of just client.Client?
60+
5661
// HookFunc is the function signature that can be used to
5762
// establish callbacks at certain points in the reconciliation logic.
58-
// Hooks will be passed the current (potentially unsaved) state of the component.
63+
// Hooks will be passed a local client (to be precise, the one belonging to the owning
64+
// manager), and the current (potentially unsaved) state of the component.
5965
// Post-hooks will only be called if the according operation (read, reconcile, delete)
6066
// has been successful.
6167
type HookFunc[T Component] func(ctx context.Context, client client.Client, component T) error
@@ -183,13 +189,20 @@ func (r *Reconciler[T]) Reconcile(ctx context.Context, req ctrl.Request) (result
183189
if retryAfter == nil || *retryAfter == 0 {
184190
retryAfter = &retryInterval
185191
}
186-
status.SetState(StatePending, readyConditionPending, err.Error())
192+
// TODO: allow RetriableError to provide custom reason and message
193+
if component.GetDeletionTimestamp().IsZero() {
194+
status.SetState(StatePending, readyConditionReasonPending, capitalize(err.Error()))
195+
} else {
196+
status.SetState(StateDeletionPending, readyConditionReasonDeletionPending, capitalize(err.Error()))
197+
}
187198
result = ctrl.Result{RequeueAfter: *retryAfter}
188199
err = nil
189200
} else {
190201
status.SetState(StateError, readyConditionReasonError, err.Error())
191202
}
192203
}
204+
// TODO: should we move this behind the DeepEqual check below?
205+
// TODO: follow-up on missing events
193206
state, reason, message := status.GetState()
194207
if state == StateError {
195208
r.client.EventRecorder().Event(component, corev1.EventTypeWarning, reason, message)
@@ -284,11 +297,13 @@ func (r *Reconciler[T]) Reconcile(ctx context.Context, req ctrl.Request) (result
284297
return ctrl.Result{}, errors.Wrap(err, "error checking whether deletion is possible")
285298
}
286299
log.V(1).Info("deletion not allowed")
300+
// TODO: have an additional StateDeletionBlocked?
287301
status.SetState(StateDeleting, readyConditionReasonDeletionBlocked, "Deletion blocked: "+msg)
288302
return ctrl.Result{RequeueAfter: 1*time.Second + r.backoff.Next(req, readyConditionReasonDeletionBlocked)}, nil
289303
} else if len(slices.Remove(component.GetFinalizers(), r.name)) > 0 {
290304
// deletion is blocked because of foreign finalizers
291305
log.V(1).Info("deleted blocked due to existence of foreign finalizers")
306+
// TODO: have an additional StateDeletionBlocked?
292307
status.SetState(StateDeleting, readyConditionReasonDeletionBlocked, "Deletion blocked due to existing foreign finalizers")
293308
return ctrl.Result{RequeueAfter: 1*time.Second + r.backoff.Next(req, readyConditionReasonDeletionBlocked)}, nil
294309
} else {

pkg/component/types.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ type Status struct {
151151
LastObservedAt *metav1.Time `json:"lastObservedAt,omitempty"`
152152
LastAppliedAt *metav1.Time `json:"lastAppliedAt,omitempty"`
153153
Conditions []Condition `json:"conditions,omitempty"`
154-
// +kubebuilder:validation:Enum=Ready;Pending;Processing;Deleting;Error
154+
// +kubebuilder:validation:Enum=Ready;Pending;Processing;DeletionPending;Deleting;Error
155155
State State `json:"state,omitempty"`
156156
Inventory []*InventoryItem `json:"inventory,omitempty"`
157157
}
@@ -191,7 +191,7 @@ const (
191191
ConditionUnknown ConditionStatus = "Unknown"
192192
)
193193

194-
// Component state. Can be one of 'Ready', 'Pending', 'Processing', 'Deleting', 'Error'.
194+
// Component state. Can be one of 'Ready', 'Pending', 'Processing', 'DeletionPending', 'Deleting', 'Error'.
195195
type State string
196196

197197
const (
@@ -201,6 +201,8 @@ const (
201201
StatePending State = "Pending"
202202
// Component state 'Processing'.
203203
StateProcessing State = "Processing"
204+
// Component state 'DeletionPending'.
205+
StateDeletionPending State = "DeletionPending"
204206
// Component state 'Deleting'.
205207
StateDeleting State = "Deleting"
206208
// Component state 'Error'.

pkg/component/util.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ func sha256base32(data []byte) string {
3535
return strings.ToLower(base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(sum[:]))
3636
}
3737

38+
func capitalize(s string) string {
39+
if len(s) <= 1 {
40+
return s
41+
}
42+
return strings.ToUpper(s[0:1]) + s[1:]
43+
}
44+
3845
func calculateObjectDigest(obj client.Object) (string, error) {
3946
resourceVersion := obj.GetResourceVersion()
4047
defer obj.SetResourceVersion(resourceVersion)

0 commit comments

Comments
 (0)