Skip to content

Add CatalogAPI #342

Merged
mjudeikis merged 3 commits into
kbind-dev:mainfrom
mjudeikis:mjudeikis/catalog.api
Oct 23, 2025
Merged

Add CatalogAPI #342
mjudeikis merged 3 commits into
kbind-dev:mainfrom
mjudeikis:mjudeikis/catalog.api

Conversation

@mjudeikis

@mjudeikis mjudeikis commented Oct 15, 2025

Copy link
Copy Markdown
Contributor

Summary

This adds machinery for catalog API. Its not used anywhere, just api and some kcp wiring.

What Type of PR Is This?

/kind feature

Related Issue(s)

Fixes #

Release Notes

Add CatalogAPI skeleton

Summary by CodeRabbit

  • New Features

    • Introduced Catalog API with Collections and Modules for better resource organization.
    • Enhanced permission claims supporting named resources and combined selectors.
    • Added provider-side namespace management capabilities.
    • Redesigned UI with module-centric view for improved resource browsing.
  • Documentation

    • Added comprehensive usage guide and migration guide (v0.5 to v0.6).
    • Updated API documentation with v0.6.0 changes.
  • Changes

    • Simplified API service binding workflow.
    • Removed legacy login interface.

@mjudeikis mjudeikis requested a review from a team as a code owner October 15, 2025 09:45
@mjudeikis mjudeikis requested a review from ntnn October 15, 2025 09:45
@coderabbitai

coderabbitai Bot commented Oct 15, 2025

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • ai-code-review

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

This PR introduces a template-based architecture for resource exports, replacing per-resource dynamic discovery with module/collection-centric workflows. Core changes include renaming NamedResource to NamedResources, introducing APIServiceExportTemplate and Collection CRDs, refactoring backend HTTP handlers to use template-derived data, updating UI components to display modules, and adding comprehensive migration documentation.

Changes

Cohort / File(s) Summary
API Type Definitions
sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go, sdk/apis/kubebind/v1alpha2/collection_types.go, sdk/apis/kubebind/v1alpha2/register.go
New public types: APIServiceExportTemplate, APIServiceExportTemplateSpec, APIServiceExportTemplateStatus, Collection, CollectionSpec, CollectionStatus, and their list variants; registered in v1alpha2 scheme.
NamedResource Field Rename
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go, sdk/apis/kubebind/v1alpha2/zz_generated.deepcopy.go, pkg/resources/resources.go, pkg/resources/resources_test.go, pkg/konnector/controllers/cluster/claimedresources/claimedresources_controller.go, test/e2e/bind/happy-case_test.go
Renamed field from NamedResource to NamedResources across Selector usage; updated DeepCopy implementations and controller logic.
CRD Definitions
deploy/crd/kube-bind.io_apiserviceexporttemplates.yaml, deploy/crd/kube-bind.io_collections.yaml, deploy/crd/kube-bind.io_apiservicebindings.yaml, deploy/crd/kube-bind.io_apiserviceexportexports.yaml, deploy/crd/kube-bind.io_apiserviceexportrequests.yaml
New CRDs for APIServiceExportTemplate and Collection; updated existing CRDs to reflect NamedResources rename and added namespaces field to APIServiceExportRequest.
KCP Resource Schemas
contrib/kcp/deploy/resources/apiresourceschema-*.yaml
Updated schema versions and added new APIResourceSchema entries for apiserviceexporttemplates and collections; renamed namedResource to namedResources.
KCP APIExport
contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml
Updated apiservicebindings and apiserviceexports schema references; added new apiserviceexporttemplates and collections entries.
KCP Deploy Examples
contrib/kcp/deploy/examples/collection-wildwest.yaml, contrib/kcp/deploy/examples/template-cowboys.yaml, contrib/kcp/deploy/examples/template-sheriffs.yaml, apiserviceexport.yaml
New manifest examples demonstrating Collection and APIServiceExportTemplate resources with permission claims and namespaces.
KCP Documentation
contrib/kcp/README.md
Updated kubectl commands to use apply instead of create; added UI template examples; refreshed example URLs.
Backend Manager
backend/kubernetes/manager.go
Added public methods: ListCollections(ctx, cluster) and GetTemplates(ctx, cluster, name) for fetching template metadata.
Backend HTTP Handler
backend/http/handler.go
Replaced getBackendDynamicResource with listCollectionTemplates; updated handleResources and handleBind to construct UISchema from template data; changed UISchema structure to include Description, Resources, PermissionClaims, Namespaces arrays.
Backend Resources
backend/kubernetes/resources/resources.go
Removed TODO comment before ExportedCRDsLabel constant.
UI Templates
backend/template/resources.gohtml
Redesigned resources page with module-centric two-column grid layout; replaced per-resource Bind links with module-level Bind Module button; added Bootstrap Icons; removed old export card structure.
Removed Login UI
backend/template/login.html
Deleted entire login template file.
CLI Binding
cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go
Simplified binding workflow to use single APIServiceBinding per request; added global CRD ownership validation; consolidated success messaging.
Generated Client/Informer/Lister Code
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/apiserviceexporttemplate.go, sdk/client/clientset/versioned/typed/kubebind/v1alpha2/collection.go, sdk/client/clientset/versioned/typed/kubebind/v1alpha2/fake/*.go, sdk/client/clientset/versioned/typed/kubebind/v1alpha2/kubebind_client.go, sdk/client/clientset/versioned/typed/kubebind/v1alpha2/generated_expansion.go, sdk/client/informers/externalversions/kubebind/v1alpha2/*.go, sdk/client/informers/externalversions/generic.go, sdk/client/listers/kubebind/v1alpha2/*.go
Generated typed interfaces, implementations, and factory functions for APIServiceExportTemplate and Collection CRUD, watching, listing, and caching operations.
Documentation
README.md, docs/content/index.md, docs/content/setup/index.md, docs/content/setup/quickstart.md, docs/content/.pages, docs/content/usage/.pages, docs/content/usage/index.md, docs/content/usage/migration.md
Added v0.6.0 API change documentation, key features section, usage guide, and comprehensive migration guide from v0.5.x.
CodeRabbit Configuration
.coderabbit.yaml
Reversed path_filters semantics from inclusion to exclusion; now excludes sdk/client/** and **/*.yaml patterns.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User as User
    participant UI as Backend UI
    participant Manager as Backend Manager
    participant K8s as Kubernetes API

    rect rgb(200, 220, 255)
    Note over User,K8s: Old Per-Resource Flow (v0.5)
    User->>UI: Request resources
    UI->>Manager: getBackendDynamicResource
    Manager->>K8s: List APIServiceExports
    K8s-->>Manager: Per-resource schemas
    Manager-->>UI: Individual resource data
    UI->>UI: Build per-resource cards
    UI-->>User: Export list with per-resource Bind
    end

    rect rgb(200, 255, 220)
    Note over User,K8s: New Template-Based Flow (v0.6)
    User->>UI: Request resources
    UI->>Manager: listCollectionTemplates
    Manager->>K8s: List Collections
    K8s-->>Manager: Collection list
    Manager->>K8s: Get Templates for each Collection
    K8s-->>Manager: Template specs with resources & claims
    Manager-->>UI: Template data (Description, Resources, PermissionClaims)
    UI->>UI: Build module cards from templates
    UI-->>User: Module grid with Module-level Bind
    end

    rect rgb(255, 220, 200)
    Note over User,K8s: Binding Flow
    User->>UI: Bind Module
    UI->>Manager: GetTemplates(templateName)
    Manager->>K8s: Get specific Template
    K8s-->>Manager: Template spec
    Manager-->>UI: APIServiceExportRequestSpec from Template
    UI->>UI: Create single APIServiceBinding
    UI->>K8s: Apply APIServiceBinding
    K8s-->>UI: Binding created/reused
    UI-->>User: Success (X resources bound)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Rationale: The PR spans multiple heterogeneous areas (API schema changes, backend refactoring, UI redesign, CLI simplification, and codegen) with substantive logic modifications. While generated code is high-volume, the core business logic changes in backend handlers, controller updates for NamedResources, and CRD migrations require careful reasoning per area. The template-to-resources mapping, UISchema structure changes, and unified binding workflow represent densely interconnected logic changes across the system.

Possibly related PRs

  • Add PermissionClaims #304: Modifies PermissionClaim/Selector/NamedResource APIs and touches deep-copy, client/informer wiring, and controller logic for claimed resources—directly overlapping with this PR's API and controller changes.
  • Provider side namespace management  #345: Adds provider-side namespace bootstrapping via the namespaces field in APIServiceExportRequest CRD, which is part of this PR's schema updates.
  • Move to schemaless backend #295: Refactors backend/http handler and manager to transition from per-resource APIResourceSchema dynamics to template/BoundSchema-driven workflows, paralleling the template architecture introduced here.

Suggested labels

ai-code-review, api-change, backend, ui-update, migration-guide

Suggested reviewers

  • xrstf
  • moadqassem

Poem

🐰 Templates bloom, modules gleam bright,
No more per-resource in sight,
Collections gather, permission claims soar,
The binding dance simplified to core,
A v0.6 spring, refactored delight!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed The PR description contains all required sections from the template: a Summary section explaining that the PR adds catalog API machinery with API definitions and KCP wiring; a What Type of PR section with the /kind feature tag; a Related Issue(s) section (though empty, which may be acceptable if unrelated to a specific issue); and Release Notes with "Add CatalogAPI skeleton". The description is sufficiently complete with a clear explanation of the change scope and intent, even though some sections are minimal.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
Title Check ✅ Passed The title "Add CatalogAPI" directly and accurately summarizes the primary objective of the changeset. The PR introduces a complete Catalog API framework including new API types (APIServiceExportTemplate, Collection), backend handlers and manager methods to list collections and retrieve templates, UI updates to use template-based resources, CRD definitions, and associated client libraries and informers. The title clearly conveys that the main change is the addition of CatalogAPI infrastructure, which is consistent with the PR objectives stating "Adds machinery for a catalog API, including API definitions and some kcp wiring." The title is concise and specific enough that reviewers scanning the history would understand the primary change.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ntnn ntnn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love it. Just one nit.

Comment thread sdk/apis/kubebind/v1alpha2/collection_types.go
@mjudeikis mjudeikis force-pushed the mjudeikis/catalog.api branch 2 times, most recently from a66c8f5 to 39d8023 Compare October 16, 2025 07:31
ntnn
ntnn previously approved these changes Oct 16, 2025
@mjudeikis

Copy link
Copy Markdown
Contributor Author

Ran into another issue with "provider driven namespaces & resources". As its now blocked by kcp-dev/kcp#3653, continue work until its unblocked and will start splitting it out after.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
deploy/crd/kube-bind.io_apiservicebindings.yaml (1)

384-405: Update example YAML file to use new field name.

The breaking field rename has been correctly implemented in the schema (CRD) and Go code, and migration documentation is in place. However, the example file contrib/kcp/deploy/examples/apiserviceexport-namespaced.yaml at line 24 still uses the old namedResource: (singular) field name, which will fail validation against the updated schema.

Update line 24 in the example file from:

namedResource:

to:

namedResources:

The rest of the example uses valid structure—it only needs the field name corrected.

deploy/crd/kube-bind.io_apiserviceexports.yaml (1)

427-429: Validation message does not match rule

Rule enforces metadata.name == <plural>.<group>, but message says “informerScope is immutable”.

Apply this diff:

-        - message: informerScope is immutable
-          rule: self.metadata.name == self.spec.names.plural+"."+self.spec.group
+        - message: metadata.name must equal spec.names.plural+"."+spec.group
+          rule: self.metadata.name == self.spec.names.plural+"."+self.spec.group
🧹 Nitpick comments (15)
backend/template/resources.gohtml (1)

10-11: Consider pinning Bootstrap Icons to a specific version.

The Bootstrap Icons CDN link uses version 1.7.2, which is several years old (released ~2021). Consider either:

  1. Updating to the latest stable version for bug fixes and new icons
  2. Adding a subresource integrity (SRI) hash for the specified version
-    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css">
+    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" integrity="sha384-..." crossorigin="anonymous">

You can generate the SRI hash at https://www.srihash.org/

pkg/konnector/controllers/cluster/namespacelifecycle/namespacelifecycle_controller.go (1)

237-254: Clarify intended behavior for namespace cleanup on APIServiceNamespace deletion.

When an APIServiceNamespace is deleted (lines 239-254), the code checks if the corresponding Namespace exists but then does not delete it, stating "we can't be sure who owns it" (line 251). This could leave orphaned namespaces in the consumer cluster.

Is this the intended behavior? Consider:

  1. If the APIServiceNamespace had the ObjectOwnerLabel, that information is now lost (since the object is deleted), making it impossible to determine ownership
  2. This conservative approach prevents accidental deletion but may require manual cleanup

Suggested alternatives:

  • Use a finalizer on APIServiceNamespace to determine ownership before deletion
  • Add owner references or labels to the Namespace itself to track ownership
  • Document this behavior and provide a cleanup tool for operators

Do you want to track this as a known limitation, or should we implement one of the alternatives?

sdk/apis/catalog/v1alpha1/collection_types.go (1)

71-78: Consider adding validation for module name format.

The ModuleReference.Name field is marked as required but doesn't specify format validation. Should it validate that the name references an actual Module resource?

Consider adding:

  1. Pattern validation to match Kubernetes resource name constraints
  2. A CEL validation rule to check that the referenced Module exists (if cross-resource validation is supported in your environment)
 type ModuleReference struct {
 	// name is the name of the module.
 	//
 	// +required
 	// +kubebuilder:validation:Required
+	// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
+	// +kubebuilder:validation:MaxLength=253
 	Name string `json:"name"`
 }

Validating the reference exists would require a validating webhook or CEL rule, which may be out of scope for this PR.

contrib/kcp/deploy/resources/apiresourceschema-apiservicebindings.kube-bind.io.yaml (1)

377-399: Pluralization is correct; fix descriptions and consider list keys + optional CEL.

  • Descriptions still say “NamedResource” (singular). Align wording with the plural field.
  • For deterministic merges/dedup, make the list a map keyed by name/namespace.
  • If selector.labelSelector and selector.namedResources are intended to be mutually exclusive, add a CEL rule (optional).

Apply within this block:

-                      namedResources:
-                        description: NamedResource is a shorthand for selecting a
-                          single resource by name and namespace.
+                      namedResources:
+                        description: NamedResources is a shorthand for selecting specific
+                          resources by name and namespace.
+                        x-kubernetes-list-type: map
+                        x-kubernetes-list-map-keys:
+                        - name
+                        - namespace
                         items:
-                          description: NamedResource selects a specific resource by
-                            name and namespace.
+                          description: A NamedResource item selects a specific resource by
+                            name and namespace.

If mutually exclusive with labelSelector, add under selector (outside this range):

# under: selector:
x-kubernetes-validations:
- rule: "has(self.labelSelector) != has(self.namedResources)"
  message: "Provide either labelSelector or namedResources, not both."

Please confirm exclusivity intent; I can send a full patch accordingly.

pkg/konnector/controllers/cluster/claimedresources/claimedresources_reconciler.go (1)

186-187: LGTM! Good refactoring to use public constant.

Replacing the hardcoded label key "kube-bind.io/owner" with the public constant kubebindv1alpha2.ObjectOwnerLabel improves maintainability and eliminates potential typos. The behavior remains unchanged.

Also applies to: 195-196, 238-238, 251-251

docs/content/usage/index.md (1)

125-125: Minor grammar issue: hyphenate compound adjective.

As per the static analysis hint, "Label Selector Based" should be hyphenated when used as a compound adjective before a noun.

Apply this diff:

-### Label Selector Based Claims
+### Label-Selector-Based Claims
backend/controllers/serviceexportrequest/serviceexportrequest_reconcile.go (2)

376-405: Optional: rename param to avoid shadowing package name.

Rename cache cache.Cache to infCache cache.Cache for readability and to avoid shadowing the imported package.

-func (r *reconciler) ensureAPIServiceNamespaces(ctx context.Context, cl client.Client, cache cache.Cache, req *kubebindv1alpha2.APIServiceExportRequest) error {
+func (r *reconciler) ensureAPIServiceNamespaces(ctx context.Context, cl client.Client, infCache cache.Cache, req *kubebindv1alpha2.APIServiceExportRequest) error {
-    err := cache.Get(ctx, client.ObjectKey{Namespace: apiServiceNamespace.Namespace, Name: apiServiceNamespace.Name}, currentAPIServiceNamespace)
+    err := infCache.Get(ctx, client.ObjectKey{Namespace: apiServiceNamespace.Namespace, Name: apiServiceNamespace.Name}, currentAPIServiceNamespace)

73-76: Consider status/condition for namespace provisioning.

Add a condition (e.g., NamespacesReady) to reflect progress/errors per requested namespace.

If desired, I can draft the condition plumbing.

deploy/crd/catalog.kube-bind.io_collections.yaml (1)

58-71: Enforce uniqueness for spec.modules via list-map keys

To prevent duplicate module references and get merge-friendly patches, model modules as a map-by-name.

Apply this diff:

   modules:
     description: modules is a list of module references that are part
       of this collection.
     items:
       description: ModuleReference references a Module by name.
       properties:
         name:
           description: name is the name of the module.
           type: string
       required:
       - name
       type: object
-    minItems: 1
-    type: array
+    minItems: 1
+    type: array
+    x-kubernetes-list-type: map
+    x-kubernetes-list-map-keys:
+    - name
cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go (1)

54-55: Avoid hardcoding kube-bind namespace for the secret (if configurable)

If the secret’s namespace can vary across environments, avoid a hard-coded check; compare against the intended namespace source, or make it an option.

Consider:

  • Pass the expected namespace into this function, or
  • Compare against request.Spec.Namespaces (if present in v1alpha2) or another config source.
deploy/crd/kube-bind.io_apiserviceexports.yaml (1)

567-589: Pluralized field namedResources still uses singular wording; add list-map keys for dedupe

Update description to plural and consider enforcing uniqueness by (namespace,name).

Apply this diff:

-                        namedResources:
-                          description: NamedResource is a shorthand for selecting
-                            a single resource by name and namespace.
+                        namedResources:
+                          description: NamedResources is a shorthand for selecting
+                            specific resources by name and namespace.
                           items:
                             description: NamedResource selects a specific resource
                               by name and namespace.
                             properties:
@@
                           type: array
+                          x-kubernetes-list-type: map
+                          x-kubernetes-list-map-keys:
+                          - namespace
+                          - name
deploy/crd/catalog.kube-bind.io_modules.yaml (1)

203-212: Redundant but harmless scope validation.

The allOf contains two identical enum lists (just in different orders). This is redundant but doesn't affect functionality—it's likely generated by kubebuilder.

Simplify to a single enum:

-            allOf:
-            - enum:
-              - Cluster
-              - Namespaced
-            - enum:
-              - Namespaced
-              - Cluster
+            enum:
+            - Cluster
+            - Namespaced
sdk/apis/catalog/v1alpha1/module_types.go (1)

60-64: Optional: remove omitempty on required field.

scope is required; omitempty is misleading (marshalling only). Safe to drop.

- Scope kubebindv1alpha2.InformerScope `json:"scope,omitempty"`
+ Scope kubebindv1alpha2.InformerScope `json:"scope"`
contrib/kcp/deploy/resources/apiresourceschema-modules.catalog.kube-bind.io.yaml (2)

201-209: Simplify duplicated scope enum.

Two identical enums under allOf are redundant; keep one for clarity.

-            scope:
-              allOf:
-              - enum:
-                - Cluster
-                - Namespaced
-              - enum:
-                - Namespaced
-                - Cluster
+            scope:
+              enum:
+              - Cluster
+              - Namespaced

84-90: Polish description grammar (non-functional).

Use “cannot” and “a service”.

-                      Note: it is worth noting that you can not ask for permissions for resource provided by a CRD
-                      not provided by an service binding export.
+                      Note: you cannot ask for permissions for a resource provided by a CRD
+                      not provided by a service binding export.

Also applies to: 170-186

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10c28b8 and d1ae972.

📒 Files selected for processing (77)
  • .coderabbit.yaml (1 hunks)
  • README.md (1 hunks)
  • apiserviceexport.yaml (1 hunks)
  • backend/config.go (2 hunks)
  • backend/controllers/serviceexport/serviceexport_controller.go (2 hunks)
  • backend/controllers/serviceexport/serviceexport_reconcile.go (3 hunks)
  • backend/controllers/serviceexportrequest/serviceexportrequest_reconcile.go (2 hunks)
  • backend/controllers/servicenamespace/servicenamespace_reconcile.go (1 hunks)
  • backend/http/handler.go (6 hunks)
  • backend/kubernetes/manager.go (2 hunks)
  • backend/kubernetes/resources/resources.go (1 hunks)
  • backend/server.go (1 hunks)
  • backend/template/login.html (0 hunks)
  • backend/template/resources.gohtml (1 hunks)
  • cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go (2 hunks)
  • contrib/kcp/README.md (3 hunks)
  • contrib/kcp/deploy/examples/collection-wildwest.yaml (1 hunks)
  • contrib/kcp/deploy/examples/module-cowboys.yaml (1 hunks)
  • contrib/kcp/deploy/examples/module-sheriffs.yaml (1 hunks)
  • contrib/kcp/deploy/resources/apiexport-catalog.kube-bind.io.yaml (1 hunks)
  • contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml (2 hunks)
  • contrib/kcp/deploy/resources/apiresourceschema-apiservicebindings.kube-bind.io.yaml (2 hunks)
  • contrib/kcp/deploy/resources/apiresourceschema-apiserviceexportrequests.kube-bind.io.yaml (3 hunks)
  • contrib/kcp/deploy/resources/apiresourceschema-apiserviceexports.kube-bind.io.yaml (2 hunks)
  • contrib/kcp/deploy/resources/apiresourceschema-collections.catalog.kube-bind.io.yaml (1 hunks)
  • contrib/kcp/deploy/resources/apiresourceschema-modules.catalog.kube-bind.io.yaml (1 hunks)
  • contrib/kcp/hack/update-kcp-codegen.sh (1 hunks)
  • deploy/crd/catalog.kube-bind.io_collections.yaml (1 hunks)
  • deploy/crd/catalog.kube-bind.io_modules.yaml (1 hunks)
  • deploy/crd/kube-bind.io_apiservicebindings.yaml (1 hunks)
  • deploy/crd/kube-bind.io_apiserviceexportrequests.yaml (2 hunks)
  • deploy/crd/kube-bind.io_apiserviceexports.yaml (1 hunks)
  • docs/content/.pages (1 hunks)
  • docs/content/index.md (1 hunks)
  • docs/content/setup/index.md (1 hunks)
  • docs/content/setup/quickstart.md (1 hunks)
  • docs/content/usage/.pages (1 hunks)
  • docs/content/usage/index.md (1 hunks)
  • docs/content/usage/migration.md (1 hunks)
  • pkg/konnector/controllers/cluster/claimedresources/claimedresources_controller.go (2 hunks)
  • pkg/konnector/controllers/cluster/claimedresources/claimedresources_reconciler.go (4 hunks)
  • pkg/konnector/controllers/cluster/cluster_controller.go (5 hunks)
  • pkg/konnector/controllers/cluster/namespacelifecycle/namespacelifecycle_controller.go (5 hunks)
  • pkg/resources/resources.go (2 hunks)
  • pkg/resources/resources_test.go (9 hunks)
  • sdk/apis/catalog/v1alpha1/collection_types.go (1 hunks)
  • sdk/apis/catalog/v1alpha1/doc.go (1 hunks)
  • sdk/apis/catalog/v1alpha1/module_types.go (1 hunks)
  • sdk/apis/catalog/v1alpha1/register.go (1 hunks)
  • sdk/apis/catalog/v1alpha1/zz_generated.deepcopy.go (1 hunks)
  • sdk/apis/kubebind/v1alpha2/apiserviceexport_types.go (1 hunks)
  • sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (2 hunks)
  • sdk/apis/kubebind/v1alpha2/helpers/namespaces.go (1 hunks)
  • sdk/apis/kubebind/v1alpha2/zz_generated.deepcopy.go (3 hunks)
  • sdk/client/clientset/versioned/clientset.go (4 hunks)
  • sdk/client/clientset/versioned/fake/clientset_generated.go (2 hunks)
  • sdk/client/clientset/versioned/fake/register.go (2 hunks)
  • sdk/client/clientset/versioned/scheme/register.go (2 hunks)
  • sdk/client/clientset/versioned/typed/catalog/v1alpha1/catalog_client.go (1 hunks)
  • sdk/client/clientset/versioned/typed/catalog/v1alpha1/collection.go (1 hunks)
  • sdk/client/clientset/versioned/typed/catalog/v1alpha1/doc.go (1 hunks)
  • sdk/client/clientset/versioned/typed/catalog/v1alpha1/fake/doc.go (1 hunks)
  • sdk/client/clientset/versioned/typed/catalog/v1alpha1/fake/fake_catalog_client.go (1 hunks)
  • sdk/client/clientset/versioned/typed/catalog/v1alpha1/fake/fake_collection.go (1 hunks)
  • sdk/client/clientset/versioned/typed/catalog/v1alpha1/fake/fake_module.go (1 hunks)
  • sdk/client/clientset/versioned/typed/catalog/v1alpha1/generated_expansion.go (1 hunks)
  • sdk/client/clientset/versioned/typed/catalog/v1alpha1/module.go (1 hunks)
  • sdk/client/informers/externalversions/catalog/interface.go (1 hunks)
  • sdk/client/informers/externalversions/catalog/v1alpha1/collection.go (1 hunks)
  • sdk/client/informers/externalversions/catalog/v1alpha1/interface.go (1 hunks)
  • sdk/client/informers/externalversions/catalog/v1alpha1/module.go (1 hunks)
  • sdk/client/informers/externalversions/factory.go (2 hunks)
  • sdk/client/informers/externalversions/generic.go (2 hunks)
  • sdk/client/listers/catalog/v1alpha1/collection.go (1 hunks)
  • sdk/client/listers/catalog/v1alpha1/expansion_generated.go (1 hunks)
  • sdk/client/listers/catalog/v1alpha1/module.go (1 hunks)
  • test/e2e/bind/happy-case_test.go (2 hunks)
💤 Files with no reviewable changes (1)
  • backend/template/login.html
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-22T13:20:49.952Z
Learnt from: mjudeikis
PR: kube-bind/kube-bind#304
File: sdk/apis/kubebind/v1alpha2/boundchema_types.go:49-0
Timestamp: 2025-09-22T13:20:49.952Z
Learning: In kube-bind, BoundSchema.ResourceGroupName() is only used for CRDs (Custom Resource Definitions), and CRDs must always have non-empty API groups. Therefore, handling empty groups (core API group "") is not necessary in this context, unlike general Kubernetes GroupResource handling.

Applied to files:

  • sdk/apis/catalog/v1alpha1/register.go
📚 Learning: 2025-09-22T13:20:49.952Z
Learnt from: mjudeikis
PR: kube-bind/kube-bind#304
File: sdk/apis/kubebind/v1alpha2/boundchema_types.go:49-0
Timestamp: 2025-09-22T13:20:49.952Z
Learning: In kube-bind, there are two different ResourceGroupName() methods: BoundSchema.ResourceGroupName() for CRDs (always non-empty groups) uses simple fmt.Sprintf formatting, while APIServiceExportRequestResource.ResourceGroupName() for export requests handles empty groups by converting to "core". BoundSchema is exclusively for CRDs which cannot have empty API groups per Kubernetes validation.

Applied to files:

  • sdk/apis/catalog/v1alpha1/register.go
📚 Learning: 2025-09-12T08:40:15.290Z
Learnt from: mjudeikis
PR: kube-bind/kube-bind#295
File: backend/controllers/serviceexportrequest/serviceexportrequest_reconcile.go:140-143
Timestamp: 2025-09-12T08:40:15.290Z
Learning: APIServiceExportRequest resources in kube-bind are short-lived and automatically deleted after 10 minutes, so they should not be used as owner references for longer-lived resources like BoundSchema. The proper lifecycle management for BoundSchema resources created by APIServiceExportRequest is tracked in issue #297.

Applied to files:

  • contrib/kcp/deploy/resources/apiresourceschema-apiserviceexportrequests.kube-bind.io.yaml
  • apiserviceexport.yaml
  • contrib/kcp/deploy/resources/apiresourceschema-apiserviceexports.kube-bind.io.yaml
🧬 Code graph analysis (36)
sdk/apis/catalog/v1alpha1/module_types.go (4)
sdk/apis/third_party/conditions/apis/conditions/v1alpha1/types.go (1)
  • Conditions (92-92)
sdk/apis/kubebind/v1alpha2/boundchema_types.go (1)
  • InformerScope (59-59)
sdk/apis/kubebind/v1alpha2/apiserviceexport_types.go (1)
  • APIServiceExportResource (83-83)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (2)
  • PermissionClaim (206-213)
  • Namespaces (129-135)
sdk/client/informers/externalversions/catalog/v1alpha1/interface.go (5)
sdk/client/informers/externalversions/catalog/v1alpha1/collection.go (1)
  • CollectionInformer (37-40)
sdk/client/informers/externalversions/catalog/v1alpha1/module.go (1)
  • ModuleInformer (37-40)
sdk/client/informers/externalversions/factory.go (1)
  • SharedInformerFactory (227-260)
sdk/client/informers/externalversions/internalinterfaces/factory_interfaces.go (1)
  • TweakListOptionsFunc (40-40)
sdk/client/informers/externalversions/catalog/interface.go (2)
  • New (39-41)
  • Interface (27-30)
backend/controllers/serviceexport/serviceexport_reconcile.go (2)
sdk/apis/kubebind/v1alpha2/boundchema_types.go (3)
  • InformerScope (59-59)
  • BoundSchema (41-47)
  • ClusterScope (62-62)
sdk/apis/kubebind/v1alpha2/apiserviceexport_types.go (1)
  • APIServiceExport (61-72)
pkg/resources/resources_test.go (1)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (1)
  • NamedResource (165-179)
sdk/client/informers/externalversions/factory.go (3)
sdk/client/clientset/versioned/clientset.go (2)
  • Interface (33-38)
  • New (138-146)
sdk/client/informers/externalversions/catalog/interface.go (2)
  • Interface (27-30)
  • New (39-41)
sdk/client/informers/externalversions/catalog/v1alpha1/interface.go (2)
  • Interface (26-31)
  • New (40-42)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/fake/fake_catalog_client.go (4)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/collection.go (1)
  • CollectionInterface (39-51)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/module.go (1)
  • ModuleInterface (39-51)
sdk/client/clientset/versioned/clientset.go (1)
  • Interface (33-38)
sdk/client/informers/externalversions/catalog/v1alpha1/interface.go (1)
  • Interface (26-31)
sdk/apis/catalog/v1alpha1/collection_types.go (1)
sdk/apis/third_party/conditions/apis/conditions/v1alpha1/types.go (1)
  • Conditions (92-92)
backend/controllers/serviceexport/serviceexport_controller.go (1)
sdk/apis/kubebind/v1alpha2/boundchema_types.go (1)
  • InformerScope (59-59)
backend/controllers/serviceexportrequest/serviceexportrequest_reconcile.go (4)
sdk/apis/third_party/conditions/util/conditions/setter.go (1)
  • SetSummary (126-128)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (2)
  • APIServiceExportRequest (46-60)
  • Namespaces (129-135)
sdk/apis/kubebind/v1alpha2/apiserviceexport_types.go (1)
  • APIServiceExport (61-72)
sdk/apis/kubebind/v1alpha2/helpers/namespaces.go (1)
  • APIServiceNamespaceFromExport (25-39)
sdk/client/informers/externalversions/generic.go (2)
sdk/apis/kubebind/v1alpha1/register.go (1)
  • SchemeGroupVersion (39-39)
sdk/apis/kubebind/v1alpha2/register.go (1)
  • SchemeGroupVersion (39-39)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/catalog_client.go (4)
sdk/client/clientset/versioned/clientset.go (4)
  • Interface (33-38)
  • NewForConfig (76-90)
  • NewForConfigAndClient (96-125)
  • New (138-146)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/collection.go (2)
  • CollectionsGetter (34-36)
  • CollectionInterface (39-51)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/module.go (2)
  • ModulesGetter (34-36)
  • ModuleInterface (39-51)
sdk/client/clientset/versioned/scheme/register.go (2)
  • Scheme (32-32)
  • Codecs (33-33)
sdk/apis/kubebind/v1alpha2/zz_generated.deepcopy.go (1)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (1)
  • Namespaces (129-135)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/fake/fake_module.go (3)
sdk/apis/catalog/v1alpha1/module_types.go (2)
  • Module (36-47)
  • ModuleList (94-99)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/fake/fake_catalog_client.go (1)
  • FakeCatalogV1alpha1 (27-29)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/module.go (1)
  • ModuleInterface (39-51)
backend/kubernetes/manager.go (2)
sdk/apis/catalog/v1alpha1/collection_types.go (1)
  • CollectionList (89-94)
sdk/apis/catalog/v1alpha1/module_types.go (1)
  • Module (36-47)
sdk/client/clientset/versioned/clientset.go (1)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/catalog_client.go (4)
  • CatalogV1alpha1Interface (29-33)
  • CatalogV1alpha1Client (36-38)
  • NewForConfigAndClient (63-71)
  • New (84-86)
sdk/apis/kubebind/v1alpha2/helpers/namespaces.go (3)
sdk/apis/kubebind/v1alpha2/apiserviceexport_types.go (2)
  • APIServiceExport (61-72)
  • ObjectOwnerLabel (30-30)
sdk/apis/kubebind/v1alpha1/apiservicenamespace_types.go (2)
  • APIServiceNamespace (41-50)
  • APIServiceNamespaceSpec (52-53)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (1)
  • OwnerProvider (220-220)
sdk/apis/catalog/v1alpha1/register.go (2)
sdk/apis/catalog/v1alpha1/module_types.go (2)
  • Module (36-47)
  • ModuleList (94-99)
sdk/apis/catalog/v1alpha1/collection_types.go (2)
  • Collection (35-46)
  • CollectionList (89-94)
pkg/konnector/controllers/cluster/claimedresources/claimedresources_reconciler.go (2)
sdk/apis/kubebind/v1alpha2/apiserviceexport_types.go (1)
  • ObjectOwnerLabel (30-30)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (2)
  • OwnerConsumer (222-222)
  • OwnerProvider (220-220)
sdk/client/clientset/versioned/fake/register.go (3)
sdk/client/clientset/versioned/scheme/register.go (1)
  • AddToScheme (55-55)
sdk/apis/kubebind/v1alpha1/register.go (1)
  • AddToScheme (27-27)
sdk/apis/kubebind/v1alpha2/register.go (1)
  • AddToScheme (27-27)
sdk/client/informers/externalversions/catalog/v1alpha1/collection.go (5)
sdk/client/listers/catalog/v1alpha1/collection.go (2)
  • CollectionLister (30-37)
  • NewCollectionLister (45-47)
sdk/client/informers/externalversions/factory.go (1)
  • SharedInformerFactory (227-260)
sdk/client/informers/externalversions/internalinterfaces/factory_interfaces.go (1)
  • TweakListOptionsFunc (40-40)
sdk/client/clientset/versioned/clientset.go (1)
  • Interface (33-38)
sdk/client/informers/externalversions/catalog/v1alpha1/interface.go (1)
  • Interface (26-31)
backend/server.go (1)
sdk/apis/kubebind/v1alpha2/boundchema_types.go (1)
  • InformerScope (59-59)
sdk/client/informers/externalversions/catalog/interface.go (3)
sdk/client/informers/externalversions/catalog/v1alpha1/interface.go (2)
  • Interface (26-31)
  • New (40-42)
sdk/client/informers/externalversions/factory.go (1)
  • SharedInformerFactory (227-260)
sdk/client/informers/externalversions/internalinterfaces/factory_interfaces.go (1)
  • TweakListOptionsFunc (40-40)
sdk/apis/catalog/v1alpha1/zz_generated.deepcopy.go (4)
sdk/apis/catalog/v1alpha1/collection_types.go (5)
  • Collection (35-46)
  • CollectionList (89-94)
  • CollectionSpec (57-69)
  • ModuleReference (72-78)
  • CollectionStatus (81-84)
sdk/apis/third_party/conditions/apis/conditions/v1alpha1/types.go (1)
  • Conditions (92-92)
sdk/apis/catalog/v1alpha1/module_types.go (4)
  • Module (36-47)
  • ModuleList (94-99)
  • ModuleSpec (58-83)
  • ModuleStatus (86-89)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (3)
  • APIServiceExportRequestResource (137-143)
  • PermissionClaim (206-213)
  • Namespaces (129-135)
sdk/client/clientset/versioned/scheme/register.go (3)
sdk/client/clientset/versioned/fake/register.go (1)
  • AddToScheme (55-55)
sdk/apis/kubebind/v1alpha1/register.go (1)
  • AddToScheme (27-27)
sdk/apis/kubebind/v1alpha2/register.go (1)
  • AddToScheme (27-27)
cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go (4)
cli/pkg/kubectl/base/options.go (1)
  • Options (26-40)
sdk/apis/third_party/conditions/util/conditions/setter.go (1)
  • MarkFalse (120-122)
sdk/apis/third_party/conditions/apis/conditions/v1alpha1/constants.go (1)
  • ReadyCondition (24-24)
sdk/apis/third_party/conditions/apis/conditions/v1alpha1/types.go (1)
  • ConditionSeverityInfo (37-37)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/collection.go (5)
sdk/apis/catalog/v1alpha1/collection_types.go (2)
  • Collection (35-46)
  • CollectionList (89-94)
sdk/client/clientset/versioned/clientset.go (1)
  • Interface (33-38)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/generated_expansion.go (1)
  • CollectionExpansion (21-21)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/catalog_client.go (1)
  • CatalogV1alpha1Client (36-38)
sdk/client/clientset/versioned/scheme/register.go (1)
  • ParameterCodec (34-34)
sdk/client/clientset/versioned/fake/clientset_generated.go (3)
sdk/client/clientset/versioned/clientset.go (1)
  • Clientset (41-46)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/catalog_client.go (1)
  • CatalogV1alpha1Interface (29-33)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/fake/fake_catalog_client.go (1)
  • FakeCatalogV1alpha1 (27-29)
test/e2e/bind/happy-case_test.go (1)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (1)
  • NamedResource (165-179)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/fake/fake_collection.go (3)
sdk/apis/catalog/v1alpha1/collection_types.go (2)
  • Collection (35-46)
  • CollectionList (89-94)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/fake/fake_catalog_client.go (1)
  • FakeCatalogV1alpha1 (27-29)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/collection.go (1)
  • CollectionInterface (39-51)
sdk/client/listers/catalog/v1alpha1/module.go (2)
sdk/apis/catalog/v1alpha1/module_types.go (1)
  • Module (36-47)
sdk/client/listers/catalog/v1alpha1/expansion_generated.go (2)
  • ModuleListerExpansion (31-31)
  • ModuleNamespaceListerExpansion (35-35)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/module.go (5)
sdk/apis/catalog/v1alpha1/module_types.go (2)
  • Module (36-47)
  • ModuleList (94-99)
sdk/client/clientset/versioned/clientset.go (1)
  • Interface (33-38)
sdk/client/informers/externalversions/catalog/v1alpha1/interface.go (1)
  • Interface (26-31)
sdk/client/clientset/versioned/typed/catalog/v1alpha1/generated_expansion.go (1)
  • ModuleExpansion (23-23)
sdk/client/clientset/versioned/scheme/register.go (1)
  • ParameterCodec (34-34)
sdk/client/informers/externalversions/catalog/v1alpha1/module.go (8)
pkg/konnector/controllers/dynamic/eventhandler.go (2)
  • Informer (40-43)
  • SharedIndexInformer (27-38)
sdk/client/listers/catalog/v1alpha1/module.go (2)
  • ModuleLister (30-37)
  • NewModuleLister (45-47)
sdk/client/informers/externalversions/factory.go (1)
  • SharedInformerFactory (227-260)
sdk/client/informers/externalversions/internalinterfaces/factory_interfaces.go (1)
  • TweakListOptionsFunc (40-40)
sdk/client/clientset/versioned/clientset.go (1)
  • Interface (33-38)
sdk/client/informers/externalversions/catalog/interface.go (1)
  • Interface (27-30)
sdk/client/informers/externalversions/catalog/v1alpha1/interface.go (1)
  • Interface (26-31)
sdk/apis/catalog/v1alpha1/module_types.go (1)
  • Module (36-47)
sdk/client/listers/catalog/v1alpha1/collection.go (2)
sdk/apis/catalog/v1alpha1/collection_types.go (1)
  • Collection (35-46)
sdk/client/listers/catalog/v1alpha1/expansion_generated.go (2)
  • CollectionListerExpansion (23-23)
  • CollectionNamespaceListerExpansion (27-27)
backend/http/handler.go (3)
sdk/apis/kubebind/v1alpha2/apiserviceexport_types.go (1)
  • APIServiceExportResource (83-83)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (5)
  • PermissionClaim (206-213)
  • Namespaces (129-135)
  • APIServiceExportRequestResponse (66-79)
  • NameObjectMeta (81-84)
  • APIServiceExportRequestSpec (95-127)
sdk/apis/catalog/v1alpha1/module_types.go (1)
  • ModuleList (94-99)
pkg/konnector/controllers/cluster/cluster_controller.go (2)
pkg/konnector/controllers/cluster/namespacelifecycle/namespacelifecycle_controller.go (1)
  • NewController (48-112)
pkg/konnector/konnector_controller.go (1)
  • GenericController (175-177)
pkg/konnector/controllers/cluster/namespacelifecycle/namespacelifecycle_controller.go (3)
pkg/konnector/controllers/cluster/cluster_controller.go (1)
  • NewController (57-175)
sdk/apis/kubebind/v1alpha2/apiserviceexport_types.go (1)
  • ObjectOwnerLabel (30-30)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (2)
  • OwnerProvider (220-220)
  • Namespaces (129-135)
🪛 LanguageTool
docs/content/usage/migration.md

[grammar] ~94-~94: Ensure spelling is correct
Context: ... ``` ## Step-by-Step Migration ### 1. Backup Existing Resources Before starting mig...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

docs/content/usage/index.md

[grammar] ~125-~125: Use a hyphen to join words.
Context: ...nd the primary CRDs. ### Label Selector Based Claims Access resources based on ...

(QB_NEW_EN_HYPHEN)

🪛 YAMLlint (1.37.1)
.coderabbit.yaml

[error] 34-34: syntax error: expected ',' or ']', but got ''

(syntax)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: verify
  • GitHub Check: go-test-e2e
  • GitHub Check: go-test
  • GitHub Check: lint

Comment thread .coderabbit.yaml
Comment thread backend/controllers/servicenamespace/servicenamespace_reconcile.go Outdated
Comment thread cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go Outdated
Comment thread sdk/apis/catalog/v1alpha1/module_types.go Outdated
Comment thread sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go Outdated
Comment thread sdk/client/listers/kubebind/v1alpha2/collection.go
Comment thread sdk/client/listers/catalog/v1alpha1/module.go Outdated
Comment thread sdk/client/listers/catalog/v1alpha1/module.go Outdated
@mjudeikis mjudeikis force-pushed the mjudeikis/catalog.api branch from d1ae972 to db0166e Compare October 21, 2025 15:56

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
contrib/kcp/deploy/resources/apiresourceschema-apiserviceexports.kube-bind.io.yaml (1)

425-427: Validation message/rule mismatch (copy/paste bug).

Message says “informerScope is immutable” but the rule enforces metadata.name equals .. Fix the message to reflect the rule.

-  - message: informerScope is immutable
-    rule: self.metadata.name == self.spec.names.plural+"."+self.spec.group
+  - message: metadata.name must be <plural>.<group>
+    rule: self.metadata.name == self.spec.names.plural+"."+self.spec.group
backend/http/handler.go (2)

249-256: Fix base64 codec mismatch for OAuth state.

You encode with base64.URLEncoding in handleAuthorize but decode with base64.StdEncoding here; decoding can fail. Use URLEncoding for both.

Apply this diff:

-	decoded, err := base64.StdEncoding.DecodeString(state)
+	decoded, err := base64.URLEncoding.DecodeString(state)

417-425: Validate required query param “template” in /bind.

Return 400 if missing to avoid fetching an empty-name template.

Apply this diff:

 func (h *handler) handleBind(w http.ResponseWriter, r *http.Request) {
 	logger := getLogger(r)
-	templateName := r.URL.Query().Get("template")
+	templateName := r.URL.Query().Get("template")
+	if templateName == "" {
+		http.Error(w, "missing template query parameter", http.StatusBadRequest)
+		return
+	}
♻️ Duplicate comments (7)
.coderabbit.yaml (1)

33-34: Fix YAML syntax error: quote strings starting with ! in flow sequences.

The unquoted strings !sdk/client/** and !'**/*.yaml' cause a YAML parse error. In flow sequences (bracket notation), strings starting with ! must be quoted to be treated as literals rather than YAML tag indicators.

Apply this diff to fix the syntax:

  path_filters: [
-   !sdk/client/**,
-   !'**/*.yaml',
+   '!sdk/client/**',
+   '!**/*.yaml',
  ]
cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go (3)

79-80: Remove namespace field from cluster-scoped APIServiceBinding resource.

APIServiceBinding is a cluster-scoped resource, but line 80 sets Namespace: "kube-bind" in the ObjectMeta. For cluster-scoped resources, the namespace field must be omitted.

Apply this diff:

  ObjectMeta: metav1.ObjectMeta{
    Name:      bindingName,
-   Namespace: "kube-bind",
  },

57-57: Message incorrectly implies an update operation.

The message says "Updating existing APIServiceBinding" but the code only validates and returns the existing binding without performing any update.

Apply this diff:

- fmt.Fprintf(b.Options.IOStreams.ErrOut, "✅ Updating existing APIServiceBinding %s.\n", existing.Name)
+ fmt.Fprintf(b.Options.IOStreams.ErrOut, "✅ Reusing existing APIServiceBinding %s.\n", existing.Name)

76-107: Replace polling wrapper with single Create call and explicit AlreadyExists handling.

Using wait.PollUntilContextCancel for a single Create operation adds unnecessary complexity. The poll will fail immediately on error anyway. Instead, perform a single Create call and handle concurrent creation via the AlreadyExists error.

Apply this diff:

- // Create new APIServiceBinding
- var created *kubebindv1alpha2.APIServiceBinding
- if err := wait.PollUntilContextCancel(ctx, 1*time.Second, false, func(ctx context.Context) (bool, error) {
-   created, err = bindClient.KubeBindV1alpha2().APIServiceBindings().Create(ctx, &kubebindv1alpha2.APIServiceBinding{
-     ObjectMeta: metav1.ObjectMeta{
-       Name:      bindingName,
-       Namespace: "kube-bind",
-     },
-     Spec: kubebindv1alpha2.APIServiceBindingSpec{
-       KubeconfigSecretRef: kubebindv1alpha2.ClusterSecretKeyRef{
-         LocalSecretKeyRef: kubebindv1alpha2.LocalSecretKeyRef{
-           Name: secretName,
-           Key:  "kubeconfig",
-         },
-         Namespace: "kube-bind",
-       },
-     },
-   }, metav1.CreateOptions{})
-   if err != nil {
-     return false, err
-   }
-
-   // Best effort status update to have "Pending" in the Ready condition
-   conditions.MarkFalse(created,
-     conditionsapi.ReadyCondition,
-     "Pending",
-     conditionsapi.ConditionSeverityInfo,
-     "Pending",
-   )
-   _, _ = bindClient.KubeBindV1alpha2().APIServiceBindings().UpdateStatus(ctx, created, metav1.UpdateOptions{})
-
-   return true, nil
- }); err != nil {
-   return nil, err
- }
+ // Create new APIServiceBinding
+ created, err := bindClient.KubeBindV1alpha2().APIServiceBindings().Create(ctx, &kubebindv1alpha2.APIServiceBinding{
+   ObjectMeta: metav1.ObjectMeta{
+     Name: bindingName,
+   },
+   Spec: kubebindv1alpha2.APIServiceBindingSpec{
+     KubeconfigSecretRef: kubebindv1alpha2.ClusterSecretKeyRef{
+       LocalSecretKeyRef: kubebindv1alpha2.LocalSecretKeyRef{
+         Name: secretName,
+         Key:  "kubeconfig",
+       },
+       Namespace: "kube-bind",
+     },
+   },
+ }, metav1.CreateOptions{})
+ if apierrors.IsAlreadyExists(err) {
+   // Concurrent creation occurred; fetch and return existing binding
+   existing, err := bindClient.KubeBindV1alpha2().APIServiceBindings().Get(ctx, bindingName, metav1.GetOptions{})
+   if err != nil {
+     return nil, err
+   }
+   return []*kubebindv1alpha2.APIServiceBinding{existing}, nil
+ }
+ if err != nil {
+   return nil, err
+ }
+
+ // Best-effort status update to mark Pending
+ conditions.MarkFalse(created,
+   conditionsapi.ReadyCondition,
+   "Pending",
+   conditionsapi.ConditionSeverityInfo,
+   "Pending",
+ )
+ _, _ = bindClient.KubeBindV1alpha2().APIServiceBindings().UpdateStatus(ctx, created, metav1.UpdateOptions{})
sdk/client/listers/kubebind/v1alpha2/collection.go (1)

45-47: Use plural resource for indexer key (“collections”) to fix lookups.

Singular breaks lister queries. Switch to plural.

 func NewCollectionLister(indexer cache.Indexer) CollectionLister {
-	return &collectionLister{listers.New[*kubebindv1alpha2.Collection](indexer, kubebindv1alpha2.Resource("collection"))}
+	return &collectionLister{listers.New[*kubebindv1alpha2.Collection](indexer, kubebindv1alpha2.Resource("collections"))}
 }
#!/usr/bin/env bash
# Find any listers using singular resource keys.
rg -nP --glob 'sdk/**/listers/**/*.go' '\bResource\("collection"\)|\bResource\("[a-z]+"\)' -C2
docs/content/usage/migration.md (2)

34-37: Fix “mangodb” → “mongodb” in groups/resources and example names.

Use mongodb.com/mongodbs consistently across examples.

-    - group: mangodb.com
+    - group: mongodb.com
@@
-      resource: mangodbs
+      resource: mongodbs
@@
-  name: mangodbs-mangodb-com
+  name: mongodbs-mongodb-com
@@
-    - group: mangodb.com
+    - group: mongodb.com
@@
-      resource: mangodbs
+      resource: mongodbs
@@
-    - group: mangodb.com
+    - group: mongodb.com
@@
-      resource: mangodbs
+      resource: mongodbs

Also applies to: 59-60, 87-90, 143-146, 180-183


96-101: Use “back up” (verb), not “backup.”

Minor grammar fix.

-Before starting migration, backup your existing resources:
+Before starting migration, back up your existing resources:
🧹 Nitpick comments (8)
backend/kubernetes/manager.go (2)

168-182: Accept a selector (and/or paging) to avoid unbounded cluster-wide lists.

Listing all Collections without filters can be costly in large clusters. Consider adding a labels.Selector/ListOptions parameter, or filtering server-side.

-func (m *Manager) ListCollections(ctx context.Context, cluster string) (*kubebindv1alpha2.CollectionList, error) {
+func (m *Manager) ListCollections(ctx context.Context, cluster string, selector labels.Selector) (*kubebindv1alpha2.CollectionList, error) {
@@
-    var collections kubebindv1alpha2.CollectionList
-    err = c.List(ctx, &collections)
+    var collections kubebindv1alpha2.CollectionList
+    listOpts := []client.ListOption{}
+    if selector != nil {
+        listOpts = append(listOpts, client.MatchingLabelsSelector{Selector: selector})
+    }
+    err = c.List(ctx, &collections, listOpts...)

184-198: Rename GetTemplates → GetTemplate for semantic accuracy.

The namespace concern is resolved: APIServiceExportTemplate is cluster-scoped (scope=Cluster), so the current Get() call without namespace is correct. However, the function name should match its return type—it returns a single template (*kubebindv1alpha2.APIServiceExportTemplate), so rename it to GetTemplate (singular).

contrib/kcp/deploy/resources/apiresourceschema-apiserviceexports.kube-bind.io.yaml (1)

565-586: Pluralization nit in description for namedResources.

The field is named namedResources (plural) but the description uses singular “NamedResource”. Align wording.

-                      namedResources:
-                        description: NamedResource is a shorthand for selecting a
-                          single resource by name and namespace.
+                      namedResources:
+                        description: NamedResources is a shorthand for selecting one or more
+                          resources by name and namespace. Each item selects a single resource.
contrib/kcp/deploy/resources/apiresourceschema-apiserviceexporttemplates.kube-bind.io.yaml (2)

141-162: Pluralization nit in description for namedResources.

Same wording issue as elsewhere; use plural for field-level description.

-                      namedResources:
-                        description: NamedResource is a shorthand for selecting a
-                          single resource by name and namespace.
+                      namedResources:
+                        description: NamedResources is a shorthand for selecting one or more
+                          resources by name and namespace. Each item selects a single resource.

200-209: Redundant enum duplication for scope.

allOf with two identical enums is redundant. Prefer a single enum for clarity.

-            scope:
-              allOf:
-              - enum:
-                - Cluster
-                - Namespaced
-              - enum:
-                - Namespaced
-                - Cluster
-              description: scope defines the scope of the resources in this template.
-              type: string
+            scope:
+              description: scope defines the scope of the resources in this template.
+              type: string
+              enum:
+              - Cluster
+              - Namespaced
sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go (1)

58-63: Minor: required field tagged omitempty.

Spec.Scope is required but uses json:"scope,omitempty". Safe, but consider dropping omitempty to always serialize it.

deploy/crd/kube-bind.io_apiserviceexporttemplates.yaml (1)

202-211: CRD scope and schema look good.

Minor nit: scope has duplicated enum entries via allOf; harmless generator artefact. No action needed.

backend/http/handler.go (1)

526-548: Nit: local var shadows imported package name; fix typo in comment.

Rename local template to tmpl and fix “consutruct” → “construct” for clarity.

Apply this diff:

-// 2. Get modules from the backend cluster and consutruct shallow-bound schemas (no crd content).
+// 2. Get modules from the backend cluster and construct shallow-bound schemas (no CRD content).
@@
-	for _, collection := range collections.Items {
-		for _, t := range collection.Spec.Templates {
-			template, err := h.kubeManager.GetTemplates(ctx, cluster, t.Name)
+	for _, collection := range collections.Items {
+		for _, t := range collection.Spec.Templates {
+			tmpl, err := h.kubeManager.GetTemplates(ctx, cluster, t.Name)
 			if err != nil {
 				return nil, fmt.Errorf("failed to get template %q: %w", t.Name, err)
 			}
-			templates.Items = append(templates.Items, *template)
+			templates.Items = append(templates.Items, *tmpl)
 		}
 	}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1ae972 and db0166e.

📒 Files selected for processing (55)
  • .coderabbit.yaml (1 hunks)
  • README.md (1 hunks)
  • apiserviceexport.yaml (1 hunks)
  • backend/http/handler.go (5 hunks)
  • backend/kubernetes/manager.go (1 hunks)
  • backend/kubernetes/resources/resources.go (1 hunks)
  • backend/template/login.html (0 hunks)
  • backend/template/resources.gohtml (1 hunks)
  • cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go (2 hunks)
  • contrib/kcp/README.md (1 hunks)
  • contrib/kcp/deploy/examples/collection-wildwest.yaml (1 hunks)
  • contrib/kcp/deploy/examples/template-cowboys.yaml (1 hunks)
  • contrib/kcp/deploy/examples/template-sheriffs.yaml (1 hunks)
  • contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml (3 hunks)
  • contrib/kcp/deploy/resources/apiresourceschema-apiservicebindings.kube-bind.io.yaml (2 hunks)
  • contrib/kcp/deploy/resources/apiresourceschema-apiserviceexportrequests.kube-bind.io.yaml (1 hunks)
  • contrib/kcp/deploy/resources/apiresourceschema-apiserviceexports.kube-bind.io.yaml (2 hunks)
  • contrib/kcp/deploy/resources/apiresourceschema-apiserviceexporttemplates.kube-bind.io.yaml (1 hunks)
  • contrib/kcp/deploy/resources/apiresourceschema-collections.kube-bind.io.yaml (1 hunks)
  • contrib/kcp/hack/update-kcp-codegen.sh (1 hunks)
  • deploy/crd/kube-bind.io_apiservicebindings.yaml (1 hunks)
  • deploy/crd/kube-bind.io_apiserviceexportrequests.yaml (1 hunks)
  • deploy/crd/kube-bind.io_apiserviceexports.yaml (1 hunks)
  • deploy/crd/kube-bind.io_apiserviceexporttemplates.yaml (1 hunks)
  • deploy/crd/kube-bind.io_collections.yaml (1 hunks)
  • docs/content/.pages (1 hunks)
  • docs/content/index.md (1 hunks)
  • docs/content/setup/index.md (1 hunks)
  • docs/content/setup/quickstart.md (1 hunks)
  • docs/content/usage/.pages (1 hunks)
  • docs/content/usage/index.md (1 hunks)
  • docs/content/usage/migration.md (1 hunks)
  • pkg/konnector/controllers/cluster/claimedresources/claimedresources_controller.go (2 hunks)
  • pkg/resources/resources.go (2 hunks)
  • pkg/resources/resources_test.go (9 hunks)
  • sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (1 hunks)
  • sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go (1 hunks)
  • sdk/apis/kubebind/v1alpha2/collection_types.go (1 hunks)
  • sdk/apis/kubebind/v1alpha2/register.go (1 hunks)
  • sdk/apis/kubebind/v1alpha2/zz_generated.deepcopy.go (3 hunks)
  • sdk/client/clientset/versioned/typed/kubebind/v1alpha2/apiserviceexporttemplate.go (1 hunks)
  • sdk/client/clientset/versioned/typed/kubebind/v1alpha2/collection.go (1 hunks)
  • sdk/client/clientset/versioned/typed/kubebind/v1alpha2/fake/fake_apiserviceexporttemplate.go (1 hunks)
  • sdk/client/clientset/versioned/typed/kubebind/v1alpha2/fake/fake_collection.go (1 hunks)
  • sdk/client/clientset/versioned/typed/kubebind/v1alpha2/fake/fake_kubebind_client.go (2 hunks)
  • sdk/client/clientset/versioned/typed/kubebind/v1alpha2/generated_expansion.go (1 hunks)
  • sdk/client/clientset/versioned/typed/kubebind/v1alpha2/kubebind_client.go (3 hunks)
  • sdk/client/informers/externalversions/generic.go (1 hunks)
  • sdk/client/informers/externalversions/kubebind/v1alpha2/apiserviceexporttemplate.go (1 hunks)
  • sdk/client/informers/externalversions/kubebind/v1alpha2/collection.go (1 hunks)
  • sdk/client/informers/externalversions/kubebind/v1alpha2/interface.go (3 hunks)
  • sdk/client/listers/kubebind/v1alpha2/apiserviceexporttemplate.go (1 hunks)
  • sdk/client/listers/kubebind/v1alpha2/collection.go (1 hunks)
  • sdk/client/listers/kubebind/v1alpha2/expansion_generated.go (2 hunks)
  • test/e2e/bind/happy-case_test.go (2 hunks)
💤 Files with no reviewable changes (1)
  • backend/template/login.html
✅ Files skipped from review due to trivial changes (1)
  • contrib/kcp/deploy/resources/apiresourceschema-collections.kube-bind.io.yaml
🚧 Files skipped from review as they are similar to previous changes (16)
  • sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go
  • docs/content/setup/index.md
  • docs/content/index.md
  • docs/content/setup/quickstart.md
  • test/e2e/bind/happy-case_test.go
  • README.md
  • deploy/crd/kube-bind.io_apiservicebindings.yaml
  • docs/content/usage/.pages
  • contrib/kcp/deploy/resources/apiresourceschema-apiservicebindings.kube-bind.io.yaml
  • deploy/crd/kube-bind.io_apiserviceexportrequests.yaml
  • docs/content/.pages
  • apiserviceexport.yaml
  • backend/kubernetes/resources/resources.go
  • pkg/konnector/controllers/cluster/claimedresources/claimedresources_controller.go
  • pkg/resources/resources_test.go
  • contrib/kcp/README.md
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-22T13:20:49.952Z
Learnt from: mjudeikis
PR: kube-bind/kube-bind#304
File: sdk/apis/kubebind/v1alpha2/boundchema_types.go:49-0
Timestamp: 2025-09-22T13:20:49.952Z
Learning: In kube-bind, there are two different ResourceGroupName() methods: BoundSchema.ResourceGroupName() for CRDs (always non-empty groups) uses simple fmt.Sprintf formatting, while APIServiceExportRequestResource.ResourceGroupName() for export requests handles empty groups by converting to "core". BoundSchema is exclusively for CRDs which cannot have empty API groups per Kubernetes validation.

Applied to files:

  • contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml
📚 Learning: 2025-09-12T08:40:15.290Z
Learnt from: mjudeikis
PR: kube-bind/kube-bind#295
File: backend/controllers/serviceexportrequest/serviceexportrequest_reconcile.go:140-143
Timestamp: 2025-09-12T08:40:15.290Z
Learning: APIServiceExportRequest resources in kube-bind are short-lived and automatically deleted after 10 minutes, so they should not be used as owner references for longer-lived resources like BoundSchema. The proper lifecycle management for BoundSchema resources created by APIServiceExportRequest is tracked in issue #297.

Applied to files:

  • contrib/kcp/deploy/resources/apiresourceschema-apiserviceexports.kube-bind.io.yaml
🧬 Code graph analysis (18)
cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go (4)
cli/pkg/kubectl/base/options.go (1)
  • Options (26-40)
sdk/apis/third_party/conditions/util/conditions/setter.go (1)
  • MarkFalse (120-122)
sdk/apis/third_party/conditions/apis/conditions/v1alpha1/constants.go (1)
  • ReadyCondition (24-24)
sdk/apis/third_party/conditions/apis/conditions/v1alpha1/types.go (1)
  • ConditionSeverityInfo (37-37)
sdk/apis/kubebind/v1alpha2/collection_types.go (1)
sdk/apis/third_party/conditions/apis/conditions/v1alpha1/types.go (1)
  • Conditions (92-92)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/fake/fake_kubebind_client.go (2)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/apiserviceexporttemplate.go (1)
  • APIServiceExportTemplateInterface (39-51)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/collection.go (1)
  • CollectionInterface (39-51)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/fake/fake_collection.go (4)
sdk/apis/kubebind/v1alpha2/collection_types.go (2)
  • Collection (35-46)
  • CollectionList (89-94)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/fake/fake_kubebind_client.go (1)
  • FakeKubeBindV1alpha2 (27-29)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/collection.go (1)
  • CollectionInterface (39-51)
sdk/apis/kubebind/v1alpha2/register.go (1)
  • SchemeGroupVersion (39-39)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/kubebind_client.go (2)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/apiserviceexporttemplate.go (2)
  • APIServiceExportTemplatesGetter (34-36)
  • APIServiceExportTemplateInterface (39-51)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/collection.go (2)
  • CollectionsGetter (34-36)
  • CollectionInterface (39-51)
backend/kubernetes/manager.go (2)
sdk/apis/kubebind/v1alpha2/collection_types.go (1)
  • CollectionList (89-94)
sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go (1)
  • APIServiceExportTemplate (35-46)
sdk/apis/kubebind/v1alpha2/register.go (2)
sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go (2)
  • APIServiceExportTemplate (35-46)
  • APIServiceExportTemplateList (93-98)
sdk/apis/kubebind/v1alpha2/collection_types.go (2)
  • Collection (35-46)
  • CollectionList (89-94)
sdk/client/informers/externalversions/kubebind/v1alpha2/collection.go (5)
sdk/client/listers/kubebind/v1alpha2/collection.go (2)
  • CollectionLister (30-37)
  • NewCollectionLister (45-47)
sdk/client/informers/externalversions/factory.go (1)
  • SharedInformerFactory (226-258)
sdk/client/informers/externalversions/internalinterfaces/factory_interfaces.go (1)
  • TweakListOptionsFunc (40-40)
sdk/client/informers/externalversions/kubebind/v1alpha2/interface.go (1)
  • Interface (26-43)
sdk/client/clientset/versioned/clientset.go (1)
  • Interface (32-36)
sdk/client/informers/externalversions/kubebind/v1alpha2/apiserviceexporttemplate.go (5)
sdk/client/listers/kubebind/v1alpha2/apiserviceexporttemplate.go (2)
  • APIServiceExportTemplateLister (30-37)
  • NewAPIServiceExportTemplateLister (45-47)
sdk/client/informers/externalversions/factory.go (1)
  • SharedInformerFactory (226-258)
sdk/client/informers/externalversions/internalinterfaces/factory_interfaces.go (1)
  • TweakListOptionsFunc (40-40)
sdk/client/informers/externalversions/kubebind/v1alpha2/interface.go (1)
  • Interface (26-43)
sdk/client/clientset/versioned/clientset.go (1)
  • Interface (32-36)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/fake/fake_apiserviceexporttemplate.go (4)
sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go (2)
  • APIServiceExportTemplate (35-46)
  • APIServiceExportTemplateList (93-98)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/fake/fake_kubebind_client.go (1)
  • FakeKubeBindV1alpha2 (27-29)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/apiserviceexporttemplate.go (1)
  • APIServiceExportTemplateInterface (39-51)
sdk/apis/kubebind/v1alpha2/register.go (1)
  • SchemeGroupVersion (39-39)
sdk/client/informers/externalversions/kubebind/v1alpha2/interface.go (2)
sdk/client/informers/externalversions/kubebind/v1alpha2/apiserviceexporttemplate.go (1)
  • APIServiceExportTemplateInformer (37-40)
sdk/client/informers/externalversions/kubebind/v1alpha2/collection.go (1)
  • CollectionInformer (37-40)
backend/http/handler.go (3)
sdk/apis/kubebind/v1alpha2/apiserviceexport_types.go (1)
  • APIServiceExportResource (83-83)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (3)
  • PermissionClaim (206-213)
  • Namespaces (129-135)
  • APIServiceExportRequestSpec (95-127)
sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go (1)
  • APIServiceExportTemplateList (93-98)
sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go (4)
sdk/apis/third_party/conditions/apis/conditions/v1alpha1/types.go (1)
  • Conditions (92-92)
sdk/apis/kubebind/v1alpha2/boundchema_types.go (1)
  • InformerScope (59-59)
sdk/apis/kubebind/v1alpha2/apiserviceexport_types.go (1)
  • APIServiceExportResource (83-83)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (2)
  • PermissionClaim (206-213)
  • Namespaces (129-135)
sdk/apis/kubebind/v1alpha2/zz_generated.deepcopy.go (4)
sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go (4)
  • APIServiceExportTemplate (35-46)
  • APIServiceExportTemplateList (93-98)
  • APIServiceExportTemplateSpec (57-82)
  • APIServiceExportTemplateStatus (85-88)
sdk/apis/kubebind/v1alpha2/collection_types.go (5)
  • APIServiceExportTemplateReference (72-78)
  • Collection (35-46)
  • CollectionList (89-94)
  • CollectionSpec (57-69)
  • CollectionStatus (81-84)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (3)
  • APIServiceExportRequestResource (137-143)
  • PermissionClaim (206-213)
  • Namespaces (129-135)
sdk/apis/third_party/conditions/apis/conditions/v1alpha1/types.go (1)
  • Conditions (92-92)
sdk/client/listers/kubebind/v1alpha2/collection.go (3)
sdk/apis/kubebind/v1alpha2/collection_types.go (1)
  • Collection (35-46)
sdk/client/listers/kubebind/v1alpha2/expansion_generated.go (2)
  • CollectionListerExpansion (75-75)
  • CollectionNamespaceListerExpansion (79-79)
sdk/apis/kubebind/v1alpha2/register.go (1)
  • Resource (42-44)
sdk/client/listers/kubebind/v1alpha2/apiserviceexporttemplate.go (3)
sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go (1)
  • APIServiceExportTemplate (35-46)
sdk/client/listers/kubebind/v1alpha2/expansion_generated.go (2)
  • APIServiceExportTemplateListerExpansion (43-43)
  • APIServiceExportTemplateNamespaceListerExpansion (47-47)
sdk/apis/kubebind/v1alpha2/register.go (1)
  • Resource (42-44)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/apiserviceexporttemplate.go (5)
sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go (2)
  • APIServiceExportTemplate (35-46)
  • APIServiceExportTemplateList (93-98)
sdk/client/informers/externalversions/kubebind/v1alpha2/interface.go (1)
  • Interface (26-43)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/generated_expansion.go (1)
  • APIServiceExportTemplateExpansion (27-27)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/kubebind_client.go (1)
  • KubeBindV1alpha2Client (42-44)
sdk/client/clientset/versioned/scheme/register.go (1)
  • ParameterCodec (33-33)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/collection.go (4)
sdk/apis/kubebind/v1alpha2/collection_types.go (2)
  • Collection (35-46)
  • CollectionList (89-94)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/generated_expansion.go (1)
  • CollectionExpansion (35-35)
sdk/client/clientset/versioned/typed/kubebind/v1alpha2/kubebind_client.go (1)
  • KubeBindV1alpha2Client (42-44)
sdk/client/clientset/versioned/scheme/register.go (1)
  • ParameterCodec (33-33)
🪛 LanguageTool
docs/content/usage/index.md

[grammar] ~125-~125: Use a hyphen to join words.
Context: ...nd the primary CRDs. ### Label Selector Based Claims Access resources based on ...

(QB_NEW_EN_HYPHEN)

docs/content/usage/migration.md

[grammar] ~94-~94: Ensure spelling is correct
Context: ... ``` ## Step-by-Step Migration ### 1. Backup Existing Resources Before starting mig...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 YAMLlint (1.37.1)
.coderabbit.yaml

[error] 34-34: syntax error: expected ',' or ']', but got ''

(syntax)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: verify
  • GitHub Check: lint
  • GitHub Check: go-test
  • GitHub Check: go-test-e2e
🔇 Additional comments (35)
contrib/kcp/hack/update-kcp-codegen.sh (1)

31-31: LGTM: Preserve resources during KCP codegen.

The --preserve-resources flag ensures that newly introduced APIResourceSchema definitions and CRD resources are retained during code generation, preventing loss of state.

contrib/kcp/deploy/resources/apiresourceschema-apiserviceexportrequests.kube-bind.io.yaml (2)

313-313: LGTM: Field renamed to plural form.

The rename from namedResource to namedResources aligns with the broader API changes across the codebase, standardizing on plural naming for collection fields.


452-452: Verify v1alpha2 is the intended storage version.

Storage version configuration is correct: v1alpha1 has storage: false (line 172) and v1alpha2 has storage: true (line 452), ensuring only one version is designated as storage.

However, the conversion strategy is set to None, meaning no conversion rules exist between versions. If v1alpha1 was the previous storage version with existing objects in the cluster, verify that:

  • A migration strategy exists outside this schema (e.g., kubectl patch, custom controllers)
  • OR v1alpha1 was never the storage version in production clusters

Confirm this aligns with kube-bind v0.6.0 release strategy and that the cluster upgrade path is documented.

docs/content/usage/index.md (1)

1-281: LGTM: Comprehensive usage documentation for kube-bind v0.6.0.

This documentation effectively covers the new Catalog API features, permission claims, provider-side namespace management, and migration guidance. The structure is clear, examples are helpful, and it aligns well with the API changes in this PR.

pkg/resources/resources.go (2)

33-33: LGTM: Field rename reflects API change.

The update from selector.NamedResource to selector.NamedResources is consistent with the plural naming convention adopted across the v1alpha2 API.


55-65: LGTM: Named resources iteration updated.

The logic correctly iterates over the renamed NamedResources field, maintaining the existing matching behavior for name and namespace checks.

deploy/crd/kube-bind.io_apiserviceexports.yaml (1)

567-567: LGTM: CRD schema updated to match API types.

The field rename from namedResource to namedResources in the v1alpha2 CRD schema aligns with the corresponding Go type changes, ensuring validation consistency.

backend/template/resources.gohtml (1)

1-231: LGTM: UI refactored to support module-centric workflow.

The template successfully transitions from a single-export view to a modular, grid-based layout that displays multiple modules with their resources, permissions, and namespaces. Key improvements:

  • Responsive two-column grid for module cards
  • Clear visualization of permissions with collapsible details for NamedResources and LabelSelector
  • Per-module "Bind Module" action aligning with the template-based workflow
  • Professional styling with proper hover states and visual hierarchy

This change aligns well with the Catalog API features (Collections, Modules) introduced in this PR.

contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml (2)

52-62: Schema version updates look correct.

The schema version bumps for apiservicebindings and apiserviceexports follow the established date-based versioning pattern and are consistent with the PR's changes.


75-99: Remove the orphaned catalog.kube-bind.io collections entry or verify if missing CRD definition is required.

Investigation reveals the duplication appears unintentional. Only one collections CRD definition exists in the codebase (./deploy/crd/kube-bind.io_collections.yaml for the kube-bind.io group). The first entry referencing catalog.kube-bind.io collections has no corresponding CRD file and appears to be an orphaned or leftover entry. Either remove it from the export or confirm if a separate catalog.kube-bind.io collections CRD definition is required.

contrib/kcp/deploy/examples/collection-wildwest.yaml (1)

1-10: Well-structured example manifest.

The Collection example is clean and demonstrates the basic usage pattern correctly. The referenced templates (cowboys and sheriffs) align with the broader catalog API changes introduced in this PR.

sdk/client/informers/externalversions/kubebind/v1alpha2/interface.go (1)

33-34: Generated informer code follows correct patterns.

The new informer methods for APIServiceExportTemplates and Collections are properly generated and follow the established patterns in this file. The implementations correctly wire factory, namespace, and tweakListOptions.

Also applies to: 41-42, 71-74, 91-94

sdk/client/informers/externalversions/generic.go (1)

75-76: Generated ForResource switch cases look correct.

The new cases for apiserviceexporttemplates and collections properly follow the existing pattern and correctly wire the resource metadata and informer references.

Also applies to: 83-84

sdk/client/clientset/versioned/typed/kubebind/v1alpha2/generated_expansion.go (1)

27-27: Expansion interfaces correctly generated.

The new APIServiceExportTemplateExpansion and CollectionExpansion interfaces follow the standard Kubernetes client-gen pattern for providing extension points without modifying generated code.

Also applies to: 35-35

sdk/apis/kubebind/v1alpha2/register.go (1)

63-66: Type registration is correct.

The four new types (APIServiceExportTemplate, APIServiceExportTemplateList, Collection, CollectionList) are properly registered with the scheme following the established pattern.

sdk/client/clientset/versioned/typed/kubebind/v1alpha2/fake/fake_apiserviceexporttemplate.go (1)

27-52: Fake client implementation follows Kubernetes patterns correctly.

The generated fake client for APIServiceExportTemplate properly implements the standard Kubernetes fake client pattern using gentype.FakeClientWithList. All metadata, constructors, and list conversion functions are correctly wired.

sdk/apis/kubebind/v1alpha2/collection_types.go (3)

25-46: Collection type definition is well-structured.

The Collection type follows Kubernetes API conventions correctly with proper kubebuilder markers, cluster scope, and standard status subresource support. The design appropriately represents a logical grouping of templates for UI organization.


56-69: CollectionSpec design is reasonable with discussed validation.

The spec design is clean with an optional Description and required Templates list. The MinItems=1 validation on Templates was discussed in past reviews and the decision to keep it is reasonable—a Collection should logically contain at least one template to be meaningful.

Note: Based on past review comments, the team considered future extensibility with label selectors but opted for the simpler reference-by-name approach for now, which is appropriate for an initial implementation.


71-78: Template reference type is appropriately simple.

The APIServiceExportTemplateReference using only a Name field follows standard Kubernetes patterns for referencing resources within the same scope. This is sufficient for the current use case.

contrib/kcp/deploy/examples/template-cowboys.yaml (1)

5-12: Confirm selector semantics and “versions” field name.

  • Does APIServiceExportTemplate allow using both selector.namedResources and selector.labelSelector simultaneously (AND vs OR)? Please confirm expected evaluation.
  • Verify the field is “versions” (array) for resources here; docs examples elsewhere use singular “version”. Aligning across docs/templates would prevent confusion.

Also applies to: 12-22, 23-32

contrib/kcp/deploy/examples/template-sheriffs.yaml (1)

5-12: Template scope and namespace expectations.

  • This manifest omits metadata.namespace; confirm APIServiceExportTemplate is cluster-scoped as assumed.
  • For namespaces provisioning, confirm controller behavior when they already exist (idempotency/ownership labels).

Also applies to: 12-32, 33-35

sdk/client/listers/kubebind/v1alpha2/expansion_generated.go (1)

41-48: LGTM — expansion points correctly added for new resources.

Matches lister-gen conventions; no further action.

Also applies to: 73-79

sdk/client/clientset/versioned/typed/kubebind/v1alpha2/fake/fake_collection.go (1)

33-50: LGTM — fake client wiring uses correct “collections” resource and kind.

Good use of NewFakeClientWithList and slice converters.

sdk/client/informers/externalversions/kubebind/v1alpha2/collection.go (1)

35-40: LGTM — standard generated informer.

sdk/client/clientset/versioned/typed/kubebind/v1alpha2/collection.go (1)

32-36: LGTM — standard generated typed client for Collections.

backend/http/handler.go (1)

386-394: Scope filter semantics — confirm intent.

Condition shows all templates when h.scope == ClusterScope and filters otherwise. If the intention was “Cluster shows both; Namespaced shows only namespaced,” this is correct; otherwise, adjust.

sdk/apis/kubebind/v1alpha2/zz_generated.deepcopy.go (9)

517-548: APIServiceExportTemplateList deepcopy/object are standard and correct.


550-564: APIServiceExportTemplateReference deepcopy is fine (value-only struct).


566-599: APIServiceExportTemplateSpec deep-copies complex slices; shallow-copies Namespaces appropriately.

Resources and PermissionClaims use DeepCopyInto; Namespaces uses copy, which is correct given Namespaces is a simple value struct today.


601-623: APIServiceExportTemplateStatus conditions deepcopy is correct.


1090-1116: Collection runtime.Object deepcopy follows the standard pattern.


1118-1149: CollectionList deepcopy/object look good.


1151-1161: CollectionSpec shallow-copies Templates; OK since APIServiceExportTemplateReference is value-only.


1172-1194: CollectionStatus conditions deepcopy is correct.


489-516: Now I'll generate scripts to locate and inspect the relevant v1alpha2 files to verify the registration:

Deepcopy code is correct; verify type registration if these are CRDs.

The DeepCopy methods are independent and do not require scheme registration since Kubernetes 1.9. The deepcopy patterns in your changes are correct: ObjectMeta uses DeepCopyInto, Spec/Status fields properly use DeepCopyInto, and runtime.Object returns handle nil checks appropriately.

However, if APIServiceExportTemplate and Collection are Custom Resources that need to be usable by controllers or the API server, they should also be registered with SchemeBuilder and included in OpenAPI specs. Verification shows these types are not currently registered. Confirm whether these types require scheme registration for your use case.

Comment thread deploy/crd/kube-bind.io_collections.yaml Outdated
Comment thread sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go
Comment thread sdk/apis/kubebind/v1alpha2/zz_generated.deepcopy.go
Comment thread sdk/client/clientset/versioned/typed/kubebind/v1alpha2/kubebind_client.go Outdated
Comment thread sdk/client/listers/kubebind/v1alpha2/apiserviceexporttemplate.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/http/handler.go (1)

417-453: Validate the template query parameter before use.

The template query parameter is retrieved on line 419 but never validated before being passed to GetTemplates on line 448. An empty or missing template name would likely cause errors downstream.

Apply this diff to add validation:

 func (h *handler) handleBind(w http.ResponseWriter, r *http.Request) {
 	logger := getLogger(r)
 	templateName := r.URL.Query().Get("template")
+	if templateName == "" {
+		logger.Error(errors.New("missing template parameter"), "template parameter is required")
+		http.Error(w, "missing template parameter", http.StatusBadRequest)
+		return
+	}
 	providerCluster := mux.Vars(r)["cluster"]
🧹 Nitpick comments (2)
backend/template/resources.gohtml (1)

14-133: Consider extracting inline CSS to an external stylesheet.

The 119 lines of inline CSS could be extracted to a separate stylesheet for better maintainability, reusability, and testability. However, since this is described as a skeleton implementation, this refactor can be deferred.

backend/http/handler.go (1)

535-548: Consider optimizing template fetching to reduce API calls.

The current implementation makes N+1 API calls (one ListCollections followed by one GetTemplates per template). While acceptable for a skeleton implementation, consider batch-fetching templates in the future to improve performance.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between db0166e and 123f537.

📒 Files selected for processing (4)
  • backend/http/handler.go (5 hunks)
  • backend/template/resources.gohtml (1 hunks)
  • contrib/kcp/README.md (2 hunks)
  • contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-22T13:20:49.952Z
Learnt from: mjudeikis
PR: kube-bind/kube-bind#304
File: sdk/apis/kubebind/v1alpha2/boundchema_types.go:49-0
Timestamp: 2025-09-22T13:20:49.952Z
Learning: In kube-bind, there are two different ResourceGroupName() methods: BoundSchema.ResourceGroupName() for CRDs (always non-empty groups) uses simple fmt.Sprintf formatting, while APIServiceExportRequestResource.ResourceGroupName() for export requests handles empty groups by converting to "core". BoundSchema is exclusively for CRDs which cannot have empty API groups per Kubernetes validation.

Applied to files:

  • contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml
🧬 Code graph analysis (1)
backend/http/handler.go (2)
sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go (5)
  • PermissionClaim (206-213)
  • Namespaces (129-135)
  • APIServiceExportRequestResponse (66-79)
  • NameObjectMeta (81-84)
  • APIServiceExportRequestSpec (95-127)
sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go (1)
  • APIServiceExportTemplateList (93-98)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: lint
  • GitHub Check: verify
  • GitHub Check: go-test-e2e
  • GitHub Check: go-test
🔇 Additional comments (9)
contrib/kcp/README.md (2)

96-104: Prefer kubectl apply for reproducible setup documentation.

The change from kubectl create -f to kubectl apply -f is a best practice improvement. The apply command is idempotent and more appropriate for documentation that may be executed multiple times or used as reference material. ✓


111-111: Cluster URL updates are consistent.

The example cluster URLs have been updated consistently across both the LogicalCluster output (line 111) and the kubectl-bind consumer command (line 127), maintaining documentation coherence. ✓

Also applies to: 127-127

contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml (2)

80-89: Verification complete—schema resources are properly defined.

The APIResourceSchema files for both new resources exist:

  • apiresourceschema-apiserviceexporttemplates.kube-bind.io.yaml
  • apiresourceschema-collections.kube-bind.io.yaml

The schema versions referenced in the APIExport are correctly configured.


52-52: All schema version updates are correctly aligned with corresponding APIResourceSchema definitions.

Verification confirms:

  • Lines 52 & 62: Updated schema identifiers (v251015-f561c7c.apiservicebindings.kube-bind.io and v251015-f561c7c.apiserviceexports.kube-bind.io) match their respective APIResourceSchema resources
  • Lines 80-89: New resources (apiserviceexporttemplates and collections) reference valid schema identifiers (v251020-d1ae972.apiserviceexporttemplates.kube-bind.io and v251020-d1ae972.collections.kube-bind.io) that match their corresponding APIResourceSchema files
backend/template/resources.gohtml (1)

219-221: LGTM: Module bind flow correctly passes template name.

The bind URL correctly passes the module name via the template query parameter, which aligns with the backend's module-centric binding flow.

backend/http/handler.go (4)

344-356: LGTM: UISchema correctly restructured for module-centric workflow.

The UISchema struct has been appropriately refactored from per-resource fields to module-level aggregates (Resources, PermissionClaims, Namespaces arrays), which aligns with the template-based catalog API design.


384-398: LGTM: Template iteration and UISchema construction are correct.

The loop correctly filters templates by scope and constructs UISchema entries with the appropriate module-level fields from the templates.


455-468: LGTM: APIServiceExportRequestResponse construction is correct.

The request object is correctly constructed from the template specification, with proper field mappings for Resources, PermissionClaims, and Namespaces.


447-447: Fix typo in comment.

Line 447 has a typo: "consutruct" should be "construct".

Apply this diff:

-	// Module consist of many resources and permissionClaims. Read it and translate to
+	// Module consists of many resources and permissionClaims. Read it and translate to request.

Likely an incorrect or invalid review comment.

Comment thread backend/http/handler.go
Comment thread backend/http/handler.go
Comment thread backend/template/resources.gohtml
Comment thread contrib/kcp/README.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
docs/content/usage/migration.md (2)

34-37: Fix typo: "mangodb" → "mongodb" (flagged in prior review).

These examples still use the incorrect API group and resource names. This was previously flagged but remains unresolved.

Apply this diff to fix all instances:

--- migration.md (lines 34-36)
- group: mangodb.com
+ group: mongodb.com
  version: v1alpha1
- resource: mangodbs
+ resource: mongodbs

--- migration.md (line 59)
- name: mangodbs-mangodb-com
+ name: mongodbs-mongodb-com

--- migration.md (lines 87-89)
- group: mangodb.com
+ group: mongodb.com
  version: v1alpha1
- resource: mangodbs
+ resource: mongodbs

--- migration.md (lines 143-145)
- group: mangodb.com
+ group: mongodb.com
  version: v1alpha1
- resource: mangodbs
+ resource: mongodbs

--- migration.md (lines 180-182)
- group: mangodb.com
+ group: mongodb.com
  version: v1alpha1
- resource: mangodbs
+ resource: mongodbs

Also applies to: 59-60, 87-90, 143-146, 180-183


94-102: Fix verb form: "backup" → "back up" (flagged in prior review).

The verb form must be two words. This was previously flagged but remains unresolved.

Apply this diff:

- ### 1. Backup Existing Resources
+ ### 1. Back Up Existing Resources

- Before starting migration, backup your existing resources:
+ Before starting migration, back up your existing resources:
  
  ```bash
- # Backup APIServiceExports
+ # Back up APIServiceExports
  kubectl get apiserviceexports -o yaml > apiserviceexports-backup.yaml
  
- # Backup APIServiceBindings
+ # Back up APIServiceBindings
  kubectl get apiservicebindings -o yaml > apiservicebindings-backup.yaml
  
- # Backup bound CRDs
+ # Back up bound CRDs
  kubectl get crds -l kube-bind.io/bound-crd=true -o yaml > bound-crds-backup.yaml

Also applies to: 105-105

cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go (1)

74-107: PollUntilContextCancel is unnecessary and concurrent creates are unhandled

A previous review comment suggested removing wait.PollUntilContextCancel and handling AlreadyExists explicitly (marked as "✅ Addressed"), but the current code still uses it. The Poll always returns true on first iteration (line 104), making it a pointless wrapper. More critically, if two concurrent callers both see NotFound at line 49, both will attempt Create, and the second will fail with AlreadyExists (not handled).

Apply this diff to fix:

-	// Create new APIServiceBinding
-	var created *kubebindv1alpha2.APIServiceBinding
-	if err := wait.PollUntilContextCancel(ctx, 1*time.Second, false, func(ctx context.Context) (bool, error) {
-		created, err = bindClient.KubeBindV1alpha2().APIServiceBindings().Create(ctx, &kubebindv1alpha2.APIServiceBinding{
-			ObjectMeta: metav1.ObjectMeta{
-				Name: bindingName,
-			},
-			Spec: kubebindv1alpha2.APIServiceBindingSpec{
-				KubeconfigSecretRef: kubebindv1alpha2.ClusterSecretKeyRef{
-					LocalSecretKeyRef: kubebindv1alpha2.LocalSecretKeyRef{
-						Name: secretName,
-						Key:  "kubeconfig",
-					},
-					Namespace: "kube-bind",
-				},
-			},
-		}, metav1.CreateOptions{})
-		if err != nil {
-			return false, err
-		}
-
-		// Best effort status update to have "Pending" in the Ready condition
-		conditions.MarkFalse(created,
-			conditionsapi.ReadyCondition,
-			"Pending",
-			conditionsapi.ConditionSeverityInfo,
-			"Pending",
-		)
-		_, _ = bindClient.KubeBindV1alpha2().APIServiceBindings().UpdateStatus(ctx, created, metav1.UpdateOptions{})
-
-		return true, nil
-	}); err != nil {
-		return nil, err
-	}
+	// Create new APIServiceBinding
+	created, err := bindClient.KubeBindV1alpha2().APIServiceBindings().Create(ctx, &kubebindv1alpha2.APIServiceBinding{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: bindingName,
+		},
+		Spec: kubebindv1alpha2.APIServiceBindingSpec{
+			KubeconfigSecretRef: kubebindv1alpha2.ClusterSecretKeyRef{
+				LocalSecretKeyRef: kubebindv1alpha2.LocalSecretKeyRef{
+					Name: secretName,
+					Key:  "kubeconfig",
+				},
+				Namespace: "kube-bind",
+			},
+		},
+	}, metav1.CreateOptions{})
+	if apierrors.IsAlreadyExists(err) {
+		// Concurrent create; fetch existing
+		existing, err := bindClient.KubeBindV1alpha2().APIServiceBindings().Get(ctx, bindingName, metav1.GetOptions{})
+		if err != nil {
+			return nil, err
+		}
+		return []*kubebindv1alpha2.APIServiceBinding{existing}, nil
+	}
+	if err != nil {
+		return nil, err
+	}
+
+	// Best-effort status update
+	conditions.MarkFalse(created,
+		conditionsapi.ReadyCondition,
+		"Pending",
+		conditionsapi.ConditionSeverityInfo,
+		"Pending",
+	)
+	_, _ = bindClient.KubeBindV1alpha2().APIServiceBindings().UpdateStatus(ctx, created, metav1.UpdateOptions{})
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 123f537 and ca928ec.

📒 Files selected for processing (5)
  • backend/kubernetes/resources/resources.go (0 hunks)
  • cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go (2 hunks)
  • docs/content/setup/quickstart.md (1 hunks)
  • docs/content/usage/index.md (1 hunks)
  • docs/content/usage/migration.md (1 hunks)
💤 Files with no reviewable changes (1)
  • backend/kubernetes/resources/resources.go
✅ Files skipped from review due to trivial changes (1)
  • docs/content/setup/quickstart.md
🧰 Additional context used
🧬 Code graph analysis (1)
cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go (5)
sdk/apis/third_party/conditions/util/conditions/getter.go (1)
  • Get (39-51)
cli/pkg/kubectl/base/options.go (1)
  • Options (26-40)
sdk/apis/third_party/conditions/util/conditions/setter.go (1)
  • MarkFalse (120-122)
sdk/apis/third_party/conditions/apis/conditions/v1alpha1/constants.go (1)
  • ReadyCondition (24-24)
sdk/apis/third_party/conditions/apis/conditions/v1alpha1/types.go (1)
  • ConditionSeverityInfo (37-37)
🪛 LanguageTool
docs/content/usage/index.md

[grammar] ~125-~125: Use a hyphen to join words.
Context: ...nd the primary CRDs. ### Label Selector Based Claims Access resources based on ...

(QB_NEW_EN_HYPHEN)

docs/content/usage/migration.md

[grammar] ~94-~94: Ensure spelling is correct
Context: ... ``` ## Step-by-Step Migration ### 1. Backup Existing Resources Before starting mig...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: lint
  • GitHub Check: go-test
  • GitHub Check: verify
  • GitHub Check: go-test-e2e
🔇 Additional comments (3)
docs/content/usage/index.md (1)

61-61: Use hyphens for the compound adjective modifier.

The section heading "Label Selector Based Claims" should follow grammatical rules for compound adjectives preceding nouns.

-### Label Selector Based Claims
+### Label-Selector-Based Claims

Likely an incorrect or invalid review comment.

cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go (2)

47-72: LGTM: Reuse logic correctly validates ownership and secret references

The reuse path properly validates that the existing binding's secret reference matches and that all CRDs are owned by kube-bind before proceeding. The refactoring to use a single binding name per request aligns with the PR's goal of consolidating per-resource bindings into a unified workflow.


109-110: LGTM: Success message accurately reflects unified binding workflow

The message clearly indicates a single binding was created for multiple resources, which aligns with the PR's consolidation of per-resource bindings.

Comment thread docs/content/usage/index.md Outdated
@mjudeikis mjudeikis force-pushed the mjudeikis/catalog.api branch 2 times, most recently from 172a62f to dc93a02 Compare October 23, 2025 06:17
Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
On-behalf-of: @SAP mangirdas.judeikis@sap.com
@mjudeikis mjudeikis force-pushed the mjudeikis/catalog.api branch from dc93a02 to c1dcfc4 Compare October 23, 2025 06:19
@mjudeikis mjudeikis changed the title Add catalogAPI Add CatalogAPI Oct 23, 2025
@mjudeikis mjudeikis requested a review from ntnn October 23, 2025 07:15
Comment thread docs/content/index.md Outdated
Comment thread docs/content/index.md Outdated
Comment thread README.md Outdated
Comment thread README.md Outdated
mjudeikis and others added 2 commits October 23, 2025 17:19
Co-authored-by: Nelo-T. Wallus <10514301+ntnn@users.noreply.github.com>
@mjudeikis mjudeikis merged commit a1d334d into kbind-dev:main Oct 23, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants