Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] main from kubeflow:main #156

Merged
merged 16 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
20c04c7
build(deps): bump k8s.io/apimachinery from 0.31.3 to 0.31.4 in /clien…
dependabot[bot] Dec 11, 2024
1449fb3
feat(bff): user info endpoint (#630)
ederign Dec 11, 2024
6fe5f35
bump @typescript-eslint/parser and @typescript-eslint/eslint-plugin f…
ederign Dec 11, 2024
b046764
build(deps-dev): bump react-router-dom and react-router from 6.28.0 …
ederign Dec 11, 2024
e599cda
build(deps-dev): bump typescript from 5.6.3 to 5.7.2 in /clients/ui/f…
dependabot[bot] Dec 11, 2024
2fb4d26
Improve username logic and add navbar elements (#641)
lucferbux Dec 13, 2024
8dd89af
feat(bff): update bff service filtering to match model registry servi…
ederign Dec 13, 2024
ba333d7
Add support for env variables in the frontend (#642)
lucferbux Dec 13, 2024
f6feaeb
build(deps): bump dompurify and @types/dompurify in /clients/ui/front…
dependabot[bot] Dec 16, 2024
630044c
build(deps-dev): bump webpack from 5.96.1 to 5.97.1 in /clients/ui/fr…
dependabot[bot] Dec 16, 2024
c22875e
build(deps-dev): bump webpack-dev-server from 5.1.0 to 5.2.0 in /clie…
dependabot[bot] Dec 16, 2024
0938adb
Prepare dashboard for env variables (#645)
lucferbux Dec 16, 2024
1f7b925
build(deps): bump helm/kind-action from 1.10.0 to 1.11.0 (#646)
dependabot[bot] Dec 16, 2024
a861d08
build(deps-dev): bump ruff from 0.8.2 to 0.8.3 in /clients/python (#647)
dependabot[bot] Dec 16, 2024
6c40612
build(deps-dev): bump pytest-asyncio from 0.24.0 to 0.25.0 in /client…
dependabot[bot] Dec 16, 2024
f56a131
build(deps): bump golang.org/x/crypto from 0.26.0 to 0.31.0 (#643)
dependabot[bot] Dec 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-image-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
IMG_VERSION: ${{ steps.tags.outputs.tag }}
run: make image/build
- name: Start Kind Cluster
uses: helm/kind-action@v1.10.0
uses: helm/kind-action@v1.11.0
with:
node_image: "kindest/node:v1.27.11"
- name: Load Local Registry Test Image
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/csi-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
run: make image/build

- name: Start KinD cluster
uses: helm/kind-action@v1.10.0
uses: helm/kind-action@v1.11.0
with:
node_image: "kindest/node:v1.27.11"

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ jobs:
IMG_VERSION: ${{ steps.tags.outputs.tag }}
run: make image/build
- name: Start Kind Cluster
uses: helm/kind-action@v1.10.0
uses: helm/kind-action@v1.11.0
with:
node_image: "kindest/node:v1.27.11"
cluster_name: chart-testing-py-${{ matrix.python }}
Expand Down
52 changes: 26 additions & 26 deletions clients/python/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion clients/python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ coverage = { extras = ["toml"], version = "^7.3.2" }
pytest-cov = ">=4.1,<7.0"
ruff = ">=0.5.2,<0.9.0"
mypy = "^1.7.0"
pytest-asyncio = ">=0.23.7,<0.25.0"
pytest-asyncio = ">=0.23.7,<0.26.0"
requests = "^2.32.2"
black = "^24.4.2"
types-python-dateutil = "^2.9.0.20240906"
Expand Down
34 changes: 29 additions & 5 deletions clients/ui/api/openapi/mod-arch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ paths:
operationId: healthcheck
summary: HealthCheck
description: HealthCheck endpoint.
/api/v1/config:
summary: Path used to manage Configuration information regarding the UI.
/api/v1/user:
summary: Path used to Retrieve a user based on the header.
description: >-
The REST endpoint/path used pass all the config information needed for the UI.
get:
tags:
- K8SOperation
parameters:
- $ref: "#/components/parameters/kubeflowUserId"
responses:
"200":
$ref: "#/components/responses/ConfigResponse"
Expand All @@ -49,6 +51,8 @@ paths:
get:
tags:
- K8SOperation
parameters:
- $ref: "#/components/parameters/kubeflowUserId"
responses:
"200":
$ref: "#/components/responses/ModelRegistryRespone"
Expand All @@ -68,6 +72,7 @@ paths:
- ModelRegistryService
parameters:
- $ref: "#/components/parameters/modelRegistryName"
- $ref: "#/components/parameters/kubeflowUserId"
responses:
"200":
$ref: "#/components/responses/ModelVersionResponse"
Expand Down Expand Up @@ -112,6 +117,7 @@ paths:
description: Updates an existing `ModelVersion`.
parameters:
- $ref: "#/components/parameters/modelRegistryName"
- $ref: "#/components/parameters/kubeflowUserId"
- name: modelversionId
description: A unique identifier for a `ModelVersion`.
schema:
Expand All @@ -131,6 +137,7 @@ paths:
- $ref: "#/components/parameters/orderBy"
- $ref: "#/components/parameters/sortOrder"
- $ref: "#/components/parameters/nextPageToken"
- $ref: "#/components/parameters/kubeflowUserId"
responses:
"200":
$ref: "#/components/responses/RegisteredModelListResponse"
Expand Down Expand Up @@ -159,6 +166,7 @@ paths:
- ModelRegistryService
parameters:
- $ref: "#/components/parameters/modelRegistryName"
- $ref: "#/components/parameters/kubeflowUserId"
responses:
"201":
$ref: "#/components/responses/RegisteredModelResponse"
Expand All @@ -180,6 +188,7 @@ paths:
- ModelRegistryService
parameters:
- $ref: "#/components/parameters/modelRegistryName"
- $ref: "#/components/parameters/kubeflowUserId"
responses:
"200":
$ref: "#/components/responses/RegisteredModelResponse"
Expand Down Expand Up @@ -224,6 +233,7 @@ paths:
description: Updates an existing `RegisteredModel`.
parameters:
- $ref: "#/components/parameters/modelRegistryName"
- $ref: "#/components/parameters/kubeflowUserId"
- name: registeredmodelId
description: A unique identifier for a `RegisteredModel`.
schema:
Expand All @@ -245,6 +255,7 @@ paths:
- $ref: "#/components/parameters/orderBy"
- $ref: "#/components/parameters/sortOrder"
- $ref: "#/components/parameters/nextPageToken"
- $ref: "#/components/parameters/kubeflowUserId"
responses:
"200":
$ref: "#/components/responses/ArtifactListResponse"
Expand Down Expand Up @@ -274,6 +285,7 @@ paths:
- ModelRegistryService
parameters:
- $ref: "#/components/parameters/modelRegistryName"
- $ref: "#/components/parameters/kubeflowUserId"
responses:
"200":
$ref: "#/components/responses/ArtifactResponse"
Expand Down Expand Up @@ -311,6 +323,7 @@ paths:
- $ref: "#/components/parameters/orderBy"
- $ref: "#/components/parameters/sortOrder"
- $ref: "#/components/parameters/nextPageToken"
- $ref: "#/components/parameters/kubeflowUserId"
responses:
"200":
$ref: "#/components/responses/ModelVersionListResponse"
Expand Down Expand Up @@ -355,6 +368,7 @@ paths:
description: Creates a new instance of a `ModelVersion`.
parameters:
- $ref: "#/components/parameters/modelRegistryName"
- $ref: "#/components/parameters/kubeflowUserId"
- name: registeredmodelId
description: A unique identifier for a `RegisteredModel`.
schema:
Expand All @@ -365,12 +379,16 @@ components:
schemas:
Config:
required:
- username
- userId
- clusterAdmin
type: object
properties:
username:
userId:
type: string
example: username-1
example: [email protected]
clusterAdmin:
type: boolean
example: true
ModelRegistry:
required:
- name
Expand Down Expand Up @@ -1193,6 +1211,12 @@ components:
$ref: "#/components/schemas/ServeModel"
description: A response containing a `ServeModel` entity.
parameters:
kubeflowUserId:
in: header
name: kubeflow-userid
schema:
type: string
required: true
modelRegistryName:
name: modelRegistryName
description: Name of the Model Registry selected.
Expand Down
40 changes: 40 additions & 0 deletions clients/ui/bff/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ make docker-build
| URL Pattern | Handler | Action |
|----------------------------------------------------------------------------------------------|----------------------------------------------|-------------------------------------------------------------|
| GET /v1/healthcheck | HealthcheckHandler | Show application information. |
| GET /v1/user | UserHandler | Show "kubeflow-user-id" from header information. |
| GET /v1/model_registry | ModelRegistryHandler | Get all model registries, |
| GET /v1/model_registry/{model_registry_id}/registered_models | GetAllRegisteredModelsHandler | Gets a list of all RegisteredModel entities. |
| POST /v1/model_registry/{model_registry_id}/registered_models | CreateRegisteredModelHandler | Create a RegisteredModel entity. |
Expand All @@ -78,6 +79,10 @@ You will need to inject your requests with a kubeflow-userid header for authoriz
curl -i -H "kubeflow-userid: [email protected]" localhost:4000/api/v1/healthcheck
```
```
# GET /v1/user
curl -i -H "kubeflow-userid: [email protected]" localhost:4000/api/v1/user
```
```
# GET /v1/model_registry
curl -i -H "kubeflow-userid: [email protected]" localhost:4000/api/v1/model_registry
```
Expand Down Expand Up @@ -211,3 +216,38 @@ curl -i -H "kubeflow-userid: [email protected]" "http://localhost:4000/api/v1/mod
# Get with a page size of 5, order by last update time in descending order.
curl -i -H "kubeflow-userid: [email protected]" "http://localhost:4000/api/v1/model_registry/model-registry/registered_models?pageSize=5&orderBy=LAST_UPDATE_TIME&sortOrder=DESC"
```


### FAQ

#### 1. How do we filter model registry services from other Kubernetes services?

We filter Model Registry services by using the Kubernetes label `component: model-registry. This label helps distinguish Model Registry services from other services in the cluster.

For example, in our service manifest, the `component label is defined as follows:
```yaml
# ...
labels:
# ...
component: model-registry
#...
```
You can view the complete Model Registry service manifest [here](https://github.com/kubeflow/model-registry/blob/main/manifests/kustomize/base/model-registry-service.yaml#L10).

#### 2. What is the structure of the mock Kubernetes environment?

The mock Kubernetes environment is activated when the environment variable `MOCK_K8S_CLIENT` is set to `true`. It is based on `env-test` and is designed to simulate a realistic Kubernetes setup for testing. The mock has the following characteristics:

- **Namespaces**:
- `kubeflow`
- `dora-namespace`

- **Users**:
- `[email protected]` (has `cluster-admin` privileges)
- `[email protected]` (restricted to the `dora-namespace`)

- **Services (Model Registries)**:
- `model-registry`: resides in the `kubeflow` namespace with the label `component: model-registry`.
- `model-registry-dora`: resides in the `dora-namespace` namespace with the label `component: model-registry`.
- `model-registry-bella`: resides in the `kubeflow` namespace with the label `component: model-registry`.
- `non-model-registry`: resides in the `kubeflow` namespace *without* the label `component: model-registry`.
2 changes: 1 addition & 1 deletion clients/ui/bff/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/onsi/gomega v1.35.1
github.com/stretchr/testify v1.9.0
k8s.io/api v0.31.2
k8s.io/apimachinery v0.31.3
k8s.io/apimachinery v0.31.4
k8s.io/client-go v0.31.2
sigs.k8s.io/controller-runtime v0.19.1
)
Expand Down
4 changes: 2 additions & 2 deletions clients/ui/bff/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,8 @@ k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0=
k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk=
k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk=
k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk=
k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4=
k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/apimachinery v0.31.4 h1:8xjE2C4CzhYVm9DGf60yohpNUh5AEBnPxCryPBECmlM=
k8s.io/apimachinery v0.31.4/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc=
k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
Expand Down
2 changes: 2 additions & 0 deletions clients/ui/bff/internal/api/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const (
ModelVersionId = "model_version_id"
ModelArtifactId = "model_artifact_id"
HealthCheckPath = PathPrefix + "/healthcheck"
UserPath = PathPrefix + "/user"
ModelRegistryListPath = PathPrefix + "/model_registry"
ModelRegistryPath = ModelRegistryListPath + "/:" + ModelRegistryId
RegisteredModelListPath = ModelRegistryPath + "/registered_models"
Expand Down Expand Up @@ -103,6 +104,7 @@ func (app *App) Routes() http.Handler {
router.POST(ModelVersionArtifactListPath, app.AttachRESTClient(app.CreateModelArtifactByModelVersionHandler))

// Kubernetes client routes
router.GET(UserPath, app.UserHandler)
router.GET(ModelRegistryListPath, app.ModelRegistryHandler)
router.PATCH(ModelRegistryPath, app.AttachRESTClient(app.UpdateModelVersionHandler))

Expand Down
6 changes: 6 additions & 0 deletions clients/ui/bff/internal/api/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ func (app *App) RequireAccessControl(next http.Handler) http.Handler {
return
}

// Skip SAR for user info
if r.URL.Path == UserPath {
next.ServeHTTP(w, r)
return
}

user := r.Header.Get(kubeflowUserId)
if user == "" {
app.forbiddenResponse(w, r, "missing kubeflow-userid header")
Expand Down
Loading
Loading