Skip to content

Commit 09e5225

Browse files
authored
feat: application resource deletion protection (#630)
Signed-off-by: Alexander Matyushentsev <[email protected]>
1 parent 72bcdda commit 09e5225

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

pkg/sync/common/types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const (
1616
AnnotationKeyHook = "argocd.argoproj.io/hook"
1717
// AnnotationKeyHookDeletePolicy is the policy of deleting a hook
1818
AnnotationKeyHookDeletePolicy = "argocd.argoproj.io/hook-delete-policy"
19+
AnnotationDeletionApproved = "argocd.argoproj.io/deletion-approved"
1920

2021
// Sync option that disables dry run in resource is missing in the cluster
2122
SyncOptionSkipDryRunOnMissingResource = "SkipDryRunOnMissingResource=true"
@@ -35,6 +36,10 @@ const (
3536
SyncOptionDisableDeletion = "Delete=false"
3637
// Sync option that sync only out of sync resources
3738
SyncOptionApplyOutOfSyncOnly = "ApplyOutOfSyncOnly=true"
39+
// Sync option that requires confirmation before deleting the resource
40+
SyncOptionDeleteRequireConfirm = "Delete=confirm"
41+
// Sync option that requires confirmation before deleting the resource
42+
SyncOptionPruneRequireConfirm = "Prune=confirm"
3843
)
3944

4045
type PermissionValidator func(un *unstructured.Unstructured, res *metav1.APIResource) error

pkg/sync/sync_context.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,13 @@ func WithPrune(prune bool) SyncOpt {
116116
}
117117
}
118118

119+
// WithPruneConfirmed specifies if prune is confirmed for resources that require confirmation
120+
func WithPruneConfirmed(confirmed bool) SyncOpt {
121+
return func(ctx *syncContext) {
122+
ctx.pruneConfirmed = confirmed
123+
}
124+
}
125+
119126
// WithOperationSettings allows to set sync operation settings
120127
func WithOperationSettings(dryRun bool, prune bool, force bool, skipHooks bool) SyncOpt {
121128
return func(ctx *syncContext) {
@@ -339,6 +346,7 @@ type syncContext struct {
339346
serverSideApplyManager string
340347
pruneLast bool
341348
prunePropagationPolicy *metav1.DeletionPropagation
349+
pruneConfirmed bool
342350

343351
syncRes map[string]common.ResourceSyncResult
344352
startedAt time.Time
@@ -1149,6 +1157,24 @@ func (sc *syncContext) runTasks(tasks syncTasks, dryRun bool) runState {
11491157
}
11501158
// prune first
11511159
{
1160+
if !sc.pruneConfirmed {
1161+
var resources []string
1162+
for _, task := range pruneTasks {
1163+
if resourceutil.HasAnnotationOption(task.liveObj, common.AnnotationSyncOptions, common.SyncOptionPruneRequireConfirm) {
1164+
resources = append(resources, fmt.Sprintf("%s/%s/%s", task.obj().GetAPIVersion(), task.obj().GetKind(), task.name()))
1165+
}
1166+
}
1167+
if len(resources) > 0 {
1168+
sc.log.WithValues("resources", resources).Info("Prune requires confirmation")
1169+
andMessage := ""
1170+
if len(resources) > 1 {
1171+
andMessage = fmt.Sprintf(" and %d more resources", len(resources)-1)
1172+
}
1173+
sc.message = fmt.Sprintf("Waiting for pruning confirmation of %s%s", resources[0], andMessage)
1174+
return pending
1175+
}
1176+
}
1177+
11521178
ss := newStateSync(state)
11531179
for _, task := range pruneTasks {
11541180
t := task

0 commit comments

Comments
 (0)