Skip to content

Commit 55be958

Browse files
authored
Merge pull request #1444 from fluxcd/gc-wait-for-termination
Implement `WaitForTermination` deletion policy
2 parents c25690c + 413118e commit 55be958

8 files changed

Lines changed: 72 additions & 21 deletions

File tree

api/v1/kustomization_types.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ const (
3434
IfNotPresentValue = "IfNotPresent"
3535
IgnoreValue = "Ignore"
3636

37-
DeletionPolicyMirrorPrune = "MirrorPrune"
38-
DeletionPolicyDelete = "Delete"
39-
DeletionPolicyOrphan = "Orphan"
37+
DeletionPolicyMirrorPrune = "MirrorPrune"
38+
DeletionPolicyDelete = "Delete"
39+
DeletionPolicyWaitForTermination = "WaitForTermination"
40+
DeletionPolicyOrphan = "Orphan"
4041
)
4142

4243
// KustomizationSpec defines the configuration to calculate the desired state
@@ -101,9 +102,9 @@ type KustomizationSpec struct {
101102

102103
// DeletionPolicy can be used to control garbage collection when this
103104
// Kustomization is deleted. Valid values are ('MirrorPrune', 'Delete',
104-
// 'Orphan'). 'MirrorPrune' mirrors the Prune field (orphan if false,
105-
// delete if true). Defaults to 'MirrorPrune'.
106-
// +kubebuilder:validation:Enum=MirrorPrune;Delete;Orphan
105+
// 'WaitForTermination', 'Orphan'). 'MirrorPrune' mirrors the Prune field
106+
// (orphan if false, delete if true). Defaults to 'MirrorPrune'.
107+
// +kubebuilder:validation:Enum=MirrorPrune;Delete;WaitForTermination;Orphan
107108
// +optional
108109
DeletionPolicy string `json:"deletionPolicy,omitempty"`
109110

config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,12 @@ spec:
113113
description: |-
114114
DeletionPolicy can be used to control garbage collection when this
115115
Kustomization is deleted. Valid values are ('MirrorPrune', 'Delete',
116-
'Orphan'). 'MirrorPrune' mirrors the Prune field (orphan if false,
117-
delete if true). Defaults to 'MirrorPrune'.
116+
'WaitForTermination', 'Orphan'). 'MirrorPrune' mirrors the Prune field
117+
(orphan if false, delete if true). Defaults to 'MirrorPrune'.
118118
enum:
119119
- MirrorPrune
120120
- Delete
121+
- WaitForTermination
121122
- Orphan
122123
type: string
123124
dependsOn:

docs/api/v1/kustomize.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,8 @@ string
217217
<em>(Optional)</em>
218218
<p>DeletionPolicy can be used to control garbage collection when this
219219
Kustomization is deleted. Valid values are (&lsquo;MirrorPrune&rsquo;, &lsquo;Delete&rsquo;,
220-
&lsquo;Orphan&rsquo;). &lsquo;MirrorPrune&rsquo; mirrors the Prune field (orphan if false,
221-
delete if true). Defaults to &lsquo;MirrorPrune&rsquo;.</p>
220+
&lsquo;WaitForTermination&rsquo;, &lsquo;Orphan&rsquo;). &lsquo;MirrorPrune&rsquo; mirrors the Prune field
221+
(orphan if false, delete if true). Defaults to &lsquo;MirrorPrune&rsquo;.</p>
222222
</td>
223223
</tr>
224224
<tr>
@@ -775,8 +775,8 @@ string
775775
<em>(Optional)</em>
776776
<p>DeletionPolicy can be used to control garbage collection when this
777777
Kustomization is deleted. Valid values are (&lsquo;MirrorPrune&rsquo;, &lsquo;Delete&rsquo;,
778-
&lsquo;Orphan&rsquo;). &lsquo;MirrorPrune&rsquo; mirrors the Prune field (orphan if false,
779-
delete if true). Defaults to &lsquo;MirrorPrune&rsquo;.</p>
778+
&lsquo;WaitForTermination&rsquo;, &lsquo;Orphan&rsquo;). &lsquo;MirrorPrune&rsquo; mirrors the Prune field
779+
(orphan if false, delete if true). Defaults to &lsquo;MirrorPrune&rsquo;.</p>
780780
</td>
781781
</tr>
782782
<tr>

docs/spec/v1/kustomizations.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,16 @@ Valid values:
181181
`true` and orphaned if `false`.
182182
- `Delete` - Ensure the managed resources are deleted before the Kustomization
183183
is deleted.
184+
- `WaitForTermination` - Ensure the managed resources are deleted and wait for
185+
termination before the Kustomization is deleted.
184186
- `Orphan` - Leave the managed resources when the Kustomization is deleted.
185187

188+
The `WaitForTermination` deletion policy blocks and waits for the managed
189+
resources to be removed from etcd by the Kubernetes garbage collector.
190+
The wait time is determined by the `.spec.timeout` field. If a timeout occurs,
191+
the controller will stop waiting for the deletion of the resources,
192+
log an error and will allow the Kustomization to be deleted.
193+
186194
For special cases when the managed resources are removed by other means (e.g.
187195
the deletion of the namespace specified with
188196
[`.spec.targetNamespace`](#target-namespace)), you can set the deletion policy

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ require (
2929
github.com/fluxcd/pkg/http/fetch v0.16.0
3030
github.com/fluxcd/pkg/kustomize v1.17.0
3131
github.com/fluxcd/pkg/runtime v0.59.0
32-
github.com/fluxcd/pkg/ssa v0.46.0
32+
github.com/fluxcd/pkg/ssa v0.47.0
3333
github.com/fluxcd/pkg/tar v0.12.0
3434
github.com/fluxcd/pkg/testserver v0.11.0
3535
github.com/fluxcd/source-controller/api v1.5.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,8 @@ github.com/fluxcd/pkg/runtime v0.59.0 h1:3OrFkMJB39NcQ2vhhoxqls59sQVSn8U+thhyLbs
202202
github.com/fluxcd/pkg/runtime v0.59.0/go.mod h1:MFbfyNyyoYRgPxpdwC9/dCOkzo7Yxhu/cQ9NKyhvqc0=
203203
github.com/fluxcd/pkg/sourceignore v0.12.0 h1:jCIe6d50rQ3wdXPF0+PhhqN0XrTRIq3upMomPelI8Mw=
204204
github.com/fluxcd/pkg/sourceignore v0.12.0/go.mod h1:dc0zvkuXM5OgL/b3IkrVuwvPjj1zJn4NBUMH45uJ4Y0=
205-
github.com/fluxcd/pkg/ssa v0.46.0 h1:TGomtbA6zTfZrHF0TDn3mIGKH+bbX45zdWSkdYrwS8g=
206-
github.com/fluxcd/pkg/ssa v0.46.0/go.mod h1:qCek0b8tKumh9iNZLmga1mjeXOlZPlZpc6xip/hLMJM=
205+
github.com/fluxcd/pkg/ssa v0.47.0 h1:J6lt6g21HjpfF89xbwcMZ9s1ZgguvNsHrNyc0onjx8g=
206+
github.com/fluxcd/pkg/ssa v0.47.0/go.mod h1:qCek0b8tKumh9iNZLmga1mjeXOlZPlZpc6xip/hLMJM=
207207
github.com/fluxcd/pkg/tar v0.12.0 h1:og6F+ivnWNRbNJSq0ukCTVs7YrGIlzjxSVZU+E8NprM=
208208
github.com/fluxcd/pkg/tar v0.12.0/go.mod h1:Ra5Cj++MD5iCy7bZGKJJX3GpOeMPv+ZDkPO9bBwpDeU=
209209
github.com/fluxcd/pkg/testserver v0.11.0 h1:a/kxpFqv7XQxZjwVPP3voooRmSd/3ipLVolK0xUIxXQ=

internal/controller/kustomization_controller.go

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,20 +1032,40 @@ func (r *KustomizationReconciler) prune(ctx context.Context,
10321032
return false, nil
10331033
}
10341034

1035+
// finalizerShouldDeleteResources determines if resources should be deleted
1036+
// based on the object's inventory and deletion policy.
1037+
// A suspended Kustomization or one without an inventory will not delete resources.
10351038
func finalizerShouldDeleteResources(obj *kustomizev1.Kustomization) bool {
1036-
if obj.GetDeletionPolicy() == kustomizev1.DeletionPolicyMirrorPrune {
1039+
if obj.Spec.Suspend {
1040+
return false
1041+
}
1042+
1043+
if obj.Status.Inventory == nil || len(obj.Status.Inventory.Entries) == 0 {
1044+
return false
1045+
}
1046+
1047+
switch obj.GetDeletionPolicy() {
1048+
case kustomizev1.DeletionPolicyMirrorPrune:
10371049
return obj.Spec.Prune
1050+
case kustomizev1.DeletionPolicyDelete:
1051+
return true
1052+
case kustomizev1.DeletionPolicyWaitForTermination:
1053+
return true
1054+
default:
1055+
return false
10381056
}
1039-
return obj.Spec.DeletionPolicy == kustomizev1.DeletionPolicyDelete
10401057
}
10411058

1059+
// finalize handles the finalization logic for a Kustomization resource during its deletion process.
1060+
// Managed resources are pruned based on the deletion policy and suspended state of the Kustomization.
1061+
// When the policy is set to WaitForTermination, the function blocks and waits for the resources
1062+
// to be terminated by the Kubernetes Garbage Collector for the specified timeout duration.
1063+
// If the service account used for impersonation is no longer available or if a timeout occurs
1064+
// while waiting for resources to be terminated, an error is logged and the finalizer is removed.
10421065
func (r *KustomizationReconciler) finalize(ctx context.Context,
10431066
obj *kustomizev1.Kustomization) (ctrl.Result, error) {
10441067
log := ctrl.LoggerFrom(ctx)
1045-
if finalizerShouldDeleteResources(obj) &&
1046-
!obj.Spec.Suspend &&
1047-
obj.Status.Inventory != nil &&
1048-
obj.Status.Inventory.Entries != nil {
1068+
if finalizerShouldDeleteResources(obj) {
10491069
objects, _ := inventory.List(obj.Status.Inventory)
10501070

10511071
var impersonatorOpts []runtimeClient.ImpersonatorOption
@@ -1098,7 +1118,21 @@ func (r *KustomizationReconciler) finalize(ctx context.Context,
10981118
}
10991119

11001120
if changeSet != nil && len(changeSet.Entries) > 0 {
1121+
// Emit event with the resources marked for deletion.
11011122
r.event(obj, obj.Status.LastAppliedRevision, obj.Status.LastAppliedOriginRevision, eventv1.EventSeverityInfo, changeSet.String(), nil)
1123+
1124+
// Wait for the resources marked for deletion to be terminated.
1125+
if obj.GetDeletionPolicy() == kustomizev1.DeletionPolicyWaitForTermination {
1126+
if err := resourceManager.WaitForSetTermination(changeSet, ssa.WaitOptions{
1127+
Interval: 2 * time.Second,
1128+
Timeout: obj.GetTimeout(),
1129+
}); err != nil {
1130+
// Emit an event and log the error if a timeout occurs.
1131+
msg := "failed to wait for resources termination"
1132+
log.Error(err, msg)
1133+
r.event(obj, obj.Status.LastAppliedRevision, obj.Status.LastAppliedOriginRevision, eventv1.EventSeverityError, msg, nil)
1134+
}
1135+
}
11021136
}
11031137
} else {
11041138
// when the account to impersonate is gone, log the stale objects and continue with the finalization

internal/controller/kustomization_deletion_policy_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ func TestKustomizationReconciler_DeletionPolicyDelete(t *testing.T) {
4848
deletionPolicy: kustomizev1.DeletionPolicyDelete,
4949
wantDelete: true,
5050
},
51+
{
52+
name: "should delete and wait when deletionPolicy overrides pruning disabled",
53+
prune: false,
54+
deletionPolicy: kustomizev1.DeletionPolicyWaitForTermination,
55+
wantDelete: true,
56+
},
5157
{
5258
name: "should delete when deletionPolicy mirrors prune and pruning enabled",
5359
prune: true,
@@ -131,6 +137,7 @@ data:
131137
TargetNamespace: id,
132138
Prune: tt.prune,
133139
DeletionPolicy: tt.deletionPolicy,
140+
Timeout: &metav1.Duration{Duration: 5 * time.Second},
134141
},
135142
}
136143

0 commit comments

Comments
 (0)