Background
#82 adds a Secret watch to APIKeyStatusReconciler (internal/controller/apikey_status_controller.go) so that APIKeys stuck in SecretNotFound recover once their referenced Secret is created. See #78.
The watch is currently unfiltered:
Watches(&corev1.Secret{}, handler.EnqueueRequestsFromMapFunc(r.enqueueClass)).
This reconciler uses a "class reconciler" pattern: every watched event enqueues the same fixed key and triggers a full list-and-reconcile of all APIKeys (Reconcile, internal/controller/apikey_status_controller.go:63). The manager's cache is not namespace-scoped (cmd/main.go), so in practice any Secret create/update/delete anywhere in the cluster now triggers a full reconcile pass of every APIKey.
Proposal
Define a label that marks a Secret as an APIKey's referenced secret (e.g. devportal.kuadrant.io/apikey-secret: "true"), and filter the Secret watch in apikey_status_controller.go with a predicate so it only reacts to Secrets carrying that label.
Scope — when the label is (and isn't) needed
The label is only relevant to the Secret-created-after-APIKey race. If the Secret already exists at the time the APIKey is created (the normal/original ordering), reconciliation is already triggered by the APIKey watch itself — no Secret event, and therefore no label, is needed for that path to succeed. The label-scoped watch exists solely to catch the recovery case from #78/#82: APIKey created first, referencing a Secret that doesn't exist yet, created moments later. Consumers/plugins that always create the Secret before the APIKey never need to set this label for correctness — only those that create the APIKey first (e.g. to set an ownerReference, per kuadrant-console-plugin#541) need it.
Non-goal: keeping the APIKey in sync with later Secret content changes. This watch only reacts to the Secret appearing (create/update events firing the same generic re-reconcile). It does not mean the system keeps API key material in sync if someone edits the Secret's data.api_key after the fact:
APIKeyStatusReconciler only re-checks existence/non-emptiness of the entry, it doesn't project the value anywhere that would need re-syncing.
APIKeySecretReconciler (internal/controller/apikey_secret_controller.go), which copies the consumer Secret's api_key value into the Authorino-enforced secret, does not watch Secrets at all (only APIKey) — so an in-place edit of the consumer's Secret value is never propagated to enforcement, label or no label.
This issue is scoped to detecting Secret creation for the missing-secret recovery case, not to general Secret-content sync. That gap (edits to an existing Secret's value not propagating to enforcement) is a separate, pre-existing issue if it needs addressing.
Tasks
Background
#82 adds a
Secretwatch toAPIKeyStatusReconciler(internal/controller/apikey_status_controller.go) so that APIKeys stuck inSecretNotFoundrecover once their referenced Secret is created. See #78.The watch is currently unfiltered:
This reconciler uses a "class reconciler" pattern: every watched event enqueues the same fixed key and triggers a full list-and-reconcile of all APIKeys (
Reconcile,internal/controller/apikey_status_controller.go:63). The manager's cache is not namespace-scoped (cmd/main.go), so in practice any Secret create/update/delete anywhere in the cluster now triggers a full reconcile pass of every APIKey.Proposal
Define a label that marks a Secret as an APIKey's referenced secret (e.g.
devportal.kuadrant.io/apikey-secret: "true"), and filter the Secret watch inapikey_status_controller.gowith a predicate so it only reacts to Secrets carrying that label.Scope — when the label is (and isn't) needed
The label is only relevant to the Secret-created-after-APIKey race. If the Secret already exists at the time the APIKey is created (the normal/original ordering), reconciliation is already triggered by the APIKey watch itself — no Secret event, and therefore no label, is needed for that path to succeed. The label-scoped watch exists solely to catch the recovery case from #78/#82: APIKey created first, referencing a Secret that doesn't exist yet, created moments later. Consumers/plugins that always create the Secret before the APIKey never need to set this label for correctness — only those that create the APIKey first (e.g. to set an ownerReference, per kuadrant-console-plugin#541) need it.
Non-goal: keeping the APIKey in sync with later Secret content changes. This watch only reacts to the Secret appearing (create/update events firing the same generic re-reconcile). It does not mean the system keeps API key material in sync if someone edits the Secret's
data.api_keyafter the fact:APIKeyStatusReconcileronly re-checks existence/non-emptiness of the entry, it doesn't project the value anywhere that would need re-syncing.APIKeySecretReconciler(internal/controller/apikey_secret_controller.go), which copies the consumer Secret'sapi_keyvalue into the Authorino-enforced secret, does not watch Secrets at all (only APIKey) — so an in-place edit of the consumer's Secret value is never propagated to enforcement, label or no label.This issue is scoped to detecting Secret creation for the missing-secret recovery case, not to general Secret-content sync. That gap (edits to an existing Secret's value not propagating to enforcement) is a separate, pre-existing issue if it needs addressing.
Tasks
apikey_status_controller.goRequestAPIKeyModal.tsx) to set the label — only strictly required for the create-APIKey-before-Secret flow (kuadrant-console-plugin#541)router.tsPOST /secrets) to set the label if/when it adopts the same create-order