diff --git a/REVERSEENGINEERING.md b/REVERSEENGINEERING.md new file mode 100644 index 00000000..48322e97 --- /dev/null +++ b/REVERSEENGINEERING.md @@ -0,0 +1,19 @@ +# Reverse Engineering InteractiveAI Platform + +## Apidocs + +* [Event-Api](http://localhost:5001/docs) +* [Context-Api](http://localhost:5100/docs) +* [Historic-Api](http://localhost:5200/docs) + +## Notes + +* Use cases are statically defined at build: + e.g. `class MetadataSchemaRTE(MetadataSchema):` is located in `backend/resources`. +* Users have +* Schemas for use-case specific event types are there, but seem not published in swagger, e.g. `class MetadataSchemaRTE(MetadataSchema):` found but not + in [Event-Api](http://localhost:5001/docs) + +## Wiring + +![Wiring.drawio.png](Wiring.drawio.png) \ No newline at end of file diff --git a/Wiring.drawio.png b/Wiring.drawio.png new file mode 100644 index 00000000..fa164c34 Binary files /dev/null and b/Wiring.drawio.png differ diff --git a/backend/context-service/api/schemas.py b/backend/context-service/api/schemas.py index 3752e236..178c28ec 100644 --- a/backend/context-service/api/schemas.py +++ b/backend/context-service/api/schemas.py @@ -1,7 +1,7 @@ import importlib from apiflask import Schema -from apiflask.fields import DateTime, Dict, Integer, String +from apiflask.fields import DateTime, Dict, Integer, String, List, Nested from apiflask.validators import Length, OneOf from marshmallow import ValidationError, validates_schema @@ -11,13 +11,19 @@ class MetadataSchema(Schema): pass +# workaround to expose schema in openapi.json: copy-paste from resources/Railway +class MetadataSchemaRailway(MetadataSchema): + trains = List(Dict(), required=False) + list_of_target = Dict(required=False) + direction_agents = List(Integer(), required=False) + position_agents = Dict(required=False) class ContextIn(Schema): use_case = String( required=True, validate=OneOf(["PowerGrid", "Railway", "ATM"]) ) date = DateTime(format="iso") - data = Dict() + data = Nested(MetadataSchemaRailway) @validates_schema def validate_metadata(self, data, **kwargs): @@ -45,7 +51,7 @@ class ContextOut(Schema): id_context = String() use_case = String() date = DateTime(format="iso") - data = Dict() + data = Nested(MetadataSchemaRailway) class UseCaseIn(Schema): diff --git a/backend/event-service/api/schemas.py b/backend/event-service/api/schemas.py index 8b1302ba..9c3d9765 100644 --- a/backend/event-service/api/schemas.py +++ b/backend/event-service/api/schemas.py @@ -2,14 +2,29 @@ from api.models import UseCaseModel from apiflask import Schema -from apiflask.fields import Boolean, DateTime, Dict, Integer, String +from apiflask.fields import Boolean, DateTime, Dict, Integer, String, List, Float, Nested from apiflask.validators import Length, OneOf from marshmallow import ValidationError, validates_schema - class MetadataSchema(Schema): pass +# workaround to expose schema in openapi.json: copy-paste from resources/Railway +class MetadataSchemaRailway(MetadataSchema): + agent_id = String(allow_none=True, required=True) + event_type = String(required=True) + agent_position = List( + Integer(allow_none=True), allow_none=True, default=None + ) + delay = Integer(required=True) + id_train = String(allow_none=True, required=True) + malfunction_stop_position = List(Integer(allow_none=True), allow_none=True) + num_rame = String(allow_none=True, default=None) + tmp_rame = String(allow_none=True, default=None) + travel_plan = List(Dict(), allow_none=True) + longitude = Float(allow_none=True, default=None) + latitude = Float(allow_none=True, default=None) + simulation_name = String(allow_none=True, default=None) class EventIn(Schema): use_case = String(required=True, validate=Length(1, 255)) @@ -21,7 +36,7 @@ class EventIn(Schema): required=True, validate=OneOf(["ND", "HIGH", "MEDIUM", "LOW", "ROUTINE"]), ) - data = Dict() + data = Nested(MetadataSchemaRailway) is_active = Boolean() parent_event_id = String(allow_none=True) @@ -57,7 +72,7 @@ class EventOut(Schema): start_date = DateTime(format="iso", allow_none=True) end_date = DateTime(format="iso", allow_none=True) criticality = String() - data = Dict() + data = Nested(MetadataSchemaRailway) is_active = Boolean() parent_event_id = String(allow_none=True) diff --git a/config/dev/cab-standalone/docker-compose.sh b/config/dev/cab-standalone/docker-compose.sh index 281eeeec..bac36288 100755 --- a/config/dev/cab-standalone/docker-compose.sh +++ b/config/dev/cab-standalone/docker-compose.sh @@ -44,4 +44,4 @@ fi echo "HOST_IP=${HOST_IP}" >> .env cat .env -docker-compose up -d +docker compose up -d diff --git a/config/dev/cab-standalone/docker-compose.yml b/config/dev/cab-standalone/docker-compose.yml index 0f247617..8595e112 100644 --- a/config/dev/cab-standalone/docker-compose.yml +++ b/config/dev/cab-standalone/docker-compose.yml @@ -11,8 +11,8 @@ services: - FLASK_APP=app:create_app('dev') - PYTHONPATH=/code - FLASK_ENV=development - - URL_INTROSPECT=http://frontend:80/auth/check_token - - KEYCLOAK_SERVER_URL=http://frontend:80/auth/ + - URL_INTROSPECT=http://${GATEWAY_HOSTNAME:-frontend}:80/auth/check_token + - KEYCLOAK_SERVER_URL=http://${GATEWAY_HOSTNAME:-frontend}:80/auth/ - OPFAB_CLIENT_SECRET=opfab-keycloak-secret - TZ=UTC # Set timezone to UTC @@ -34,19 +34,19 @@ services: restart: unless-stopped environment: - CARDS_PUBLICATION_SERVICE=http://cards-publication:8080 - - GATEWAY_SERVICE=http://frontend:80 + - GATEWAY_SERVICE=http://${GATEWAY_HOSTNAME:-frontend}:80 - HISTORIC_SERVICE=http://cabhistoric:5000 - DATABASE_URL=postgresql://postgres:postgres@db_postgres_event:5432/cab-event - FLASK_APP=app:create_app('dev') - PYTHONPATH=/code - FLASK_ENV=development - - URL_INTROSPECT=http://frontend:80/auth/check_token - - KEYCLOAK_SERVER_URL=http://frontend:80/auth/ + - URL_INTROSPECT=http://${GATEWAY_HOSTNAME:-frontend}:80/auth/check_token + - KEYCLOAK_SERVER_URL=http://${GATEWAY_HOSTNAME:-frontend}:80/auth/ - OPFAB_CLIENT_SECRET=opfab-keycloak-secret - TZ=UTC # Set timezone to UTC command: sh -c "./entrypoint.sh" ports: - - 5000:5000 + - 5001:5000 volumes: - ../../../backend/event-service:/code depends_on: @@ -63,8 +63,8 @@ services: - FLASK_APP=app:create_app('dev') - FLASK_ENV=development - PYTHONPATH=/my_app - - URL_INTROSPECT=http://frontend:80/auth/check_token - - KEYCLOAK_SERVER_URL=http://frontend:80/auth/ + - URL_INTROSPECT=http://${GATEWAY_HOSTNAME:-frontend}:80/auth/check_token + - KEYCLOAK_SERVER_URL=http://${GATEWAY_HOSTNAME:-frontend}:80/auth/ - OPFAB_CLIENT_SECRET=opfab-keycloak-secret - TZ=UTC # Set timezone to UTC restart: unless-stopped @@ -130,7 +130,7 @@ services: restart: unless-stopped frontend: - container_name: frontend + container_name: ${GATEWAY_HOSTNAME:-frontend} build: context: ../../../frontend dockerfile: Dockerfile @@ -148,6 +148,8 @@ services: - './nginx-cors-permissive.conf:/etc/nginx/conf.d/default.conf' ports: - '3200:80' + # tokens are issued for ${GATEWAY_HOSTNAME:-frontend}:80 (see KEYCLOAK_SERVER_URL below), need to match the URL + - '80:80' depends_on: - cabrecommendation - cabevent @@ -163,15 +165,17 @@ services: build: context: ../../../backend dockerfile: Recommendation-Service-Dockerfile + # fix platform as otherwise, we get compile errors on macOS.... + platform: "linux/amd64" restart: unless-stopped environment: - - GATEWAY_SERVICE=http://frontend:80 + - GATEWAY_SERVICE=http://${GATEWAY_HOSTNAME:-frontend}:80 - DATABASE_URL=postgresql://postgres:postgres@db_postgres_recommendation:5432/cab-recommendation - FLASK_APP=app:create_app('dev') - PYTHONPATH=/my_app - FLASK_ENV=development - - URL_INTROSPECT=http://frontend:80/auth/check_token - - KEYCLOAK_SERVER_URL=http://frontend:80/auth/ + - URL_INTROSPECT=http://${GATEWAY_HOSTNAME:-frontend}:80/auth/check_token + - KEYCLOAK_SERVER_URL=http://${GATEWAY_HOSTNAME:-frontend}:80/auth/ - OPFAB_CLIENT_SECRET=opfab-keycloak-secret - TZ=UTC # Set timezone to UTC command: sh -c "./entrypoint.sh" @@ -206,8 +210,8 @@ services: - FLASK_APP=app:create_app('dev') - FLASK_ENV=development - PYTHONPATH=/my_app - - URL_INTROSPECT=http://frontend:80/auth/check_token - - KEYCLOAK_SERVER_URL=http://frontend:80/auth/ + - URL_INTROSPECT=http://${GATEWAY_HOSTNAME:-frontend}:80/auth/check_token + - KEYCLOAK_SERVER_URL=http://${GATEWAY_HOSTNAME:-frontend}:80/auth/ - OPFAB_CLIENT_SECRET=opfab-keycloak-secret - TZ=UTC # Set timezone to UTC restart: unless-stopped diff --git a/resources/bundles/deleteAllBundles.sh b/resources/bundles/deleteAllBundles.sh index 41551266..0f22604c 100755 --- a/resources/bundles/deleteAllBundles.sh +++ b/resources/bundles/deleteAllBundles.sh @@ -12,7 +12,7 @@ # is called from another folder cd "$(dirname "${BASH_SOURCE[0]}")" -url=$2 +url=$1 if [ -z $url ] then url="http://localhost" diff --git a/resources/getToken.sh b/resources/getToken.sh index ccc48ba0..654dbed3 100755 --- a/resources/getToken.sh +++ b/resources/getToken.sh @@ -23,7 +23,7 @@ fi echo "Get token for user $username on $url" access_token_pattern='"access_token":"([^"]+)"' -response=$(curl -s -X POST -d "username="$username"&password=test&grant_type=password&client_id=opfab-client" $url:3200/auth/token) +response=$(curl -s -X POST -d "username="$username"&password=test&grant_type=password&client_id=opfab-client" $url:80/auth/token) if [[ $response =~ $access_token_pattern ]] ; then export token=${BASH_REMATCH[1]} fi diff --git a/resources/loadTestConf.sh b/resources/loadTestConf.sh index e8bdd466..04739d0b 100755 --- a/resources/loadTestConf.sh +++ b/resources/loadTestConf.sh @@ -15,7 +15,8 @@ cd "$(dirname "${BASH_SOURCE[0]}")" url=$1 if [[ -z $url ]] then - url="http://localhost" + # tweak /etc/hosts to run from docker host! + url="http://frontend" fi ( cd bundles diff --git a/usecases_examples/PowerGrid/README.md b/usecases_examples/PowerGrid/README.md index 9c6fb0e0..28269b91 100644 --- a/usecases_examples/PowerGrid/README.md +++ b/usecases_examples/PowerGrid/README.md @@ -73,7 +73,7 @@ docker-compose up -d --build api ``` The launched API might be accessible at this address: -http://SERVER_ADDRESS:5100 +http://SERVER_ADDRESS:5101 The SERVER_ADDRESS will be the one of the computer used to launch the Docker command. @@ -92,8 +92,8 @@ pip install -r requirements-app.txt docker-compose up -d --build app ``` -The launched app might be accessible at this address: -http://SERVER_ADDRESS:5100/ +The launched app will be accessible at this address: +http://SERVER_ADDRESS:5101/ The SERVER_ADDRESS will be the one of the computer used to launch the Docker command. @@ -115,11 +115,11 @@ python PowerGrid_poc_simulator_consol.py ### To launch the simulator app (BEST APPROACH) Open a web browser and navigate to the URL returned by Docker after running the containers. -This URL will typically be `http://localhost:5100/` unless you've configured a different port. +This URL will typically be `http://localhost:5101/` unless you've configured a different port. Note: If you're running Docker on a remote machine or using Docker Toolbox on Windows, you may need to replace 'localhost' with the appropriate IP address. -For example : http://SERVER_ADDRESS:5100/ with **SERVER_ADDRESS** the one of your remote machine. +For example : http://SERVER_ADDRESS:5101/ with **SERVER_ADDRESS** the one of your remote machine. ### Run the simulator in your terminal (optional) ```commandline diff --git a/usecases_examples/PowerGrid/docker-compose.yml b/usecases_examples/PowerGrid/docker-compose.yml index 2608c16a..e0a3e853 100644 --- a/usecases_examples/PowerGrid/docker-compose.yml +++ b/usecases_examples/PowerGrid/docker-compose.yml @@ -8,10 +8,11 @@ services: container_name: PowerGrid-simulator-app restart: always ports: - - "5100:5000" + - "5101:5000" volumes: - .:/code - + networks: + - cab-standalone_default api: build: context: . @@ -20,6 +21,14 @@ services: container_name: PowerGrid-simulator-api restart: always ports: - - "5100:5000" + - "5101:5000" volumes: - .:/code + networks: + - cab-standalone_default + +# allow for communication between simulator and cab +networks: + cab-standalone_default: + name: cab-standalone_default + external: true \ No newline at end of file