Skip to content

Commit 85570ca

Browse files
committed
feat: adapt the code to upstream
Signed-off-by: lucferbux <[email protected]>
1 parent 666de2c commit 85570ca

File tree

8 files changed

+14
-1650
lines changed

8 files changed

+14
-1650
lines changed

clients/ui/bff/internal/redhat/docs/extensions.md renamed to clients/ui/bff/docs/extensions.md

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Some downstream builds (for example, the RHOAI dashboard) need to add behavior t
1111
## Ownership boundaries
1212

1313
- **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/redhat` (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.
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.
1515
- **Shared interfaces** (for example repository interfaces or the handler override registry itself) stay upstream. Only implementers that are specific to a vendor move downstream.
1616

1717
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.
@@ -54,7 +54,7 @@ func overrideModelRegistrySettingsList(app *api.App, _ func() httprouter.Handle)
5454
}
5555

5656
// Use the client to fetch data from Kubernetes and build the response.
57-
// Downstream repositories live in internal/redhat/repositories.
57+
// Downstream repositories live in internal/<override-repository>/repositories.
5858
_ = client // placeholder for actual implementation
5959

6060
resp := api.ModelRegistrySettingsListEnvelope{Data: nil}
@@ -69,27 +69,15 @@ Package registration is purely compile-time: add a blank import in `clients/ui/b
6969

7070
## Managing downstream overrides
7171

72-
- **Structure** – Place handler factories below `clients/ui/bff/internal/redhat/handlers`, and keep any repository or helper implementations under `clients/ui/bff/internal/redhat/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/redhat/handlers"`) in the main entry point to enable them. No configuration flags are needed.
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.
7474
- **Conditional delegation** – If an override needs to fall back to upstream logic under certain conditions, call `buildDefault()`. Otherwise, the downstream handler runs unconditionally.
7575
- **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.
7676
- **Testing** – Keep unit and integration tests downstream next to the overrides. Use the upstream interfaces to mock dependencies the same way default handlers do.
7777

7878
## Change workflow
7979

8080
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/redhat`. Register them in the package `init()` by calling `api.RegisterHandlerOverride`.
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`.
8282
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.
8383
4. **Document and test** – update this guide when extending coverage, and add downstream tests to catch regressions before shipping.
84-
85-
## Current coverage
86-
87-
| Handler ID | Path |
88-
|------------|------|
89-
| `modelRegistrySettings:list` | `GET /api/v1/settings/model_registry` |
90-
| `modelRegistrySettings:create` | `POST /api/v1/settings/model_registry` |
91-
| `modelRegistrySettings:get` | `GET /api/v1/settings/model_registry/:model_registry_id` |
92-
| `modelRegistrySettings:update` | `PATCH /api/v1/settings/model_registry/:model_registry_id` |
93-
| `modelRegistrySettings:delete` | `DELETE /api/v1/settings/model_registry/:model_registry_id` |
94-
95-
Additions follow the same pattern: declare a `HandlerID` constant, wrap the router registration with `app.handlerWithOverride`, and document the new ID here so downstream authors know it is available.

clients/ui/bff/internal/api/app.go

Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,6 @@ const (
7575
CatalogSourcePreviewPath = ModelCatalogSettingsPathPrefix + "/source_preview"
7676
)
7777

78-
const (
79-
// TODO(upstream): Keep handler IDs unexported so the extension mechanism stays agnostic of downstream overrides.
80-
handlerModelRegistrySettingsListID HandlerID = "modelRegistrySettings:list"
81-
handlerModelRegistrySettingsCreateID HandlerID = "modelRegistrySettings:create"
82-
handlerModelRegistrySettingsGetID HandlerID = "modelRegistrySettings:get"
83-
handlerModelRegistrySettingsUpdateID HandlerID = "modelRegistrySettings:update"
84-
handlerModelRegistrySettingsDeleteID HandlerID = "modelRegistrySettings:delete"
85-
)
86-
8778
type App struct {
8879
config config.EnvConfig
8980
logger *slog.Logger
@@ -260,36 +251,11 @@ func (app *App) Routes() http.Handler {
260251
// SettingsPath endpoints are used to manage the model registry settings and create new model registries
261252
// We are still discussing the best way to create model registries in the community
262253
// But in the meantime, those endpoints are STUBs endpoints used to unblock the frontend development
263-
apiRouter.GET(
264-
ModelRegistrySettingsListPath,
265-
app.handlerWithOverride(handlerModelRegistrySettingsListID, func() httprouter.Handle {
266-
return app.AttachNamespace(app.GetAllModelRegistriesSettingsHandler)
267-
}),
268-
)
269-
apiRouter.POST(
270-
ModelRegistrySettingsListPath,
271-
app.handlerWithOverride(handlerModelRegistrySettingsCreateID, func() httprouter.Handle {
272-
return app.AttachNamespace(app.CreateModelRegistrySettingsHandler)
273-
}),
274-
)
275-
apiRouter.GET(
276-
ModelRegistrySettingsPath,
277-
app.handlerWithOverride(handlerModelRegistrySettingsGetID, func() httprouter.Handle {
278-
return app.AttachNamespace(app.GetModelRegistrySettingsHandler)
279-
}),
280-
)
281-
apiRouter.PATCH(
282-
ModelRegistrySettingsPath,
283-
app.handlerWithOverride(handlerModelRegistrySettingsUpdateID, func() httprouter.Handle {
284-
return app.AttachNamespace(app.UpdateModelRegistrySettingsHandler)
285-
}),
286-
)
287-
apiRouter.DELETE(
288-
ModelRegistrySettingsPath,
289-
app.handlerWithOverride(handlerModelRegistrySettingsDeleteID, func() httprouter.Handle {
290-
return app.AttachNamespace(app.DeleteModelRegistrySettingsHandler)
291-
}),
292-
)
254+
apiRouter.GET(ModelRegistrySettingsListPath, app.AttachNamespace(app.GetAllModelRegistriesSettingsHandler))
255+
apiRouter.POST(ModelRegistrySettingsListPath, app.AttachNamespace(app.CreateModelRegistrySettingsHandler))
256+
apiRouter.GET(ModelRegistrySettingsPath, app.AttachNamespace(app.GetModelRegistrySettingsHandler))
257+
apiRouter.PATCH(ModelRegistrySettingsPath, app.AttachNamespace(app.UpdateModelRegistrySettingsHandler))
258+
apiRouter.DELETE(ModelRegistrySettingsPath, app.AttachNamespace(app.DeleteModelRegistrySettingsHandler))
293259

294260
//SettingsPath: Certificate endpoints
295261
apiRouter.GET(CertificatesPath, app.AttachNamespace(app.GetCertificatesHandler))

clients/ui/bff/internal/api/extensions.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func RegisterHandlerOverride(id HandlerID, factory HandlerFactory) {
3030
handlerOverrides[id] = factory
3131
}
3232

33+
//nolint:unused // Used by downstream implementations
3334
func getHandlerOverride(id HandlerID) HandlerFactory {
3435
handlerOverrideMu.RLock()
3536
defer handlerOverrideMu.RUnlock()
@@ -38,6 +39,8 @@ func getHandlerOverride(id HandlerID) HandlerFactory {
3839

3940
// handlerWithOverride returns the handler registered for the given id or builds the default one.
4041
// TODO(upstream): This glue stays upstream so the router keeps working even when no downstream overrides exist.
42+
//
43+
//nolint:unused // Used by downstream implementations
4144
func (app *App) handlerWithOverride(id HandlerID, buildDefault func() httprouter.Handle) httprouter.Handle {
4245
if factory := getHandlerOverride(id); factory != nil {
4346
app.logHandlerOverride(id)
@@ -46,6 +49,7 @@ func (app *App) handlerWithOverride(id HandlerID, buildDefault func() httprouter
4649
return buildDefault()
4750
}
4851

52+
//nolint:unused // Used by downstream implementations
4953
func (app *App) logHandlerOverride(id HandlerID) {
5054
if app == nil || app.logger == nil {
5155
return

0 commit comments

Comments
 (0)