From 7bc80d5d6328b62734cc64a5d63009945dd4fb58 Mon Sep 17 00:00:00 2001 From: Barrett <81570928+btlghrants@users.noreply.github.com> Date: Mon, 28 Oct 2024 07:20:54 -0500 Subject: [PATCH] feat: add ability to exit Finalize() callback WITHOUT removing the finalizer (#1321) ## Description Adds ability for Module Author to "opt out" of removing Pepr's metadata.finalizers entry. End to End Test: [pepr-excellent-examples #172](https://github.com/defenseunicorns/pepr-excellent-examples/pull/172) ## Related Issue Fixes #1316 ## Type of change - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Other (security config, docs update, etc) ## Checklist before merging - [ ] Unit, [Journey](https://github.com/defenseunicorns/pepr/tree/main/journey), [E2E Tests](https://github.com/defenseunicorns/pepr-excellent-examples), [docs](https://github.com/defenseunicorns/pepr/tree/main/docs), [adr](https://github.com/defenseunicorns/pepr/tree/main/adr) added or updated as needed - [ ] [Contributor Guide Steps](https://docs.pepr.dev/main/contribute/#submitting-a-pull-request) followed --------- Co-authored-by: Case Wylie Co-authored-by: schaeferka --- src/lib/capability.ts | 2 +- src/lib/types.ts | 2 +- src/lib/watch-processor.ts | 16 +++++++++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/lib/capability.ts b/src/lib/capability.ts index 1e4e13da8..b26d3e59d 100644 --- a/src/lib/capability.ts +++ b/src/lib/capability.ts @@ -337,7 +337,7 @@ export class Capability implements CapabilityExport { event: Event.Update, finalizeCallback: async (update: InstanceType, logger = aliasLogger) => { Log.info(`Executing finalize action with alias: ${binding.alias || "no alias provided"}`); - await finalizeCallback(update, logger); + return await finalizeCallback(update, logger); }, }; bindings.push(watchBinding); diff --git a/src/lib/types.ts b/src/lib/types.ts index d2625901f..dc21782dc 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -255,7 +255,7 @@ export type ValidateActionResponse = { export type FinalizeAction> = ( update: K, logger?: Logger, -) => Promise | void; +) => Promise | boolean | void; export type FinalizeActionChain = { /** diff --git a/src/lib/watch-processor.ts b/src/lib/watch-processor.ts index c75ced5c1..145f70537 100644 --- a/src/lib/watch-processor.ts +++ b/src/lib/watch-processor.ts @@ -106,12 +106,22 @@ async function runBinding(binding: Binding, capabilityNamespaces: string[], igno if (!obj.metadata?.deletionTimestamp) { return; } + + let shouldRemoveFinalizer: boolean | void | undefined = true; try { - await binding.finalizeCallback?.(obj); + shouldRemoveFinalizer = await binding.finalizeCallback?.(obj); - // irrespective of callback success / failure, remove pepr finalizer + // if not opt'ed out of / if in error state, remove pepr finalizer } finally { - await removeFinalizer(binding, obj); + const peprFinal = "pepr.dev/finalizer"; + const meta = obj.metadata!; + const resource = `${meta.namespace || "ClusterScoped"}/${meta.name}`; + + // [ true, void, undefined ] SHOULD remove finalizer + // [ false ] should NOT remove finalizer + shouldRemoveFinalizer === false + ? Log.debug({ obj }, `Skipping removal of finalizer '${peprFinal}' from '${resource}'`) + : await removeFinalizer(binding, obj); } } else { await binding.watchCallback?.(obj, phase);