From b380624c9f60f74cf41b10a99187310727be19fa Mon Sep 17 00:00:00 2001 From: Dominique Lasserre Date: Mon, 10 Feb 2025 00:38:35 +0100 Subject: [PATCH] Windows: Fix EOSdash startup Closes #436 #447 (#450) * On Windows use 127.0.0.1 as default config host (model defaults) and addionally redirect 0.0.0.0 to localhost on Windows (because default config file still has 0.0.0.0). Use 0.0.0.0 as default otherwise (e.g. Linux/Docker) to allow EOS being accessible on local network (not just same host). Note: Docs generation on Windows is incompatible with the Github pipeline tests. Address this in the nested-config feature branch. * Update install/startup instructions as package installation is required atm and Docker on Windows has to be accessed at localhost or 127.0.0.1 even though the server log says 0.0.0.0 (which is required to be available outside the container). * Fix EOSdash startup with read_only: true (support session key via EOS_SERVER__EOSDASH_SESSKEY variable). Backport of feature branch. * Remove root_path, causing Windows to fail load swagger UI (/docs). --- CONTRIBUTING.md | 1 + Dockerfile | 1 + README.md | 6 +++++- docker-compose.yaml | 2 +- docs/develop/getting_started.md | 2 ++ src/akkudoktoreos/server/eos.py | 9 ++++++--- src/akkudoktoreos/server/eosdash.py | 2 +- src/akkudoktoreos/server/server.py | 11 +++++++++-- 8 files changed, 26 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 71caee0..d9f9f75 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,6 +33,7 @@ See also [README.md](README.md). python -m venv .venv source .venv/bin/activate pip install -r requirements-dev.txt +pip install -e . ``` Install make to get access to helpful shortcuts (documentation generation, manual formatting, etc.). diff --git a/Dockerfile b/Dockerfile index d652f63..2c3cc14 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,6 +39,7 @@ ENTRYPOINT [] EXPOSE 8503 EXPOSE 8504 +ENV server_eosdash_host=0.0.0.0 CMD ["python", "src/akkudoktoreos/server/eos.py", "--host", "0.0.0.0"] VOLUME ["${MPLCONFIGDIR}", "${EOS_CACHE_DIR}", "${EOS_OUTPUT_DIR}", "${EOS_CONFIG_DIR}"] diff --git a/README.md b/README.md index b6657f6..f7a86bf 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Linux: ```bash python -m venv .venv .venv/bin/pip install -r requirements.txt +.venv/bin/pip install -e . ``` Windows: @@ -40,9 +41,10 @@ Windows: ```cmd python -m venv .venv .venv\Scripts\pip install -r requirements.txt + .venv\Scripts\pip install -e . ``` -Finally, start the EOS server: +Finally, start the EOS server to access it at `http://localhost:8503` (API docs at `http://localhost:8503/docs`): Linux: @@ -58,6 +60,8 @@ Windows: ### Docker +Start EOS with following command to access it at `http://localhost:8503` (API docs at `http://localhost:8503/docs`): + ```bash docker compose up ``` diff --git a/docker-compose.yaml b/docker-compose.yaml index 2759ef6..2140b60 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -17,6 +17,6 @@ services: - longitude=13.4 - elecprice_provider=ElecPriceAkkudoktor - elecprice_charges_kwh=0.21 - - server_fasthtml_host=none + - EOS_SERVER__EOSDASH_SESSKEY=s3cr3t ports: - "${EOS_PORT}:${EOS_PORT}" diff --git a/docs/develop/getting_started.md b/docs/develop/getting_started.md index 3b77fc6..a474b5d 100644 --- a/docs/develop/getting_started.md +++ b/docs/develop/getting_started.md @@ -19,6 +19,7 @@ Install the dependencies in a virtual environment: python -m venv .venv .venv\Scripts\pip install -r requirements.txt + .venv\Scripts\pip install -e . .. tab:: Linux @@ -26,6 +27,7 @@ Install the dependencies in a virtual environment: python -m venv .venv .venv/bin/pip install -r requirements.txt + .venv/bin/pip install -e . ``` diff --git a/src/akkudoktoreos/server/eos.py b/src/akkudoktoreos/server/eos.py index e18406c..e9bc047 100755 --- a/src/akkudoktoreos/server/eos.py +++ b/src/akkudoktoreos/server/eos.py @@ -223,7 +223,6 @@ app = FastAPI( "url": "https://www.apache.org/licenses/LICENSE-2.0.html", }, lifespan=lifespan, - root_path=str(Path(__file__).parent), ) @@ -882,9 +881,13 @@ async def proxy_put(request: Request, path: str) -> Response: async def proxy(request: Request, path: str) -> Union[Response | RedirectResponse | HTMLResponse]: - if config_eos.server_eosdash_host and config_eos.server_eosdash_port: + # Make hostname Windows friendly + host = str(config_eos.server_eosdash_host) + if host == "0.0.0.0" and os.name == "nt": + host = "localhost" + if host and config_eos.server_eosdash_port: # Proxy to EOSdash server - url = f"http://{config_eos.server_eosdash_host}:{config_eos.server_eosdash_port}/{path}" + url = f"http://{host}:{config_eos.server_eosdash_port}/{path}" headers = dict(request.headers) data = await request.body() diff --git a/src/akkudoktoreos/server/eosdash.py b/src/akkudoktoreos/server/eosdash.py index 91de731..30e3ab8 100644 --- a/src/akkudoktoreos/server/eosdash.py +++ b/src/akkudoktoreos/server/eosdash.py @@ -24,7 +24,7 @@ for field_name in config_eos.model_fields: configs.append(config) -app = FastHTML() +app = FastHTML(secret_key=os.getenv("EOS_SERVER__EOSDASH_SESSKEY")) rt = app.route diff --git a/src/akkudoktoreos/server/server.py b/src/akkudoktoreos/server/server.py index 780f274..52184c6 100644 --- a/src/akkudoktoreos/server/server.py +++ b/src/akkudoktoreos/server/server.py @@ -1,5 +1,6 @@ """Server Module.""" +import os from typing import Optional from pydantic import Field, IPvAnyAddress, field_validator @@ -10,6 +11,12 @@ from akkudoktoreos.core.logging import get_logger logger = get_logger(__name__) +def get_default_host() -> str: + if os.name == "nt": + return "127.0.0.1" + return "0.0.0.0" + + class ServerCommonSettings(SettingsBaseModel): """Common server settings. @@ -18,7 +25,7 @@ class ServerCommonSettings(SettingsBaseModel): """ server_eos_host: Optional[IPvAnyAddress] = Field( - default="0.0.0.0", description="EOS server IP address." + default=get_default_host(), description="EOS server IP address." ) server_eos_port: Optional[int] = Field(default=8503, description="EOS server IP port number.") server_eos_verbose: Optional[bool] = Field(default=False, description="Enable debug output") @@ -26,7 +33,7 @@ class ServerCommonSettings(SettingsBaseModel): default=True, description="EOS server to start EOSdash server." ) server_eosdash_host: Optional[IPvAnyAddress] = Field( - default="0.0.0.0", description="EOSdash server IP address." + default=get_default_host(), description="EOSdash server IP address." ) server_eosdash_port: Optional[int] = Field( default=8504, description="EOSdash server IP port number."