Skip to content

feat(catalog): add plugin infrastructure for extensible catalog types#2663

Open
Al-Pragliola wants to merge 1 commit intokubeflow:mainfrom
Al-Pragliola:al-pragliola-plugins-phase-2
Open

feat(catalog): add plugin infrastructure for extensible catalog types#2663
Al-Pragliola wants to merge 1 commit intokubeflow:mainfrom
Al-Pragliola:al-pragliola-plugins-phase-2

Conversation

@Al-Pragliola
Copy link
Copy Markdown
Contributor

Description

Introduces catalog/pkg/plugin/ — the core building blocks that allow different catalog types (models, MCP servers, datasets, etc.) to register themselves and be managed by a unified server.

This package provides:

  • CatalogPlugin interface — standard contract for all catalog plugins: identity (Name, Version, Description), lifecycle (Init, Start, Stop, Healthy), HTTP routing (RegisterRoutes), and database migrations (Migrations).
  • Optional interfacesBasePathProvider (custom API base path), SourceKeyProvider (custom config key), FlagProvider (CLI flag registration).
  • Global registry — thread-safe singleton with init()-based self-registration, deterministic iteration order, and duplicate detection (panics on conflict).
  • Config loading — thin delegation to basecatalog.ReadSourceConfig(), supporting single and multi-file loading.

Why catalog/pkg/plugin/ instead of pkg/catalog/plugin/

The original plan placed the package at the repo root (pkg/catalog/plugin/). During implementation we hit Go's internal package visibility rule: code under pkg/ at the repo root cannot import catalog/internal/... because internal packages are only visible to code rooted in their parent tree.

This matters because the plugin config layer needs basecatalog.SourceConfig and basecatalog.ReadSourceConfig() from catalog/internal/catalog/basecatalog/. Rather than re-implementing ~200 lines of config parsing, YAML schema handling, and deprecated-field merging, we moved the package into the catalog/ module tree where the import is valid. This keeps a single source of truth for config parsing and ensures plugin tests exercise the exact same code paths as the production catalog server.

What's NOT included (by design)

  • Server orchestration (server.go) — plugin discovery, lifecycle management, and config routing are a follow-up ticket. This PR establishes the contract; the server wires it together.
  • Config decouplingConfig.SourceConfig currently carries *basecatalog.SourceConfig directly. Full decoupling (plugin-defined config types with raw YAML routing) is a server orchestration concern, documented in the code.

How Has This Been Tested?

go test ./pkg/plugin/ -v       # 13/13 pass
go vet ./pkg/plugin/           # clean

Merge criteria:

  • All the commits have been signed-off (To pass the DCO check)
  • The commits have meaningful messages
  • Automated tests are provided as part of the PR for major new functionalities; testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
  • The developer has manually tested the changes and verified that the changes work.
  • Code changes follow the kubeflow contribution guidelines.
  • For first time contributors: Please reach out to the Reviewers to ensure all tests are being run, ensuring the label ok-to-test has been added to the PR.

Introduce catalog/pkg/plugin/ with the core building blocks for
plugin-based catalog extensibility: CatalogPlugin interface, global
registry with init()-based self-registration, and config loading
that delegates to basecatalog's parser.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Alessio Pragliola <seth.pro@gmail.com>
@google-oss-prow google-oss-prow Bot requested review from chambridge and fege April 30, 2026 15:42
@google-oss-prow
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from al-pragliola. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Copy link
Copy Markdown
Member

@pboyd pboyd left a comment

Choose a reason for hiding this comment

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

I had a few comments, but it looks good.

pkg normally implies an external interface, would we want to support external plugins? If not, maybe catalog/internal/plugin would be more appropriate.

return result
}

// Get returns a plugin by name, or nil if not found.
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.

Suggested change
// Get returns a plugin by name, or nil if not found.
// Get returns a plugin by name, or nil if not found. The returned boolean will be true if the plugin is found, and false otherwise.

for _, path := range paths {
cfg, err := LoadConfig(path)
if err != nil {
return nil, err
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.

Unless LoadConfig includes it, it would be helpful to include the file that failed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants