From c8b20800b6648696cfb7c0bd7b7dfc3ec1b51073 Mon Sep 17 00:00:00 2001 From: Danny Chiao Date: Sat, 14 May 2022 14:06:15 -0400 Subject: [PATCH 1/4] fix: Fix issue when user specifies a port for feast ui Signed-off-by: Danny Chiao --- sdk/python/feast/ui/public/projects-list.json | 11 +++++ sdk/python/feast/ui/src/index.tsx | 18 ++------ sdk/python/feast/ui_server.py | 42 +++++++++++-------- 3 files changed, 40 insertions(+), 31 deletions(-) create mode 100644 sdk/python/feast/ui/public/projects-list.json diff --git a/sdk/python/feast/ui/public/projects-list.json b/sdk/python/feast/ui/public/projects-list.json new file mode 100644 index 00000000000..b6e79bda5b8 --- /dev/null +++ b/sdk/python/feast/ui/public/projects-list.json @@ -0,0 +1,11 @@ +{ + "projects": [ + { + "name": "Project", + "description": "Test project", + "id": "project_id", + "registryPath": "http://0.0.0.0:8888/registry" + } + ] + } + \ No newline at end of file diff --git a/sdk/python/feast/ui/src/index.tsx b/sdk/python/feast/ui/src/index.tsx index 4191de17a06..9ddacc9b48a 100644 --- a/sdk/python/feast/ui/src/index.tsx +++ b/sdk/python/feast/ui/src/index.tsx @@ -1,22 +1,12 @@ -import React from 'react'; +import React from "react"; import ReactDOM from "react-dom"; -import './index.css'; +import "./index.css"; import FeastUI from "@feast-dev/feast-ui"; import "@feast-dev/feast-ui/dist/feast-ui.css"; ReactDOM.render( - { - return res.json(); - }) - }} - /> + , document.getElementById("root") -); \ No newline at end of file +); diff --git a/sdk/python/feast/ui_server.py b/sdk/python/feast/ui_server.py index cc546f53716..05c42a47b80 100644 --- a/sdk/python/feast/ui_server.py +++ b/sdk/python/feast/ui_server.py @@ -2,7 +2,7 @@ import threading from typing import Callable, Optional -import pkg_resources +from importlib_resources import files, as_file import uvicorn from fastapi import FastAPI, Response from fastapi.middleware.cors import CORSMiddleware @@ -16,8 +16,10 @@ def get_app( get_registry_dump: Callable, project_id: str, registry_ttl_secs: int, + host: str, + port: int, ): - ui_dir = pkg_resources.resource_filename(__name__, "ui/build/") + ui_dir = files(__package__).joinpath("ui/build/") app = FastAPI() @@ -53,25 +55,30 @@ def shutdown_event(): async_refresh() - @app.get("/registry") - def read_registry(): - return json.loads(registry_json) - - # Generate projects-list json that points to the current repo's project - # TODO(adchia): Enable users to also add project name + description fields in feature_store.yaml - @app.get("/projects-list") - def projects_list(): - projects = { + # Initialize with the projects-list.json file + try: + f = ui_dir.joinpath("projects-list.json").open(mode="w") + projects_dict = { "projects": [ { "name": "Project", "description": "Test project", "id": project_id, - "registryPath": "http://0.0.0.0:8888/registry", + "registryPath": f"http://{host}:{port}/registry", } ] } - return projects + f.write(json.dumps(projects_dict)) + except Exception as e: + raise RuntimeError( + "Failed to initialize projects-list.json with registry path" + ) from e + finally: + f.close() + + @app.get("/registry") + def read_registry(): + return json.loads(registry_json) # For all other paths (such as paths that would otherwise be handled by react router), pass to React @app.api_route("/p/{path_name:path}", methods=["GET"]) @@ -83,9 +90,10 @@ def catch_all(): return Response(content, media_type="text/html") - app.mount( - "/", StaticFiles(directory=ui_dir, html=True), name="site", - ) + with as_file(ui_dir) as react_app_dir: + app.mount( + "/", StaticFiles(directory=react_app_dir, html=True), name="site", + ) return app @@ -98,5 +106,5 @@ def start_server( project_id: str, registry_ttl_sec: int, ): - app = get_app(store, get_registry_dump, project_id, registry_ttl_sec) + app = get_app(store, get_registry_dump, project_id, registry_ttl_sec, host, port) uvicorn.run(app, host=host, port=port) From 813c420a61197fb026bde2ea6e15c68ec9a8bc79 Mon Sep 17 00:00:00 2001 From: Danny Chiao Date: Sat, 14 May 2022 14:29:35 -0400 Subject: [PATCH 2/4] fx Signed-off-by: Danny Chiao --- sdk/python/feast/ui/README.md | 18 +++++------------- sdk/python/feast/ui_server.py | 14 +++----------- 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/sdk/python/feast/ui/README.md b/sdk/python/feast/ui/README.md index ea5243ca4c6..0c11dcf134c 100644 --- a/sdk/python/feast/ui/README.md +++ b/sdk/python/feast/ui/README.md @@ -1,6 +1,6 @@ # Example Feast UI App -This is an example React App that imports the Feast UI module and relies on a "/projects-list" endpoint to get projects. +This is an example React App that imports the Feast UI module. See the module import in `src/index.js`. The main change this implements on top of a vanilla create-react-app is adding: @@ -11,23 +11,15 @@ import "@feast-dev/feast-ui/dist/feast-ui.css"; ReactDOM.render( - { - return res.json(); - }) - }} - /> + , document.getElementById("root") ); ``` -It is used by the `feast ui` command to scaffold a local UI server. The feast python package bundles in resources produced from `npm run build --omit=dev +It is used by the `feast ui` command to scaffold a local UI server. The feast python package bundles in resources produced from `npm run build --omit=dev.` + +The `feast ui` command will generate the necessary `projects-list.json` file and initialize it for the UI to read. **Note**: yarn start will not work on this because of the above dependency. diff --git a/sdk/python/feast/ui_server.py b/sdk/python/feast/ui_server.py index 05c42a47b80..dc43b2a305b 100644 --- a/sdk/python/feast/ui_server.py +++ b/sdk/python/feast/ui_server.py @@ -2,11 +2,11 @@ import threading from typing import Callable, Optional -from importlib_resources import files, as_file import uvicorn from fastapi import FastAPI, Response from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles +from importlib_resources import as_file, files import feast @@ -19,8 +19,6 @@ def get_app( host: str, port: int, ): - ui_dir = files(__package__).joinpath("ui/build/") - app = FastAPI() app.add_middleware( @@ -55,9 +53,9 @@ def shutdown_event(): async_refresh() + ui_dir = files(__package__).joinpath("ui/build/") # Initialize with the projects-list.json file - try: - f = ui_dir.joinpath("projects-list.json").open(mode="w") + with ui_dir.joinpath("projects-list.json").open(mode="w") as f: projects_dict = { "projects": [ { @@ -69,12 +67,6 @@ def shutdown_event(): ] } f.write(json.dumps(projects_dict)) - except Exception as e: - raise RuntimeError( - "Failed to initialize projects-list.json with registry path" - ) from e - finally: - f.close() @app.get("/registry") def read_registry(): From 0411e5a7bc379afa6c2d43f19d1a80a69944babc Mon Sep 17 00:00:00 2001 From: Danny Chiao Date: Sun, 15 May 2022 10:22:21 -0400 Subject: [PATCH 3/4] fix python 3.9 version of importlib Signed-off-by: Danny Chiao --- sdk/python/feast/ui_server.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/python/feast/ui_server.py b/sdk/python/feast/ui_server.py index dc43b2a305b..ad82640498f 100644 --- a/sdk/python/feast/ui_server.py +++ b/sdk/python/feast/ui_server.py @@ -1,12 +1,12 @@ import json import threading +from importlib import resources from typing import Callable, Optional import uvicorn from fastapi import FastAPI, Response from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles -from importlib_resources import as_file, files import feast @@ -53,7 +53,7 @@ def shutdown_event(): async_refresh() - ui_dir = files(__package__).joinpath("ui/build/") + ui_dir = resources.files(__package__).joinpath("ui/build/") # Initialize with the projects-list.json file with ui_dir.joinpath("projects-list.json").open(mode="w") as f: projects_dict = { @@ -82,7 +82,7 @@ def catch_all(): return Response(content, media_type="text/html") - with as_file(ui_dir) as react_app_dir: + with resources.as_file(ui_dir) as react_app_dir: app.mount( "/", StaticFiles(directory=react_app_dir, html=True), name="site", ) From 7ada6ccacbd41ac44c242664f1b9b0ae10427709 Mon Sep 17 00:00:00 2001 From: Danny Chiao Date: Sun, 15 May 2022 10:47:27 -0400 Subject: [PATCH 4/4] revert to pkg_resources Signed-off-by: Danny Chiao --- sdk/python/feast/ui_server.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sdk/python/feast/ui_server.py b/sdk/python/feast/ui_server.py index ad82640498f..5206dd5161e 100644 --- a/sdk/python/feast/ui_server.py +++ b/sdk/python/feast/ui_server.py @@ -1,8 +1,8 @@ import json import threading -from importlib import resources from typing import Callable, Optional +import pkg_resources import uvicorn from fastapi import FastAPI, Response from fastapi.middleware.cors import CORSMiddleware @@ -53,9 +53,9 @@ def shutdown_event(): async_refresh() - ui_dir = resources.files(__package__).joinpath("ui/build/") + ui_dir = pkg_resources.resource_filename(__name__, "ui/build/") # Initialize with the projects-list.json file - with ui_dir.joinpath("projects-list.json").open(mode="w") as f: + with open(ui_dir + "projects-list.json", mode="w") as f: projects_dict = { "projects": [ { @@ -82,10 +82,9 @@ def catch_all(): return Response(content, media_type="text/html") - with resources.as_file(ui_dir) as react_app_dir: - app.mount( - "/", StaticFiles(directory=react_app_dir, html=True), name="site", - ) + app.mount( + "/", StaticFiles(directory=ui_dir, html=True), name="site", + ) return app