LeTTo Doc

Build und Deployment des Referenz-Plugins (Python)

Build

build.bat (Windows, am Entwicklungsrechner mit LeTTo-Installation):

  1. Docker-Image lettohub/letto-plugin-demopython:latest bauen
  2. laufenden Container mit docker compose … down stoppen
  3. yml/docker-service-plugindemopython.yml nach /opt/letto/docker/compose/letto/ kopieren
  4. Container mit docker compose … up -d starten

Nur das Image bauen:

docker build -t lettohub/letto-plugin-demopython:latest -f Dockerfile .

Das fertige Image wird auf Docker Hub als lettohub/letto-plugin-demopython veröffentlicht.

Docker

Dockerfile:

Startoptionen (scripts/start.sh)

Variable Standard Bedeutung
debug bzw. DEBUG false Start mit debugpy auf DEBUG_BIND:DEBUG_PORT
DEBUG_PORT, DEBUG_BIND 5080, 0.0.0.0 Port und Adresse des Debuggers
DEBUG_SUSPEND false wartet beim Start, bis sich der Debugger verbindet
PORT, APP_HOST 8080, 0.0.0.0 Port und Adresse von uvicorn
LOG_LEVEL info Log-Level von uvicorn
UVICORN_WORKERS 1 Anzahl der Worker (nicht im Debug-Modus)
UVICORN_RELOAD false Neuladen bei Codeänderungen
APP_MODULE app.main:app FastAPI-Anwendung

Hinweis: Die Konfigurationssitzungen liegen im Speicher eines Prozesses. Mit mehreren Workern können Anfragen derselben Sitzung in verschiedenen Prozessen landen; im Code ist dazu nichts dokumentiert, der Standard ist ein Worker.

Compose-Datei yml/docker-service-plugindemopython.yml

Wichtige Umgebungsvariablen:

Variable Standard Bedeutung
SERVICEPATH /plugindemopython Servicepfad, muss zur location der Proxy-Konfiguration passen
letto_setup_uri http://letto-setup.nw-letto:8096 URI des Setup-Services
letto_user_user_password SERVICE_USER_PASSWORD Passwort für die Registrierung
letto_plugin_uri_intern http://letto-plugindemopython.nw-letto:8080 interne URI im Docker-Netz
letto_plugin_uri_extern https://${SERVER_NAME} externe URI des Servers; Basis für pluginDtoUri
network_letto_address, docker_container_name letto-plugindemopython werden an das Setup gemeldet
RESOURCE_DIR /app/resources Verzeichnis der Ressourcen
letto_pathPlugins /opt/letto/plugins Bildablage für /open/imageurl (Volume ${VOLUME_PLUGINS}); Dateien unter <servicepath>/<2 Zeichen>/<md5>.png
letto_webPathPlugins ${SERVER_NAME}/images/plugins öffentlicher Pfad dieser Bildablage; daraus wird die Bild-URL https://… gebildet
debug DEBUG_PLUGINS bzw. DEBUG Start mit Debugger

Weitere Variablen (letto_pathImages, letto_webPathImages, letto_schulen, letto_user_gast_password, servername) sind gesetzt, werden im Python-Code aber nicht ausgewertet.

Einstellungen der Registrierung (nicht in der Compose-Datei, Standardwerte im Code):

Variable Standard Bedeutung
PLUGIN_REGISTER_ON_READY true Registrierung beim Start
PLUGIN_REGISTER_RETRIES 30 Versuche je Durchlauf
PLUGIN_REGISTER_DELAY_SECONDS 1.0 Abstand zwischen den Versuchen
PLUGIN_REGISTER_PAUSE_SECONDS 60.0 Pause nach einem fehlgeschlagenen Durchlauf

Proxy

proxy/plugindemopython.conf:

location /plugindemopython/ {
     resolver 127.0.0.11 valid=5s ipv6=off;
     set $plugindemopythonpath     letto-plugindemopython.nw-letto:8080;
     proxy_set_header   Host $host;
     proxy_set_header   X-Real-IP $remote_addr;
     proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header   X-Forwarded-Proto $scheme;
     proxy_pass         http://$plugindemopythonpath;
     proxy_read_timeout 90;
}

Installation am LeTTo-Server

cp yml/docker-service-plugindemopython.yml /opt/letto/docker/compose/letto/
docker compose -f /opt/letto/docker/compose/letto/docker-service-plugindemopython.yml up -d
cp proxy/plugindemopython.conf /opt/letto/docker/proxy/
docker restart letto-proxy

Registrierung am LeTTo-Server

Feld Wert
name, version, author, license CONF_PLUGIN_NAME, CONF_VERSION, CONF_PLUGIN_AUTHOR, CONF_PLUGIN_LICENSE
bs, ip Betriebssystem und IP des Containers
encoding, programmingLanguage UTF-8, python
nwLettoAddress, dockerName network_letto_address, docker_container_name
uriIntern letto_plugin_uri_intern + /open
extern, uriExtern false, letto_plugin_uri_extern
plugin, scalable, stateless true, false, true
username, password, usePluginToken "", "", false
serviceStartTime, lastRegistrationTime Unix-Zeit in Sekunden
params {}
htmlServiceStartTime, htmlLastRegistrationTime zusätzlich: formatierte Zeitpunkte TT.MM.JJJJ hh:mm:ss

Tests

pip install -r requirements-dev.txt
python -m pytest

Die Tests laufen ohne Docker und ohne LeTTo (PLUGIN_REGISTER_ON_READY=false, Ressourcen aus dem Projektverzeichnis):

Datei prüft
tests/test_imageurl.py /open/imageurl unter /open und <servicepath>/open: Ablage und URL, gleiches Bild – gleiche Datei, Datei entspricht dem Base64-Bild, fehlende Bildablage, unbekanntes Plugin, URL ohne doppelte Schrägstriche
tests/test_scorer.py Zeitumrechnung, Uhrzeit-Vergleich über 12 Uhr, relative und absolute Toleranz, PluginDemo.score, Endpunkt /open/score unter /open und <servicepath>/open
tests/test_openapi.py alphabetische Sortierung in der OpenAPI-Beschreibung, Links jedes Endpunkts, DTOs und Enum-Felds auf die Java-Doku, Link auf diese Python-Doku in OpenAPI-Beschreibung und externalDocs, Links auf Java- und Python-Doku auf der Hilfeseite

Debugging mit PyCharm

PyCharm: Attach to DAP

Referenz-Plugin (Python)