Skip to content

Commit 847b9d8

Browse files
authored
Add Openapi spec and STUB endpoint for source_preview (#1884)
Signed-off-by: ppadti <ppadti@redhat.com>
1 parent d3c3924 commit 847b9d8

8 files changed

Lines changed: 280 additions & 0 deletions

File tree

clients/ui/api/openapi/mod-arch.yaml

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,66 @@ paths:
963963
summary: Delete a Model Catalog source
964964
description: Deletes an existing Model Catalog Source.
965965

966+
/api/v1/settings/model_catalog/source_preview:
967+
description: >-
968+
The REST endpoint/path used to preview the effects of catalog source configuration changes.
969+
post:
970+
summary: Preview catalog source configuration effects
971+
description: >-
972+
Accepts catalog source definitions and returns a preview of which models would be
973+
included or excluded based on the configuration. Supports multipart form uploads
974+
for YAML catalogs files.
975+
tags:
976+
- ModelCatalogService
977+
parameters:
978+
- name: statusFilter
979+
description: |-
980+
Filter the response to show specific model statuses.
981+
- `all` shows all models (default)
982+
- `included` shows only models that would be included
983+
- `excluded` shows only models that would be excluded
984+
schema:
985+
type: string
986+
enum:
987+
- all
988+
- included
989+
- excluded
990+
default: all
991+
in: query
992+
required: false
993+
- $ref: "#/components/parameters/pageSize"
994+
- $ref: "#/components/parameters/nextPageToken"
995+
requestBody:
996+
description: Catalog source configuration
997+
required: true
998+
content:
999+
application/json:
1000+
schema:
1001+
$ref: "#/components/schemas/CatalogSourcePreviewRequest"
1002+
multipart/form-data:
1003+
schema:
1004+
type: object
1005+
properties:
1006+
file:
1007+
type: string
1008+
format: yaml
1009+
description:
1010+
type: string
1011+
description:
1012+
Should include a file named `source.json`, and may optionally
1013+
include a YAML catalog. The name referenced in the source
1014+
definition should match uploaded file name.
1015+
responses:
1016+
"200":
1017+
$ref: "#/components/responses/CatalogSourcePreviewResponse"
1018+
"400":
1019+
$ref: "#/components/responses/BadRequest"
1020+
"401":
1021+
$ref: "#/components/responses/Unauthorized"
1022+
"500":
1023+
$ref: "#/components/responses/InternalServerError"
1024+
operationId: previewCatalogSource
1025+
9661026
components:
9671027
schemas:
9681028
Config:
@@ -2085,6 +2145,76 @@ components:
20852145
description: A single filter option.
20862146
additionalProperties:
20872147
$ref: "#/components/schemas/FilterOption"
2148+
CatalogSourcePreviewRequest:
2149+
description: Request to preview catalog source configuration effects.
2150+
type: object
2151+
required:
2152+
- type
2153+
properties:
2154+
type:
2155+
type: string
2156+
description: The type of catalog source (e.g., 'huggingface', 'yaml')
2157+
example: yaml
2158+
includedModels:
2159+
type: array
2160+
items:
2161+
type: string
2162+
excludedModels:
2163+
type: array
2164+
items:
2165+
type: string
2166+
properties:
2167+
type: object
2168+
description: Type-specific configuration properties
2169+
additionalProperties: true
2170+
CatalogSourcePreviewModel:
2171+
description: A model in the preview response with inclusion status.
2172+
type: object
2173+
required:
2174+
- name
2175+
- included
2176+
properties:
2177+
name:
2178+
type: string
2179+
description: Name of the model
2180+
example: microsoft/DialoGPT-medium
2181+
included:
2182+
type: boolean
2183+
description: Whether this model would be included based on the source configuration
2184+
CatalogSourcePreviewResult:
2185+
description: Preview result for catalog source configuration.
2186+
allOf:
2187+
- type: object
2188+
properties:
2189+
items:
2190+
description: Array of models with their inclusion status.
2191+
type: array
2192+
items:
2193+
$ref: "#/components/schemas/CatalogSourcePreviewModel"
2194+
summary:
2195+
description: Summary of the preview results
2196+
type: object
2197+
properties:
2198+
totalModels:
2199+
type: integer
2200+
description: Total number of models evaluated
2201+
example: 1500
2202+
includedModels:
2203+
type: integer
2204+
description: Number of models that would be included
2205+
example: 850
2206+
excludedModels:
2207+
type: integer
2208+
description: Number of models that would be excluded
2209+
example: 650
2210+
required:
2211+
- totalModels
2212+
- includedModels
2213+
- excludedModels
2214+
required:
2215+
- items
2216+
- summary
2217+
- $ref: "#/components/schemas/BaseResourceList"
20882218

20892219
# Schema for catalog settings
20902220
CatalogSourceConfig:
@@ -2501,6 +2631,12 @@ components:
25012631
schema:
25022632
$ref: "#/components/schemas/FilterOptionsList"
25032633
description: A response containing options for a `filterQuery` parameter.
2634+
CatalogSourcePreviewResponse:
2635+
content:
2636+
application/json:
2637+
schema:
2638+
$ref: "#/components/schemas/CatalogSourcePreviewResult"
2639+
description: A response containing the preview results of catalog source configuration effects.
25042640

25052641
# Catalog settings response
25062642
CatalogSourceConfigListResponse:

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ const (
7272
ModelCatalogSettingsPathPrefix = SettingsPath + "/model_catalog"
7373
ModelCatalogSettingsSourceConfigListPath = ModelCatalogSettingsPathPrefix + "/source_configs"
7474
ModelCatalogSettingsSourceConfigPath = ModelCatalogSettingsSourceConfigListPath + "/:" + CatalogSourceId
75+
CatalogSourcePreviewPath = ModelCatalogSettingsPathPrefix + "/source_preview"
7576
)
7677

7778
type App struct {
@@ -286,6 +287,8 @@ func (app *App) Routes() http.Handler {
286287
apiRouter.GET(ModelCatalogSettingsSourceConfigPath, app.AttachNamespace(app.GetCatalogSourceConfigHandler))
287288
apiRouter.PATCH(ModelCatalogSettingsSourceConfigPath, app.AttachNamespace(app.UpdateCatalogSourceConfigHandler))
288289
apiRouter.DELETE(ModelCatalogSettingsSourceConfigPath, app.AttachNamespace(app.DeleteCatalogSourceConfigHandler))
290+
291+
apiRouter.POST(CatalogSourcePreviewPath, app.AttachNamespace(app.AttachModelCatalogRESTClient(app.CreateCatalogSourcePreviewHandler)))
289292
}
290293

291294
// App Router
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package api
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"fmt"
7+
"net/http"
8+
9+
"github.com/julienschmidt/httprouter"
10+
"github.com/kubeflow/model-registry/ui/bff/internal/constants"
11+
"github.com/kubeflow/model-registry/ui/bff/internal/integrations/httpclient"
12+
"github.com/kubeflow/model-registry/ui/bff/internal/models"
13+
)
14+
15+
type CatalogSourcePreviewEnvelope Envelope[*models.CatalogSourcePreviewResult, None]
16+
17+
func (app *App) CreateCatalogSourcePreviewHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
18+
client, ok := r.Context().Value(constants.ModelCatalogHttpClientKey).(httpclient.HTTPClientInterface)
19+
if !ok {
20+
app.serverErrorResponse(w, r, errors.New("catalog REST client not found"))
21+
return
22+
}
23+
24+
var sourcePreviewPayload models.CatalogSourcePreviewRequest
25+
if err := json.NewDecoder(r.Body).Decode(&sourcePreviewPayload); err != nil {
26+
app.serverErrorResponse(w, r, fmt.Errorf("error decoding JSON:: %v", err.Error()))
27+
return
28+
}
29+
30+
sourcePreview, err := app.repositories.ModelCatalogClient.CreateCatalogSourcePreview(client, sourcePreviewPayload)
31+
32+
if err != nil {
33+
app.serverErrorResponse(w, r, err)
34+
}
35+
36+
catalogSourcePreview := CatalogSourcePreviewEnvelope{
37+
Data: sourcePreview,
38+
}
39+
40+
err = app.WriteJSON(w, http.StatusOK, catalogSourcePreview, nil)
41+
if err != nil {
42+
app.serverErrorResponse(w, r, err)
43+
}
44+
}

clients/ui/bff/internal/mocks/model_catalog_client_mock.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,9 @@ func (m *ModelCatalogClientMock) GetCatalogFilterOptions(client httpclient.HTTPC
207207

208208
return &filterOptions, nil
209209
}
210+
211+
func (m *ModelCatalogClientMock) CreateCatalogSourcePreview(client httpclient.HTTPClientInterface, sourcePreviewPaylod models.CatalogSourcePreviewRequest) (*models.CatalogSourcePreviewResult, error) {
212+
catalogSourcePreview := CreateCatalogSourcePreviewMock()
213+
214+
return &catalogSourcePreview, nil
215+
}

clients/ui/bff/internal/mocks/static_data_mock.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,3 +1373,45 @@ func GetCatalogSourceConfigListMock() models.CatalogSourceConfigList {
13731373
Catalogs: allCatalogSourceConfigs,
13741374
}
13751375
}
1376+
1377+
func GetModelsWithInclusionStatusListMocks() []models.CatalogSourcePreviewModel {
1378+
return []models.CatalogSourcePreviewModel{
1379+
{
1380+
Name: "sample-source/granite",
1381+
Included: true,
1382+
},
1383+
{
1384+
Name: "sample-source/model-1",
1385+
Included: true,
1386+
},
1387+
{
1388+
Name: "adminModel1/model-2",
1389+
Included: true,
1390+
},
1391+
{
1392+
Name: "adminModel1/model-3",
1393+
Included: false,
1394+
},
1395+
}
1396+
}
1397+
1398+
func GetCatalogSourcePreviewSummaryMock() models.CatalogSourcePreviewSummary {
1399+
return models.CatalogSourcePreviewSummary{
1400+
TotalModels: 1500,
1401+
IncludedModels: 850,
1402+
ExcludedModels: 650,
1403+
}
1404+
}
1405+
1406+
func CreateCatalogSourcePreviewMock() models.CatalogSourcePreviewResult {
1407+
catalogModelPreview := GetModelsWithInclusionStatusListMocks()
1408+
catalogSourcePreviewSummary := GetCatalogSourcePreviewSummaryMock()
1409+
1410+
return models.CatalogSourcePreviewResult{
1411+
Items: catalogModelPreview,
1412+
Summary: catalogSourcePreviewSummary,
1413+
NextPageToken: "",
1414+
PageSize: int32(10),
1415+
Size: int32(len(catalogModelPreview)),
1416+
}
1417+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package models
2+
3+
type CatalogSourcePreviewRequest struct {
4+
Type string `json:"type"`
5+
IncludedModels []string `json:"includedModels,omitempty"`
6+
ExcludedModels []string `json:"excludedModels,omitempty"`
7+
Properties map[string]interface{} `json:"properties,omitempty"`
8+
}
9+
10+
type CatalogSourcePreviewModel struct {
11+
Name string `json:"name"`
12+
Included bool `json:"included"`
13+
}
14+
15+
type CatalogSourcePreviewSummary struct {
16+
TotalModels int32 `json:"totalModels"`
17+
IncludedModels int32 `json:"includedModels"`
18+
ExcludedModels int32 `json:"excludedModels"`
19+
}
20+
21+
type CatalogSourcePreviewResult struct {
22+
Items []CatalogSourcePreviewModel `json:"items"`
23+
Summary CatalogSourcePreviewSummary `json:"summary"`
24+
NextPageToken string `json:"nextPageToken"`
25+
PageSize int32 `json:"pageSize"`
26+
Size int32 `json:"size"`
27+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package repositories
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/kubeflow/model-registry/ui/bff/internal/integrations/httpclient"
7+
"github.com/kubeflow/model-registry/ui/bff/internal/models"
8+
)
9+
10+
type CatalogSourcePreviewInterface interface {
11+
CreateCatalogSourcePreview(client httpclient.HTTPClientInterface, sourcePreviewPaylod models.CatalogSourcePreviewRequest) (*models.CatalogSourcePreviewResult, error)
12+
}
13+
14+
type CatalogSourcePreview struct {
15+
CatalogSourcePreviewInterface
16+
}
17+
18+
func (a CatalogSourcePreview) CreateCatalogSourcePreview(client httpclient.HTTPClientInterface, sourcePreviewPaylod models.CatalogSourcePreviewRequest) (*models.CatalogSourcePreviewResult, error) {
19+
return nil, fmt.Errorf("not implemented yet")
20+
}

clients/ui/bff/internal/repositories/model_catalog_client.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import (
77
type ModelCatalogClientInterface interface {
88
CatalogSourcesInterface
99
CatalogModelsInterface
10+
CatalogSourcePreviewInterface
1011
}
1112

1213
type ModelCatalogClient struct {
1314
logger *slog.Logger
1415
CatalogSources
1516
CatalogModels
17+
CatalogSourcePreview
1618
}
1719

1820
func NewModelCatalogClient(logger *slog.Logger) (ModelCatalogClientInterface, error) {

0 commit comments

Comments
 (0)