You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Refactor Kubernetes Client Factory and Introduce Red Hat Extensions
- Added a new function `NewKubernetesClientFactory` to handle client creation based on authentication method.
- Introduced a new markdown file for documenting BFF handler extensions for downstream builds.
- Implemented handler overrides for Model Registry Settings to support Red Hat-specific behavior.
- Created a new repository for Model Registry Settings with Kubernetes integration.
- Added methods for CRUD operations on Model Registry settings, including handling database secrets.
- Implemented conversion functions for unstructured Kubernetes objects to strongly typed models.
- Ensured that all new functionality adheres to existing interfaces and maintains backward compatibility.
feat: adapt the code to upstream
Signed-off-by: lucferbux <[email protected]>
Some downstream builds (for example, the RHOAI dashboard) need to add behavior that does not belong upstream yet. Instead of maintaining long-lived forks, the BFF now exposes a simple extension registry so downstream code can override individual handlers while reusing the rest of the stack.
4
+
5
+
## Core concepts
6
+
7
+
-**Handler IDs** – Each overridable endpoint exposes a stable `HandlerID` constant (see `internal/api/extensions.go`). Model Registry Settings routes are wired first.
8
+
-**Factories** – Downstream packages call `api.RegisterHandlerOverride(id, factory)` inside `init()`. Factories receive the `*api.App` plus the default handler builder, so you can either replace the handler entirely or fall back to upstream logic.
9
+
-**Dependencies** – The `App` exposes read-only accessors for configuration, repositories, and the Kubernetes client factory. It also exposes helper methods such as `BadRequest`, `ServerError`, and `WriteJSON` so overrides can follow the same conventions as upstream handlers.
10
+
11
+
## Ownership boundaries
12
+
13
+
-**Upstream-only artifacts** live under `internal/api`, `internal/repositories`, and the default handler tree. These packages must remain vendor-neutral and keep their existing contracts intact so downstream imports keep compiling.
14
+
-**Downstream-only artifacts** live under `clients/ui/bff/internal/<override-folder>` (and sibling vendor folders, if they are ever added). Any logic that assumes Red Hat credentials, namespaces, or controllers must stay here so other distributions do not pick it up accidentally.
15
+
-**Shared interfaces** (for example repository interfaces or the handler override registry itself) stay upstream. Only implementers that are specific to a vendor move downstream.
16
+
17
+
Use this rule of thumb: if a change requires Red Hat-only RBAC, Kubernetes resources, or APIs that are invisible to open-source users, keep it downstream. Everything else should be proposed upstream.
Package registration is purely compile-time: add a blank import in `clients/ui/bff/cmd/main.go` for the downstream handlers package. When the package is imported, overrides registered in `init()` are automatically active—no configuration flags required. The `buildDefault` parameter is available if an override needs to delegate to upstream logic conditionally.
69
+
70
+
## Managing downstream overrides
71
+
72
+
-**Structure** – Place handler factories below `clients/ui/bff/internal/<override-folder>/handlers`, and keep any repository or helper implementations under `clients/ui/bff/internal/<override-folder>/repositories`. This mirrors the upstream layout so the APIs remain familiar.
73
+
-**Activation** – Overrides are active whenever their package is imported. Use a blank import (e.g., `_ "github.com/.../internal/<override-folder>/handlers"`) in the main entry point to enable them. No configuration flags are needed.
74
+
-**Conditional delegation** – If an override needs to fall back to upstream logic under certain conditions, call `buildDefault()`. Otherwise, the downstream handler runs unconditionally.
75
+
-**Shared clients** – Build Kubernetes or database clients via `app.KubernetesClientFactory()` or other upstream factories. Never duplicate client configuration downstream; add capabilities to the upstream factory instead when needed.
76
+
-**Testing** – Keep unit and integration tests downstream next to the overrides. Use the upstream interfaces to mock dependencies the same way default handlers do.
77
+
78
+
## Change workflow
79
+
80
+
1.**Add the handler ID upstream** – introduce a new `HandlerID` constant and wrap the router registration with `app.handlerWithOverride`. Document the ID in this file under *Current coverage*.
81
+
2.**Introduce downstream logic** – implement handler factories (and any supporting repositories) under `clients/ui/bff/internal/<override-folder>`. Register them in the package `init()` by calling `api.RegisterHandlerOverride`.
82
+
3.**Wire repositories** – if the downstream handler needs bespoke storage logic, implement a downstream repository that satisfies the upstream interface and expose it via `app.Repositories()` overrides.
83
+
4.**Document and test** – update this guide when extending coverage, and add downstream tests to catch regressions before shipping.
0 commit comments