Conversation
📝 WalkthroughWalkthroughThree new Kubernetes controllers are introduced: Changes
Sequence Diagram(s)sequenceDiagram
participant Reconciler as APIKeyStatusReconciler
participant Client as Kubernetes API
participant Context as Context Storage
Reconciler->>Client: List all APIKeys
Reconciler->>Context: Store APIKey list
Reconciler->>Client: List all APIKeyRequests
Reconciler->>Context: Store APIKeyRequest list
Reconciler->>Client: List all APIKeyApprovals
Reconciler->>Context: Store APIKeyApproval list
Reconciler->>Client: List all APIProducts
Reconciler->>Client: List all HTTPRoutes
loop For each active APIKey
Reconciler->>Client: Get referenced APIProduct
Reconciler->>Client: Get referenced Secret
Reconciler->>Client: Get referenced HTTPRoute
alt APIProduct missing or deleting
Reconciler->>Reconciler: Set Failed condition
else Secret missing or invalid
Reconciler->>Reconciler: Set Failed condition
else APIKeyApproval valid
Reconciler->>Reconciler: Set Approved condition
else APIKeyApproval rejected
Reconciler->>Reconciler: Set Denied condition
end
Reconciler->>Reconciler: Extract AuthScheme from APIProduct
Reconciler->>Reconciler: Extract Limits from APIProduct plans
Reconciler->>Reconciler: Extract APIHostname from HTTPRoute
Reconciler->>Client: Update APIKey status (if changed)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| APIKeyRequest -->|"spec.apiProductRef<br/>(local)"| APIProduct | ||
| APIKeyApproval -->|"spec.apiKeyRequestRef<br/>(local)"| APIKeyRequest |
There was a problem hiding this comment.
Maybe we could simplify the dance between APIKeyRequest and APIKeyApproval within the same object, maybe APIKeyRequest or a new name like APIKeyManagement
82afe95 to
4e541db
Compare
d3f8420 to
dcee43e
Compare
4e541db to
2881bcd
Compare
dcee43e to
f8701e7
Compare
2881bcd to
9f85ac1
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (11)
internal/controller/devportal_helper.go (1)
10-16: Nit: key type naming inconsistency.
apiKeyRequestCtxKey(singular) uses typeapiKeyRequestsCtxKeyType(plural), while the other two key constants match their type names (apiKeysCtxKey/apiKeysCtxKeyType,apiKeyApprovalsCtxKey/apiKeyApprovalsCtxKeyType). Rename toapiKeyRequestsCtxKeyfor consistency.-const apiKeyRequestCtxKey apiKeyRequestsCtxKeyType = "apikeyrequests" +const apiKeyRequestsCtxKey apiKeyRequestsCtxKeyType = "apikeyrequests"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/controller/devportal_helper.go` around lines 10 - 16, The constant name apiKeyRequestCtxKey is inconsistent with its type apiKeyRequestsCtxKeyType; rename the constant to apiKeyRequestsCtxKey and update all usages to match so the pattern aligns with apiKeysCtxKey/apiKeysCtxKeyType and apiKeyApprovalsCtxKey/apiKeyApprovalsCtxKeyType; ensure you update references in functions or middleware that read/write context keys (look for apiKeyRequestCtxKey occurrences) to the new apiKeyRequestsCtxKey identifier.README.md (1)
400-444: LGTM — the Entity Relationship Model section and Mermaid diagram usefully summarise namespace boundaries and the shadow-resource pattern, and are consistent with the per-resource descriptions above (cross-namespaceAPIKey → APIProductandAPIKeyRequest → APIKey, localAPIKeyRequest → APIProductandAPIKeyApproval → APIKeyRequest, controller-createdAPIKey ⇢ APIKeyRequest).Tiny nit: the "Cross-Namespace References (solid arrows)" / "Local References (solid arrows)" bullets both say "solid arrows"; consider distinguishing them visually in the diagram (e.g., different stroke styles) or rewording the legend, since as written both solid-arrow categories look identical to a reader.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@README.md` around lines 400 - 444, The legend currently labels both cross-namespace and local references as "solid arrows", which is ambiguous; update the Mermaid diagram legend or the diagram itself so they are distinguishable: either reword the bullets to "Cross-Namespace References (solid arrows)" and "Local References (solid arrows — same-namespace)" or change the local-reference arrow style in the diagram (the edges APIKey --> APIProduct and APIKeyRequest --> APIProduct for cross-namespace vs APIKeyRequest --> APIProduct and APIKeyApproval --> APIKeyRequest for local) to a visually different stroke (e.g., use a different arrow style or class) and reflect that change in the legend so readers can clearly tell cross-namespace vs local links.internal/controller/apikey_status_controller.go (4)
493-497: Nit: redundantstring(...)conversion on a string literal.
"apikey-status"is already astring, so the explicit conversion is unnecessary.📝 Proposed fix
- return []ctrl.Request{{NamespacedName: types.NamespacedName{ - Name: string("apikey-status"), - }}} + return []ctrl.Request{{NamespacedName: types.NamespacedName{ + Name: "apikey-status", + }}}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/controller/apikey_status_controller.go` around lines 493 - 497, In enqueueClass, remove the redundant string conversion around the literal by changing Name: string("apikey-status") to simply Name: "apikey-status" inside the APIKeyStatusReconciler.enqueueClass function so the NamespacedName.Name is assigned the literal directly.
120-124: Nit: log message mentionsapiproductinstead ofapikey.Also a copy-paste artefact — misleading when grepping logs.
📝 Proposed fix
- logger.V(1).Info("apiproduct status unchanged, skipping update") + logger.V(1).Info("apikey status unchanged, skipping update")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/controller/apikey_status_controller.go` around lines 120 - 124, The log message in the status-check branch uses a copy-pasted string "apiproduct status unchanged, skipping update" which is misleading; update the logger call in the block that computes equalStatus (using equality.Semantic.DeepEqual(newStatus, apiKey.Status) and compares apiKey.Generation to apiKey.Status.ObservedGeneration) to reference "apikey" instead of "apiproduct" (e.g., logger.V(1).Info with a corrected message) so logs accurately reflect the checked resource.
45-49: Nit: stale doc comment referencesAPIProductReconciler.The struct is
APIKeyStatusReconciler, so the preceding comment is a copy-paste leftover fromapiproduct_controller.go.📝 Proposed fix
-// APIProductReconciler reconciles a APIProduct object +// APIKeyStatusReconciler reconciles APIKey status based on referenced APIProduct, Secret, and gateway resources type APIKeyStatusReconciler struct {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/controller/apikey_status_controller.go` around lines 45 - 49, The top-of-file doc comment is stale: change the comment that currently reads "APIProductReconciler reconciles a APIProduct object" to correctly describe the APIKeyStatusReconciler (e.g., "APIKeyStatusReconciler reconciles an APIKeyStatus object") or remove it; update the comment immediately preceding the APIKeyStatusReconciler struct declaration so it matches the struct name APIKeyStatusReconciler and its purpose.
478-480: Orphan comment left over outside any function.This trailing comment appears to be a leftover; it isn't attached to a declaration and just adds noise.
🧹 Proposed fix
-// Clear all status condition types (Approved, Denied, Failed) - // SetupWithManager sets up the controller with the Manager.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/controller/apikey_status_controller.go` around lines 478 - 480, Remove the orphan trailing comment "Clear all status condition types (Approved, Denied, Failed)" from the file (it sits outside any function) or, if the intent was to document behavior, move that text immediately above the function that actually clears status conditions (search for the method that handles status condition clearing or any function named with "status", "condition", "Clear", or "Approve/Denie/Fail" in apikey_status_controller.go) so it becomes a proper doc comment for that function.api/v1alpha1/apikey_types.go (1)
39-42: Minor: namespace fallback inAPIProductKey()is unreachable given the current schema.
APIProductReference.Namespacehas noomitempty/+optionalmarker, so it is required by the CRD and will always be populated when decoded from the API server. Theif a.Spec.APIProductRef.Namespace != ""fallback toa.Namespaceis therefore dead. Either markNamespaceas optional withomitempty(if cross-namespace-by-default-to-APIKey is the intended UX) or drop the fallback to keep intent explicit.Also applies to: 129-142
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api/v1alpha1/apikey_types.go` around lines 39 - 42, The fallback path in APIProductKey() that checks APIProductRef.Namespace is unreachable because APIProductReference.Namespace is required by the CRD (no `omitempty`/`+optional`), so it will always be populated; either make Namespace optional on the struct (add `omitempty`/`+optional` to APIProductReference.Namespace) if you want empty to mean "use a.Spec.Namespace", or remove the dead fallback logic in the APIProductKey() method to keep behavior explicit. Locate APIProductReference.Namespace and APIProductKey() (and the similar code block at the other occurrence around the 129-142 region) and apply the same change consistently.internal/controller/apikeyapproval_controller_test.go (1)
59-59: Nit:ctx := context.Background()is shared across all specs.This is captured once at container-construction time rather than per-spec. It works because
context.Background()is effectively immutable, but it means the test cannot be cancelled or time-bounded viaSpecContext. Consider using theSpecContextalready passed toBeforeEach/AfterEach/It(as you do at lines 43, 48, 108) for the innerk8sClientcalls so that per-spec timeouts propagate correctly.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/controller/apikeyapproval_controller_test.go` at line 59, The test creates a package-level/static context with `ctx := context.Background()` which prevents per-spec cancellation and timeouts; remove that global Background context and instead use the SpecContext provided to each spec (the `ctx` parameter passed into BeforeEach/AfterEach/It) when calling k8sClient methods and constructing resources (e.g., replace uses of the global `ctx` in k8sClient.Create/Delete/Update calls and any container/resource construction with the per-spec `ctx` variable passed into those hooks).internal/controller/apikeyapproval_controller.go (1)
112-124: Minor: UID-only check may miss theController: trueflag; considermetav1.IsControlledBy.The loop accepts any existing
OwnerReferencewith the matching UID, including non-controller refs. In practiceSetControllerReferencealso rejects a second controller, so the current code is effectively correct, but using the built-in helper makes intent explicit and keeps you aligned with controller-runtime conventions.🧹 Proposed tidy-up
- // Check if owner reference is already set - for _, ownerRef := range approval.OwnerReferences { - if ownerRef.UID == foundRequest.UID { - // Owner reference already set - return nil - } - } + // Already the controller of this approval? Nothing to do. + if metav1.IsControlledBy(approval, foundRequest) { + return nil + }This requires importing
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/controller/apikeyapproval_controller.go` around lines 112 - 124, The current loop over approval.OwnerReferences only compares UID (approval.OwnerReferences and foundRequest.UID) and can treat non-controller ownerRefs as controllers; replace that manual UID check with the helper metav1.IsControlledBy(approval, foundRequest) to explicitly test controller ownership before returning, and ensure you import metav1 ("k8s.io/apimachinery/pkg/apis/meta/v1"); keep the subsequent controllerutil.SetControllerReference(foundRequest, approval, r.Scheme) logic unchanged so SetControllerReference still runs when no controller owner is present.internal/controller/apikeyapproval_status_controller.go (2)
198-202: Nit: redundantstring(...)conversion of a string literal.
string("apikeyapproval-status")is a no-op. The same pattern appears ininternal/controller/apikeyapproval_controller.goline 147.🧹 Proposed tidy-up
func (r *APIKeyApprovalStatusReconciler) enqueueClass(_ context.Context, _ client.Object) []ctrl.Request { return []ctrl.Request{{NamespacedName: types.NamespacedName{ - Name: string("apikeyapproval-status"), + Name: "apikeyapproval-status", }}} }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/controller/apikeyapproval_status_controller.go` around lines 198 - 202, The Name field is using a redundant string(...) conversion in enqueueClass; change Name: string("apikeyapproval-status") to Name: "apikeyapproval-status" (remove the unnecessary string() cast) and apply the same tidy-up to the identical pattern found in the related enqueueClass implementation in the APIKeyApproval reconciler to remove the no-op conversions.
77-87: Single failing approval aborts the rest of the batch.Any non-conflict error from
reconcileStatusreturns immediately, so remaining approvals in the list are not reconciled in this pass. Controller-runtime will requeue on error, but if one approval consistently fails the others effectively stall. Consider aggregating errors (e.g. viaerrors.Join/kerrors.NewAggregate) and continuing the loop.🛠️ Suggested pattern
+ var errs []error for idx := range activeAPIKeyApprovalList { - err := r.reconcileStatus(ctx, &activeAPIKeyApprovalList[idx]) - if err != nil { + if err := r.reconcileStatus(ctx, &activeAPIKeyApprovalList[idx]); err != nil { if apierrors.IsConflict(err) { - // Ignore conflicts, resource might just be outdated. - logger.Info("failed to update status: resource might just be outdated") + logger.Info("failed to update status: resource might just be outdated", + "apikeyapproval", client.ObjectKeyFromObject(&activeAPIKeyApprovalList[idx])) return ctrl.Result{Requeue: true}, nil } - return ctrl.Result{}, err + errs = append(errs, err) } } - return ctrl.Result{}, nil + return ctrl.Result{}, errors.Join(errs...)(Also note the existing log line omits the offending approval’s key, unlike the sibling controller on line 78 of
apikeyapproval_controller.go.)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/controller/apikeyapproval_status_controller.go` around lines 77 - 87, The loop over activeAPIKeyApprovalList should not return on the first non-conflict error; instead, continue processing remaining approvals while aggregating errors: call reconcileStatus(ctx, &activeAPIKeyApprovalList[idx]) for each item, log failures including the approval key (use the same key format as apikeyapproval_controller.go), skip apierrors.IsConflict by requeueing that case, and collect other errors into a single aggregate (using errors.Join or kerrors.NewAggregate) to return after the loop so other approvals are reconciled in this pass; update the logger call to include the offending approval's key and any error details.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@internal/controller/apikey_status_controller.go`:
- Line 219: Replace direct uses of the embedded client selector (r.Client.Get)
with the short form (r.Get) to satisfy staticcheck QF1008; specifically update
the calls inside APIKeyStatusReconciler where r.Client.Get(...) appears (e.g.,
the call at the location that currently calls err := r.Client.Get(ctx,
apiProductKey, apiProduct) and the similar call around line 258) to use
r.Get(ctx, apiProductKey, apiProduct) instead so the reconciler uses the
embedded client directly (consistent with other methods like getAPIProduct and
apiHostName).
In `@internal/controller/apikeyapproval_status_controller_test.go`:
- Around line 218-261: The test never exercises the controller's
activeAPIKeyApprovalList deletion-timestamp filter because the created
APIKeyApproval has no finalizer and is immediately removed by k8sClient.Delete;
update the test to add a finalizer to the approval object (the local variable
approval) before calling k8sClient.Delete so the object stays in the API server
with a deletionTimestamp and triggers the controller path in
APIKeyApprovalStatusReconciler that uses activeAPIKeyApprovalList; after the
test remove the finalizer (teardown) so cleanup succeeds, and adjust the
Consistently closure to not treat a NotFound as a successful short-circuit
(i.e., only return true when the resource exists and has zero conditions) so the
assertion actually verifies the skipped update behavior.
In `@internal/controller/apikeyapproval_status_controller.go`:
- Around line 122-135: The existing code removes the current Valid condition
(baseConditions) before calling meta.SetStatusCondition, causing
LastTransitionTime to be reset on every reconcile; instead preserve all existing
conditions by cloning approval.Status.Conditions into newStatus.Conditions (use
slices.Clone(approval.Status.Conditions)), then compute validCondition via
calculateValidCondition(ctx, approval) and call
meta.SetStatusCondition(&newStatus.Conditions, *validCondition) as needed so
SetStatusCondition can detect real transitions; drop the lo-based filtering and
remove the lo import if unused.
- Around line 45-46: The RBAC marker for the status subresource only grants
"patch" but the controller calls r.Client.Status().Update(ctx, approval), which
requires the "update" verb; either add "update" to the kubebuilder RBAC marker
for apikeyapprovals/status (extend the verbs to "patch;update" or
"update;patch") or change the controller call to use
r.Client.Status().Patch(...) instead of Status().Update(...); locate the marker
lines with "+kubebuilder:rbac:...resources=apikeyapprovals/status,verbs=patch"
and the status write call r.Client.Status().Update(ctx, approval) to make the
corresponding change.
- Around line 100-104: The equality check is comparing a pointer to a value so
it always returns false; change the guard to compare the concrete values by
dereferencing newStatus (use equality.Semantic.DeepEqual(*newStatus,
approval.Status)) and then you can remove the redundant Generation check (or
keep it optional) so the "apikeyapproval status unchanged, skipping update"
branch can fire correctly; update the block around newStatus, approval.Status
and the logger.V(1).Info call accordingly.
In `@internal/controller/devportal_helper.go`:
- Around line 22-52: The Get* helpers currently return newly allocated empty
lists which prevents caller nil-checks from detecting missing context wiring;
change GetAPIKeys, GetAPIKeyRequests, and GetAPIKeyApprovals to return nil when
the context lookup or type assertion fails (i.e., if
ctx.Value(apiKeysCtxKey)/apiKeyRequestCtxKey/apiKeyApprovalsCtxKey is missing or
not the expected type) so existing callers that do "if x == nil { return
fmt.Errorf(... not found in context) }" behave correctly; no caller changes
required.
---
Nitpick comments:
In `@api/v1alpha1/apikey_types.go`:
- Around line 39-42: The fallback path in APIProductKey() that checks
APIProductRef.Namespace is unreachable because APIProductReference.Namespace is
required by the CRD (no `omitempty`/`+optional`), so it will always be
populated; either make Namespace optional on the struct (add
`omitempty`/`+optional` to APIProductReference.Namespace) if you want empty to
mean "use a.Spec.Namespace", or remove the dead fallback logic in the
APIProductKey() method to keep behavior explicit. Locate
APIProductReference.Namespace and APIProductKey() (and the similar code block at
the other occurrence around the 129-142 region) and apply the same change
consistently.
In `@internal/controller/apikey_status_controller.go`:
- Around line 493-497: In enqueueClass, remove the redundant string conversion
around the literal by changing Name: string("apikey-status") to simply Name:
"apikey-status" inside the APIKeyStatusReconciler.enqueueClass function so the
NamespacedName.Name is assigned the literal directly.
- Around line 120-124: The log message in the status-check branch uses a
copy-pasted string "apiproduct status unchanged, skipping update" which is
misleading; update the logger call in the block that computes equalStatus (using
equality.Semantic.DeepEqual(newStatus, apiKey.Status) and compares
apiKey.Generation to apiKey.Status.ObservedGeneration) to reference "apikey"
instead of "apiproduct" (e.g., logger.V(1).Info with a corrected message) so
logs accurately reflect the checked resource.
- Around line 45-49: The top-of-file doc comment is stale: change the comment
that currently reads "APIProductReconciler reconciles a APIProduct object" to
correctly describe the APIKeyStatusReconciler (e.g., "APIKeyStatusReconciler
reconciles an APIKeyStatus object") or remove it; update the comment immediately
preceding the APIKeyStatusReconciler struct declaration so it matches the struct
name APIKeyStatusReconciler and its purpose.
- Around line 478-480: Remove the orphan trailing comment "Clear all status
condition types (Approved, Denied, Failed)" from the file (it sits outside any
function) or, if the intent was to document behavior, move that text immediately
above the function that actually clears status conditions (search for the method
that handles status condition clearing or any function named with "status",
"condition", "Clear", or "Approve/Denie/Fail" in apikey_status_controller.go) so
it becomes a proper doc comment for that function.
In `@internal/controller/apikeyapproval_controller_test.go`:
- Line 59: The test creates a package-level/static context with `ctx :=
context.Background()` which prevents per-spec cancellation and timeouts; remove
that global Background context and instead use the SpecContext provided to each
spec (the `ctx` parameter passed into BeforeEach/AfterEach/It) when calling
k8sClient methods and constructing resources (e.g., replace uses of the global
`ctx` in k8sClient.Create/Delete/Update calls and any container/resource
construction with the per-spec `ctx` variable passed into those hooks).
In `@internal/controller/apikeyapproval_controller.go`:
- Around line 112-124: The current loop over approval.OwnerReferences only
compares UID (approval.OwnerReferences and foundRequest.UID) and can treat
non-controller ownerRefs as controllers; replace that manual UID check with the
helper metav1.IsControlledBy(approval, foundRequest) to explicitly test
controller ownership before returning, and ensure you import metav1
("k8s.io/apimachinery/pkg/apis/meta/v1"); keep the subsequent
controllerutil.SetControllerReference(foundRequest, approval, r.Scheme) logic
unchanged so SetControllerReference still runs when no controller owner is
present.
In `@internal/controller/apikeyapproval_status_controller.go`:
- Around line 198-202: The Name field is using a redundant string(...)
conversion in enqueueClass; change Name: string("apikeyapproval-status") to
Name: "apikeyapproval-status" (remove the unnecessary string() cast) and apply
the same tidy-up to the identical pattern found in the related enqueueClass
implementation in the APIKeyApproval reconciler to remove the no-op conversions.
- Around line 77-87: The loop over activeAPIKeyApprovalList should not return on
the first non-conflict error; instead, continue processing remaining approvals
while aggregating errors: call reconcileStatus(ctx,
&activeAPIKeyApprovalList[idx]) for each item, log failures including the
approval key (use the same key format as apikeyapproval_controller.go), skip
apierrors.IsConflict by requeueing that case, and collect other errors into a
single aggregate (using errors.Join or kerrors.NewAggregate) to return after the
loop so other approvals are reconciled in this pass; update the logger call to
include the offending approval's key and any error details.
In `@internal/controller/devportal_helper.go`:
- Around line 10-16: The constant name apiKeyRequestCtxKey is inconsistent with
its type apiKeyRequestsCtxKeyType; rename the constant to apiKeyRequestsCtxKey
and update all usages to match so the pattern aligns with
apiKeysCtxKey/apiKeysCtxKeyType and
apiKeyApprovalsCtxKey/apiKeyApprovalsCtxKeyType; ensure you update references in
functions or middleware that read/write context keys (look for
apiKeyRequestCtxKey occurrences) to the new apiKeyRequestsCtxKey identifier.
In `@README.md`:
- Around line 400-444: The legend currently labels both cross-namespace and
local references as "solid arrows", which is ambiguous; update the Mermaid
diagram legend or the diagram itself so they are distinguishable: either reword
the bullets to "Cross-Namespace References (solid arrows)" and "Local References
(solid arrows — same-namespace)" or change the local-reference arrow style in
the diagram (the edges APIKey --> APIProduct and APIKeyRequest --> APIProduct
for cross-namespace vs APIKeyRequest --> APIProduct and APIKeyApproval -->
APIKeyRequest for local) to a visually different stroke (e.g., use a different
arrow style or class) and reflect that change in the legend so readers can
clearly tell cross-namespace vs local links.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e6a226ad-c150-437b-a19e-c62f6a5ace20
📒 Files selected for processing (21)
CLAUDE.mdCLAUDE.mdREADME.mdapi/v1alpha1/apikey_types.goapi/v1alpha1/apikeyapproval_types.goapi/v1alpha1/zz_generated.deepcopy.gocmd/main.goconfig/crd/bases/devportal.kuadrant.io_apikeyapprovals.yamlconfig/crd/bases/devportal.kuadrant.io_apikeys.yamlconfig/rbac/role.yamlinternal/controller/apikey_status_controller.gointernal/controller/apikey_status_controller_test.gointernal/controller/apikeyapproval_controller.gointernal/controller/apikeyapproval_controller_test.gointernal/controller/apikeyapproval_status_controller.gointernal/controller/apikeyapproval_status_controller_test.gointernal/controller/apikeyrequest_controller.gointernal/controller/apikeyrequest_controller_test.gointernal/controller/apikeyrequest_status_controller_test.gointernal/controller/devportal_helper.gointernal/controller/suite_test.go
Signed-off-by: Eguzki Astiz Lezaun <eastizle@redhat.com>
Signed-off-by: Eguzki Astiz Lezaun <eastizle@redhat.com>
9f85ac1 to
9776ee3
Compare
Signed-off-by: Eguzki Astiz Lezaun <eastizle@redhat.com>
Signed-off-by: Eguzki Astiz Lezaun <eastizle@redhat.com>
Signed-off-by: Eguzki Astiz Lezaun <eastizle@redhat.com>
Signed-off-by: Eguzki Astiz Lezaun <eastizle@redhat.com>
Dependes on #45
Part of #39
Adds three new reconcilers:
Summary by CodeRabbit
Release Notes
New Features
Documentation