diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..e38db0b0 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,136 @@ +name: Test Pipeline + +on: [push, pull_request] + +jobs: + test-cab_common: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: "3.11" + - name: Install dependencies + run: | + cd backend/cab_common + export PYTHONPATH=. + pip install -r requirements.txt + - name: Run tests + run: | + cd backend/cab_common + pytest tests --cov --cov-report term --cov-report html --cov-report xml:coverage.xml --junitxml=report.xml + env: + COV_CONTEXT: "backend/cab_common" + + test-event-service: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: "3.11" + - name: Install dependencies + run: | + pip install backend/cab_common + cd backend/event-service + pip install -r requirements.txt + - name: Run tests + run: | + cd backend/event-service + export PYTHONPATH=. + export FLASK_APP=web + pytest tests --cov --cov-report term --cov-report html --cov-report xml:coverage.xml --junitxml=report.xml + env: + COV_CONTEXT: "backend/event-service" + + test-context-service: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: "3.11" + - name: Install dependencies + run: | + pip install backend/cab_common + cd backend/context-service + pip install -r requirements.txt + pip install pytest-cov==4.1.0 pytest-mock==3.12.0 pytest-runner==6.0.1 + - name: Run tests + run: | + cd backend/context-service + export PYTHONPATH=. + export FLASK_APP=web + pytest tests --cov --cov-report term --cov-report html --cov-report xml:coverage.xml --junitxml=report.xml + env: + COV_CONTEXT: "backend/context-service" + + test-recommendation-service: + runs-on: ubuntu-latest + container: python:3.11.6-slim + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Set up dependencies + run: | + mkdir -p /usr/share/man/man1 + apt update && apt install -y --no-install-recommends default-jre + pip install backend/cab_common + - name: Set up recommendation service + run: | + cd backend/recommendation-service + pip install -r requirements.txt + pip install pytest-cov==4.1.0 pytest-mock==3.12.0 pytest-runner==6.0.1 + - name: Run tests + run: | + cd backend/recommendation-service + export PYTHONPATH=. + export FLASK_APP=web + pytest tests --cov --cov-report term --cov-report html --cov-report xml:coverage.xml --junitxml=report.xml + env: + COV_CONTEXT: "backend/recommendation-service" + + test-frontend-service: + runs-on: ubuntu-latest + container: cypress/browsers:node-20.9.0-chrome-118.0.5993.88-1-ff-118.0.2-edge-118.0.2088.46-1 + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: "16" + - name: Install dependencies + run: | + cd frontend + npm ci + - name: Lint code + run: | + cd frontend + npm run lint + - name: Type-check code + run: | + cd frontend + npm run type-check + - name: Build project + run: | + cd frontend + npm run build-only + - name: Run tests + run: | + cd frontend + npm run test:coverage + - name: Upload coverage report + if: always() + uses: actions/upload-artifact@v3 + with: + name: frontend-coverage + path: frontend/coverage + env: + COV_CONTEXT: "frontend" diff --git a/backend/context-service/api/clients/correlation_client.py b/backend/context-service/api/clients/correlation_client.py deleted file mode 100644 index 31785578..00000000 --- a/backend/context-service/api/clients/correlation_client.py +++ /dev/null @@ -1,19 +0,0 @@ -import requests -import json -from settings import CORRELATION_SERVICE, logger - - -class CorrelationClient: - def __init__(self) -> None: - self.base_url = CORRELATION_SERVICE - - def send_correlation(self, correlation_app_payload): - url = f"{self.base_url}/api/v1/correlation" - payload = json.dumps(correlation_app_payload) - headers = { - 'Content-Type': 'application/json' - } - - response = requests.request("POST", url, headers=headers, data=payload) - logger.info("correlation request sent") - response.raise_for_status() diff --git a/backend/context-service/settings.py b/backend/context-service/settings.py index 69afcdab..985aa18e 100644 --- a/backend/context-service/settings.py +++ b/backend/context-service/settings.py @@ -1,9 +1,5 @@ -import os import logging.config -CORRELATION_SERVICE = os.getenv('CORRELATION_SERVICE') - - DEFAULT_LOGGING = { 'version': 1, 'formatters': {'default': { diff --git a/backend/context-service/tests/conftest.py b/backend/context-service/tests/conftest.py index 7d391f44..841d9f7e 100644 --- a/backend/context-service/tests/conftest.py +++ b/backend/context-service/tests/conftest.py @@ -18,13 +18,6 @@ def app(): yield app - use_case_factory = app.use_case_factory - try: - orange_factory = use_case_factory.get_context_manager("ORANGE") - orange_factory.correaltion_manager.correlation_request_process.terminate() - except Exception as e: - logger.info(f"Ignore this error {e}") - # Clean up the database after the test db.session.remove() db.drop_all() @@ -75,123 +68,6 @@ def rte_auth_mocker(client, mocker): }, ) - -@pytest.fixture -def da_auth_mocker(client, mocker): - # Mock the keycloak.introspect method to return a valid response - mocker.patch( - "cab_common_auth.decorators.keycloak.introspect", - return_value={ - "exp": 1684401219, - "iat": 1683796419, - "jti": "a28734f6-f5c8-4130-8fb7-573d75c39d8c", - "iss": "http://192.168.211.95:3200/realms/dev", - "aud": "account", - "sub": "da_user", - "typ": "Bearer", - "azp": "opfab-client", - "session_state": "bd3b8610-1d05-4bdd-916b-61dcfe6d5e72", - "preferred_username": "da_user", - "email_verified": False, - "acr": "1", - "realm_access": {"roles": ["offline_access", "uma_authorization"]}, - "resource_access": { - "account": { - "roles": [ - "manage-account", - "manage-account-links", - "view-profile", - ] - } - }, - "scope": "email profile", - "sid": "bd3b8610-1d05-4bdd-916b-61dcfe6d5e72", - "groups": "RTE;ADMIN;ReadOnly", - "entitiesId": "DA", - "client_id": "opfab-client", - "username": "da_user", - "active": True, - }, - ) - - -@pytest.fixture -def sncf_auth_mocker(client, mocker): - # Mock the keycloak.introspect method to return a valid response - mocker.patch( - "cab_common_auth.decorators.keycloak.introspect", - return_value={ - "exp": 1684413915, - "iat": 1683809115, - "jti": "6f63636a-625a-4926-9684-6d5ed3b80e2a", - "iss": "http://192.168.211.95:3200/realms/dev", - "aud": "account", - "sub": "sncf_user", - "typ": "Bearer", - "azp": "opfab-client", - "session_state": "0dee604d-5c03-416c-8d95-59b0aa95b61a", - "preferred_username": "sncf_user", - "email_verified": False, - "acr": "1", - "realm_access": {"roles": ["offline_access", "uma_authorization"]}, - "resource_access": { - "account": { - "roles": [ - "manage-account", - "manage-account-links", - "view-profile", - ] - } - }, - "scope": "email profile", - "sid": "0dee604d-5c03-416c-8d95-59b0aa95b61a", - "entitiesId": "SNCF", - "client_id": "opfab-client", - "username": "sncf_user", - "active": True, - }, - ) - - -@pytest.fixture -def orange_auth_mocker(client, mocker): - # Mock the keycloak.introspect method to return a valid response - mocker.patch( - "cab_common_auth.decorators.keycloak.introspect", - return_value={ - "exp": 1684766859, - "iat": 1684162059, - "jti": "418dee2b-aac6-452e-a90f-32278e34a22b", - "iss": "http://192.168.211.95:3200/realms/dev", - "aud": "account", - "sub": "orange_user", - "typ": "Bearer", - "azp": "opfab-client", - "session_state": "5297805d-fc73-4d94-97fc-0c5a52c41440", - "preferred_username": "orange_user", - "email_verified": False, - "acr": "1", - "realm_access": {"roles": ["offline_access", "uma_authorization"]}, - "resource_access": { - "account": { - "roles": [ - "manage-account", - "manage-account-links", - "view-profile", - ] - } - }, - "scope": "email profile", - "sid": "5297805d-fc73-4d94-97fc-0c5a52c41440", - "groups": "RTE;ADMIN;ReadOnly", - "entitiesId": "ORANGE", - "client_id": "opfab-client", - "username": "orange_user", - "active": True, - }, - ) - - @pytest.fixture def publisher_test_auth_mocker(client, mocker): # Mock the keycloak.introspect method to return a valid response @@ -274,32 +150,13 @@ def create_usecases(client): db.create_all() - da_use_case = UseCaseModel( - name="DA", - context_manager_class="DAContextManager", - metadata_schema_class="MetadataSchemaDA", - ) - - orange_use_case = UseCaseModel( - name="ORANGE", - context_manager_class="OrangeContextManager", - metadata_schema_class="MetadataSchemaOrange", - ) rte_use_case = UseCaseModel( name="RTE", context_manager_class="RTEContextManager", metadata_schema_class="MetadataSchemaRTE", ) - sncf_use_case = UseCaseModel( - name="SNCF", - context_manager_class="SNCFContextManager", - metadata_schema_class="MetadataSchemaSNCF", - ) - db.session.add(da_use_case) - db.session.add(orange_use_case) db.session.add(rte_use_case) - db.session.add(sncf_use_case) db.session.commit() # add use_case_factory use_case_factory = current_app.use_case_factory diff --git a/backend/context-service/tests/test_views.py b/backend/context-service/tests/test_views.py index 90b1a3b2..e58fc020 100644 --- a/backend/context-service/tests/test_views.py +++ b/backend/context-service/tests/test_views.py @@ -7,9 +7,6 @@ from datetime import datetime RTE_BEARER_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJSbXFOVTNLN0x4ck5SRmtIVTJxcTZZcTEya1RDaXNtRkw5U2NwbkNPeDBjIn0.eyJleHAiOjE2ODQzMzMyNjEsImlhdCI6MTY4MzcyODQ2MSwianRpIjoiNzE2YjAyZDQtMjliYS00MWJkLTg1YjItODAwNGNlYzFhMDMzIiwiaXNzIjoiaHR0cDovLzE5Mi4xNjguMjExLjk1OjMyMDAvcmVhbG1zL2RldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiJydGVfdXNlciIsInR5cCI6IkJlYXJlciIsImF6cCI6Im9wZmFiLWNsaWVudCIsInNlc3Npb25fc3RhdGUiOiI4OTc2YjEyNS0zOWE4LTRiZGYtYjUyMy03ZTBkY2JjZGQzYjQiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzaWQiOiI4OTc2YjEyNS0zOWE4LTRiZGYtYjUyMy03ZTBkY2JjZGQzYjQiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImdyb3VwcyI6IkRpc3BhdGNoZXI7UmVhZE9ubHk7U3VwZXJ2aXNvciIsInByZWZlcnJlZF91c2VybmFtZSI6InJ0ZV91c2VyIiwiZ2l2ZW5fbmFtZSI6IiIsImVudGl0aWVzSWQiOiJSVEUiLCJmYW1pbHlfbmFtZSI6IiJ9.j-_kiNnn5jQtUBMZ-oaeWVVfZLM1dWLFjRYKfL9pkpklG-CAVl1CuUQE969YkaPZLD4TtXaiNy02LhkIWmSwQuks2lH5_dtUlCBlpIouD1liDxg1g_oXn_m3vKwzDQ03KeeVC03BCMJR8gDTED80U-vjXT33-BngpjMP2rFMZRiZIJO_BB4GnIf55dnazWj8jbp0MVZYS9fuNeuLLrRgMevGDn5s-AlznmWLce1K6P882StmhI0unRXVOTRae8xRvDkk0BJ545K9FtLoZtgOeyEw7JrvElkPMqWKOy3R5hmpJENZSV1zCMBdXusVi7GTyn4denCqA7yYerWi_yaITg" -DA_BEARER_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJSbXFOVTNLN0x4ck5SRmtIVTJxcTZZcTEya1RDaXNtRkw5U2NwbkNPeDBjIn0.eyJleHAiOjE2ODQ0MDEyMTksImlhdCI6MTY4Mzc5NjQxOSwianRpIjoiYTI4NzM0ZjYtZjVjOC00MTMwLThmYjctNTczZDc1YzM5ZDhjIiwiaXNzIjoiaHR0cDovLzE5Mi4xNjguMjExLjk1OjMyMDAvcmVhbG1zL2RldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiJkYV91c2VyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoib3BmYWItY2xpZW50Iiwic2Vzc2lvbl9zdGF0ZSI6ImJkM2I4NjEwLTFkMDUtNGJkZC05MTZiLTYxZGNmZTZkNWU3MiIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsInNpZCI6ImJkM2I4NjEwLTFkMDUtNGJkZC05MTZiLTYxZGNmZTZkNWU3MiIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZ3JvdXBzIjoiUlRFO0FETUlOO1JlYWRPbmx5IiwicHJlZmVycmVkX3VzZXJuYW1lIjoiZGFfdXNlciIsImVudGl0aWVzSWQiOiJEQSJ9.RKl9ndaXW_EdMW81YRBxuwQhcRaZwvlfSG1H0ms1ElySp-XGnunvdNuj6VLwB56_wjdijPUnqOrKAsYMxa9lGipUzeAIdbPFojO1Et1IxGQSyqxJTX9ngpSQi3btJM3eP1bQ3bHSLNKIdSpZrCdhhxP8-s6vHa__7RcIMxSBvYjX-tT97qQBubqqHdSouAJP1RZYn1_G8T6Pzs1hK2RXseMRYvBUAtXD24-Lk9IaRB9GUO5P9MCb_VldqUEPAWM5rVkjxrojAUB0OM1NGcge1jiQotHyeqBPnB5oHD_2LdygbsuO5i1t4Z5y4Q2JxyMzrR4nyh3lrSjhUf60cfFpEA" -SNCF_BEARER_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJSbXFOVTNLN0x4ck5SRmtIVTJxcTZZcTEya1RDaXNtRkw5U2NwbkNPeDBjIn0.eyJleHAiOjE2ODQ0MDE2OTAsImlhdCI6MTY4Mzc5Njg5MCwianRpIjoiN2MzZTQ2YzUtYTliOC00ZTRmLWFmYjAtZjBlODU5Y2U3YzA1IiwiaXNzIjoiaHR0cDovLzE5Mi4xNjguMjExLjk1OjMyMDAvcmVhbG1zL2RldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiJzbmNmX3VzZXIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJvcGZhYi1jbGllbnQiLCJzZXNzaW9uX3N0YXRlIjoiM2MwNzRmNTMtODMxNy00NTE5LTk1MGMtOWZlOTE1ZjVjY2QwIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwic2lkIjoiM2MwNzRmNTMtODMxNy00NTE5LTk1MGMtOWZlOTE1ZjVjY2QwIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzbmNmX3VzZXIiLCJlbnRpdGllc0lkIjoiU05DRiJ9.LZzZGg8Gu73_8HKzAPZJdR1E_e_NPyt-Q_d0lV7YzL2zjO0_q5-F08QG8nZYBoIAK_2C10Ho7qABHNTBeIR0Oe9NQnvyRn85YGLlx1k495e9p2-ZGNAh-JBbZ20ohEoghEbRAmR304gr_fKqVBM5QoxZrYdApMRbMfGuR_vGlUaQwnuG_p5uHu0wU_3SFItOtg1cSEWgviKnEt5gNuQ3D8zWAN1YtYivpqraYwQRdbENjXtxJCWsIgK-nclAWilan3vEGHGLBhZ8FCYw0U670YnlXOoe2wnFXEwt20maJzidPXA7XhEjbmUo9J-yEgEnjWspvcQhNwgsisx8P2Jyqw" -ORANGE_BEARER_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJSbXFOVTNLN0x4ck5SRmtIVTJxcTZZcTEya1RDaXNtRkw5U2NwbkNPeDBjIn0.eyJleHAiOjE2ODQ3NjY4NTksImlhdCI6MTY4NDE2MjA1OSwianRpIjoiNDE4ZGVlMmItYWFjNi00NTJlLWE5MGYtMzIyNzhlMzRhMjJiIiwiaXNzIjoiaHR0cDovLzE5Mi4xNjguMjExLjk1OjMyMDAvcmVhbG1zL2RldiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiJvcmFuZ2VfdXNlciIsInR5cCI6IkJlYXJlciIsImF6cCI6Im9wZmFiLWNsaWVudCIsInNlc3Npb25fc3RhdGUiOiI1Mjk3ODA1ZC1mYzczLTRkOTQtOTdmYy0wYzVhNTJjNDE0NDAiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzaWQiOiI1Mjk3ODA1ZC1mYzczLTRkOTQtOTdmYy0wYzVhNTJjNDE0NDAiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImdyb3VwcyI6IlJURTtBRE1JTjtSZWFkT25seSIsInByZWZlcnJlZF91c2VybmFtZSI6Im9yYW5nZV91c2VyIiwiZW50aXRpZXNJZCI6Ik9SQU5HRSJ9.KriZd2FZT39Yi8LD2lnVGJad9nEZ00W7rQzcTaFBbGjh9AnfgC6bEwmH20u0d61ldHA0KcH9_NC8LolNhRDjGqA6QDy8l-nA67VUK-CT_9uj9bW9oo8LVHCKn-pcK2t6LlPFexQjSeb0-rK9_jA-O-7rAdXQVEhYc1shxJYTNhNqtwmEBE_QApmDTocoIBPA6jUzqGWh0wUMswmKVPAUU1yWDBUBVDsRCcKVRAO2p-P64CxyXC0R1RRSGZ1i4jexggjeIfyrARXkJrjcAMYAu4HBi8k91vDd6KBiJs45TVm9_5rrW25ZASWTPUO4fuuaz3k47DTUGQBNstO483ZrkA" PUBLISHER_TEST_BEARER_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJSbXFOVTNLN0x4ck5SRmtIVTJxcTZZcTEya1RDaXNtRkw5U2NwbkNPeDBjIn0.eyJleHAiOjE2OTk5Nzk0NTEsImlhdCI6MTY5OTM3NDY1MSwianRpIjoiMjg5YTg5MDUtOTQ0YS00MGIwLWJkYTYtNzU5ODkzZWVmODFmIiwiaXNzIjoiaHR0cDovLzE5Mi4xNjguMjExLjk1OjMyMDAvYXV0aC9yZWFsbXMvZGV2IiwiYXVkIjoiYWNjb3VudCIsInN1YiI6InB1Ymxpc2hlcl90ZXN0IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoib3BmYWItY2xpZW50Iiwic2Vzc2lvbl9zdGF0ZSI6ImI1ZjUwZTc0LTYwOWEtNGI5MC1iMDhkLTFjNDQwM2MyMGMzYSIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsInNpZCI6ImI1ZjUwZTc0LTYwOWEtNGI5MC1iMDhkLTFjNDQwM2MyMGMzYSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZ3JvdXBzIjoiRGlzcGF0Y2hlcjtSZWFkT25seTtTdXBlcnZpc29yIiwicHJlZmVycmVkX3VzZXJuYW1lIjoicHVibGlzaGVyX3Rlc3QiLCJnaXZlbl9uYW1lIjoiIiwiZmFtaWx5X25hbWUiOiIifQ.RddLBhlhPMZst7TIRe10goMEZCriUchF9qNLBG889dnRP_YRh_bc-63cPeDbPG-YmeiXiQGJ3CJ9xGvc7uQl7iKLtCrBtTqn0A1IKOWmCrfaQ_czTyNKz5mrlU9HmzpO6H534Wjrx4uylwwhXrjuO7c06wZvn03tpNrBdoIVvCQqyInfY_QDoOttXU6-dj8S6aZavAsPDSNSrfzgiP33VT5Y0atoiHZ4gNvIeRAFIl6VrbAAQ7YkVDwzHAMPcA4QC4_k6t_m9t8KJ5otdzicDS6QJLV9hKUGzFPKJN60FSmscE9Gs7Uud_EGT-9GA_i53-1Pzxq6EWr-BkQ28kQDFQ" @@ -34,106 +31,6 @@ def test_add_rte_context(client, create_usecases, rte_auth_mocker): assert response.status_code == 201 -def test_add_da_context(client, create_usecases, da_auth_mocker): - context_data = { - "data": { - "ApDest": { - "apcity": "LE BOURGET", - "apid": "LFPB", - "aplat": 48.969, - "aplon": 2.441, - "apname": "LE BOURGET Airport" - }, - "Current_airspeed": 202.8167266845703, - "Latitude": 48.45396423339844, - "Longitude": 3.3079421520233154, - "wpList": [ - { - "wpid": "PG102", - "wpidx": 1, - "wplat": 48.720722, - "wplon": 2.590194 - }, - { - "wpid": "PG518", - "wpidx": 2, - "wplat": 48.816667, - "wplon": 2.489056 - }, - { - "wpid": "PG515", - "wpidx": 3, - "wplat": 48.916222, - "wplon": 2.459417 - } - ] - }, - "date": "2023-12-05T08:51:49.341641", - "use_case": "DA" - } - headers = {"Authorization": f"Bearer {DA_BEARER_TOKEN}"} - response = client.post( - "/api/v1/contexts", headers=headers, json=context_data - ) - logger.info(response.text) - assert response.status_code == 201 - - -def test_add_sncf_context(client, create_usecases, sncf_auth_mocker): - context_data = { - "date": "2022-12-01T16:08:29.060050", - "data": { - "trains": [ - { - "id_train": "12345", - "nb_passengers_onboard": 200, - "nb_passengers_connection": 13, - "latitude": "45.8574215", - "longitude": "4.4819996", - "speed": 300, - "failure": False, - } - ] - }, - "use_case": "SNCF", - } - - headers = {"Authorization": f"Bearer {SNCF_BEARER_TOKEN}"} - response = client.post( - "/api/v1/contexts", headers=headers, json=context_data - ) - logger.info(response.text) - assert response.status_code == 201 - - -def test_add_orange_context(client, create_usecases, orange_auth_mocker): - context_data = { - "date": "2022-11-01T16:08:29.060050", - "data": { - "applications": [ - { - "application_id": "1", - "KPI": { - "nb_req": 2000, - "nb_err": 100, - "nb_pl": 100, - "delay_avg": 1, - }, - "Horodatage": "date", - "KPI_composite": {"ratio_pl": "", "ratio_err": ""}, - } - ] - }, - "use_case": "ORANGE", - } - headers = {"Authorization": f"Bearer {SNCF_BEARER_TOKEN}"} - response = client.post( - "/api/v1/contexts", headers=headers, json=context_data - ) - logger.info(response.text) - assert response.status_code == 201 - - def test_health_check(client): response = client.get("/api/v1/health") assert response.status_code == 200 diff --git a/backend/event-service/tests/conftest.py b/backend/event-service/tests/conftest.py index 2d74c208..e4c71809 100644 --- a/backend/event-service/tests/conftest.py +++ b/backend/event-service/tests/conftest.py @@ -67,91 +67,12 @@ def rte_auth_mocker(client, mocker): ) -@pytest.fixture -def da_auth_mocker(client, mocker): - # Mock the keycloak.introspect method to return a valid response - mocker.patch( - "cab_common_auth.decorators.keycloak.introspect", - return_value={ - "exp": 1684401219, - "iat": 1683796419, - "jti": "a28734f6-f5c8-4130-8fb7-573d75c39d8c", - "iss": "http://192.168.211.95:3200/realms/dev", - "aud": "account", - "sub": "da_user", - "typ": "Bearer", - "azp": "opfab-client", - "session_state": "bd3b8610-1d05-4bdd-916b-61dcfe6d5e72", - "preferred_username": "da_user", - "email_verified": False, - "acr": "1", - "realm_access": {"roles": ["offline_access", "uma_authorization"]}, - "resource_access": { - "account": { - "roles": [ - "manage-account", - "manage-account-links", - "view-profile", - ] - } - }, - "scope": "email profile", - "sid": "bd3b8610-1d05-4bdd-916b-61dcfe6d5e72", - "groups": "RTE;ADMIN;ReadOnly", - "entitiesId": "DA", - "client_id": "opfab-client", - "username": "da_user", - "active": True, - }, - ) - - -@pytest.fixture -def sncf_auth_mocker(client, mocker): - # Mock the keycloak.introspect method to return a valid response - mocker.patch( - "cab_common_auth.decorators.keycloak.introspect", - return_value={ - "exp": 1684413915, - "iat": 1683809115, - "jti": "6f63636a-625a-4926-9684-6d5ed3b80e2a", - "iss": "http://192.168.211.95:3200/realms/dev", - "aud": "account", - "sub": "sncf_user", - "typ": "Bearer", - "azp": "opfab-client", - "session_state": "0dee604d-5c03-416c-8d95-59b0aa95b61a", - "preferred_username": "sncf_user", - "email_verified": False, - "acr": "1", - "realm_access": {"roles": ["offline_access", "uma_authorization"]}, - "resource_access": { - "account": { - "roles": [ - "manage-account", - "manage-account-links", - "view-profile", - ] - } - }, - "scope": "email profile", - "sid": "0dee604d-5c03-416c-8d95-59b0aa95b61a", - "entitiesId": "SNCF", - "client_id": "opfab-client", - "username": "sncf_user", - "active": True, - }, - ) - - @pytest.fixture def mock_of_create_cards_request(requests_mock): mock_response_cards = {"id": "string", "uid": "string"} requests_mock.post("http://op/cards", json=mock_response_cards) mock_response_historic = {} - requests_mock.post( - "http://historic/api/v1/traces", json=mock_response_historic - ) + requests_mock.post("http://historic/api/v1/traces", json=mock_response_historic) @pytest.fixture(scope="function") @@ -161,32 +82,13 @@ def create_usecases(client): db.create_all() - da_use_case = UseCaseModel( - name="DA", - event_manager_class="DAEventManager", - metadata_schema_class="MetadataSchemaDA", - ) - - orange_use_case = UseCaseModel( - name="ORANGE", - event_manager_class="OrangeEventManager", - metadata_schema_class="MetadataSchemaOrange", - ) rte_use_case = UseCaseModel( name="RTE", event_manager_class="RTEEventManager", metadata_schema_class="MetadataSchemaRTE", ) - sncf_use_case = UseCaseModel( - name="SNCF", - event_manager_class="SNCFEventManager", - metadata_schema_class="MetadataSchemaSNCF", - ) - db.session.add(da_use_case) - db.session.add(orange_use_case) db.session.add(rte_use_case) - db.session.add(sncf_use_case) db.session.commit() # add use_case_factory use_case_factory = current_app.use_case_factory diff --git a/backend/event-service/tests/test_views.py b/backend/event-service/tests/test_views.py index 3a0d9297..e63424f2 100644 --- a/backend/event-service/tests/test_views.py +++ b/backend/event-service/tests/test_views.py @@ -103,100 +103,6 @@ def test_update_rte_event_if_exist( assert data[0]["criticality"] == "HIGH" -def test_add_da_event( - client, create_usecases, da_auth_mocker, mock_of_create_cards_request -): - event_data = { - "criticality": "HIGH", - "title": "90 PRESS: CABIN ALT TOO HI", - "description": "Cabin altitude exceeding: 8,300 ft, OR 14,200 ft when high airfield operation is active.", - "data": { - "system": "AIR CONDITIONING AND PRESSURIZATION", - "event_type": "90 PRESS: CABIN ALT TOO HI", - "id_plane" : "1" - }, - "use_case": "DA", - } - headers = {"Authorization": f"Bearer {DA_BEARER_TOKEN}"} - response = client.post("/api/v1/events", headers=headers, json=event_data) - logger.info(response.text) - logger.error(response.text) - print(response.text) - assert response.status_code == 201 - - -def test_add_sncf_event( - client, create_usecases, sncf_auth_mocker, mock_of_create_cards_request -): - event_data = { - "title": "PASSENGER - TGV 8404", - "criticality": "MEDIUM", - "data": { - "agent_id": "0", - "agent_position": [220, 2], - "delay": 55, - "event_type": "PASSENGER", - "id_train": "8404", - "malfunction_stop_position": [94, 2], - "num_rame": "18", - "tmp_rame": "27", - }, - "start_date": "2023-04-11T06:20:12", - "description": "0 is having PASSENGER malfunction", - "is_active": True, - "use_case": "SNCF", - } - - headers = {"Authorization": f"Bearer {SNCF_BEARER_TOKEN}"} - response = client.post("/api/v1/events", headers=headers, json=event_data) - logger.info(response.text) - assert response.status_code == 201 - - -def test_update_sncf_event_if_exist( - client, create_usecases, sncf_auth_mocker, mock_of_create_cards_request -): - - event_data = { - "title": "PASSENGER - TGV 8404", - "criticality": "MEDIUM", - "data": { - "agent_id": "0", - "agent_position": [220, 2], - "delay": 55, - "event_type": "PASSENGER", - "id_train": "8404", - "malfunction_stop_position": [94, 2], - "num_rame": "18", - "tmp_rame": "27", - }, - "start_date": "2023-04-11T06:20:12", - "description": "0 is having PASSENGER malfunction", - "is_active": True, - "use_case": "SNCF", - } - - headers = {"Authorization": f"Bearer {SNCF_BEARER_TOKEN}"} - - # Create intial event - response = client.post("/api/v1/events", headers=headers, json=event_data) - assert response.status_code == 201 - data = json.loads(response.data) - assert data["criticality"] == "MEDIUM" - - # Create with same id_train - event_data["criticality"] = "HIGH" - response = client.post("/api/v1/events", headers=headers, json=event_data) - assert response.status_code == 201 - - # Verify their is only one event - response = client.get("/api/v1/events", headers=headers) - assert response.status_code == 200 - data = json.loads(response.data) - assert len(data) == 1 - assert data[0]["criticality"] == "HIGH" - - def test_health_check(client): response = client.get("/api/v1/health") assert response.status_code == 200 diff --git a/backend/recommendation-service/requirements.txt b/backend/recommendation-service/requirements.txt index 29719dc4..7eb1ae7c 100644 Binary files a/backend/recommendation-service/requirements.txt and b/backend/recommendation-service/requirements.txt differ diff --git a/backend/recommendation-service/tests/conftest.py b/backend/recommendation-service/tests/conftest.py index 747faccb..5e42b9ba 100644 --- a/backend/recommendation-service/tests/conftest.py +++ b/backend/recommendation-service/tests/conftest.py @@ -64,122 +64,6 @@ def rte_auth_mocker(client, mocker): ) -@pytest.fixture -def da_auth_mocker(client, mocker): - # Mock the keycloak.introspect method to return a valid response - mocker.patch( - "cab_common_auth.decorators.keycloak.introspect", - return_value={ - "exp": 1684401219, - "iat": 1683796419, - "jti": "a28734f6-f5c8-4130-8fb7-573d75c39d8c", - "iss": "http://192.168.211.95:3200/realms/dev", - "aud": "account", - "sub": "da_user", - "typ": "Bearer", - "azp": "opfab-client", - "session_state": "bd3b8610-1d05-4bdd-916b-61dcfe6d5e72", - "preferred_username": "da_user", - "email_verified": False, - "acr": "1", - "realm_access": {"roles": ["offline_access", "uma_authorization"]}, - "resource_access": { - "account": { - "roles": [ - "manage-account", - "manage-account-links", - "view-profile", - ] - } - }, - "scope": "email profile", - "sid": "bd3b8610-1d05-4bdd-916b-61dcfe6d5e72", - "groups": "RTE;ADMIN;ReadOnly", - "entitiesId": "DA", - "client_id": "opfab-client", - "username": "da_user", - "active": True, - }, - ) - - -@pytest.fixture -def sncf_auth_mocker(client, mocker): - # Mock the keycloak.introspect method to return a valid response - mocker.patch( - "cab_common_auth.decorators.keycloak.introspect", - return_value={ - "exp": 1684413915, - "iat": 1683809115, - "jti": "6f63636a-625a-4926-9684-6d5ed3b80e2a", - "iss": "http://192.168.211.95:3200/realms/dev", - "aud": "account", - "sub": "sncf_user", - "typ": "Bearer", - "azp": "opfab-client", - "session_state": "0dee604d-5c03-416c-8d95-59b0aa95b61a", - "preferred_username": "sncf_user", - "email_verified": False, - "acr": "1", - "realm_access": {"roles": ["offline_access", "uma_authorization"]}, - "resource_access": { - "account": { - "roles": [ - "manage-account", - "manage-account-links", - "view-profile", - ] - } - }, - "scope": "email profile", - "sid": "0dee604d-5c03-416c-8d95-59b0aa95b61a", - "entitiesId": "SNCF", - "client_id": "opfab-client", - "username": "sncf_user", - "active": True, - }, - ) - - -@pytest.fixture -def orange_auth_mocker(client, mocker): - # Mock the keycloak.introspect method to return a valid response - mocker.patch( - "cab_common_auth.decorators.keycloak.introspect", - return_value={ - "exp": 1684766859, - "iat": 1684162059, - "jti": "418dee2b-aac6-452e-a90f-32278e34a22b", - "iss": "http://192.168.211.95:3200/realms/dev", - "aud": "account", - "sub": "orange_user", - "typ": "Bearer", - "azp": "opfab-client", - "session_state": "5297805d-fc73-4d94-97fc-0c5a52c41440", - "preferred_username": "orange_user", - "email_verified": False, - "acr": "1", - "realm_access": {"roles": ["offline_access", "uma_authorization"]}, - "resource_access": { - "account": { - "roles": [ - "manage-account", - "manage-account-links", - "view-profile", - ] - } - }, - "scope": "email profile", - "sid": "5297805d-fc73-4d94-97fc-0c5a52c41440", - "groups": "RTE;ADMIN;ReadOnly", - "entitiesId": "ORANGE", - "client_id": "opfab-client", - "username": "orange_user", - "active": True, - }, - ) - - @pytest.fixture(scope="function") def create_usecases(client): with client.application.app_context(): @@ -187,13 +71,9 @@ def create_usecases(client): db.create_all() - da_use_case = UseCaseModel(name="DA", manager_class="DAManager") rte_use_case = UseCaseModel(name="RTE", manager_class="RTEManager") - sncf_use_case = UseCaseModel(name="SNCF", manager_class="SNCFManager") - db.session.add(da_use_case) db.session.add(rte_use_case) - db.session.add(sncf_use_case) db.session.commit() # add use_case_factory use_case_factory = current_app.use_case_factory diff --git a/backend/recommendation-service/tests/test_views.py b/backend/recommendation-service/tests/test_views.py index 01c9ae92..a849ad82 100644 --- a/backend/recommendation-service/tests/test_views.py +++ b/backend/recommendation-service/tests/test_views.py @@ -22,45 +22,6 @@ def test_rte_get_recommendation(client, create_usecases, rte_auth_mocker): assert response.status_code == 200 -def test_sncf_get_recommendation(client, create_usecases, sncf_auth_mocker): - recommendation_data = {} - # Opening JSON file - with open("tests/tests_resources/sncf_recommendation.json") as json_file: - recommendation_data = json.load(json_file) - headers = {"Authorization": f"Bearer {SNCF_BEARER_TOKEN}"} - response = client.post( - "/api/v1/recommendation", headers=headers, json=recommendation_data - ) - - assert response.status_code == 200 - - -def test_da_get_recommendation_1(client, create_usecases, da_auth_mocker): - recommendation_data = {} - # Opening JSON file - with open("tests/tests_resources/da_recommendation_1.json") as json_file: - recommendation_data = json.load(json_file) - headers = {"Authorization": f"Bearer {DA_BEARER_TOKEN}"} - response = client.post( - "/api/v1/recommendation", headers=headers, json=recommendation_data - ) - - assert response.status_code == 200 - - -def test_da_get_recommendation_2(client, create_usecases, da_auth_mocker): - recommendation_data = {} - # Opening JSON file - with open("tests/tests_resources/da_recommendation_2.json") as json_file: - recommendation_data = json.load(json_file) - headers = {"Authorization": f"Bearer {DA_BEARER_TOKEN}"} - response = client.post( - "/api/v1/recommendation", headers=headers, json=recommendation_data - ) - - assert response.status_code == 200 - - def test_health_check(client): response = client.get("/api/v1/health") assert response.status_code == 200 diff --git a/backend/recommendation-service/tests/tests_resources/da_recommendation_1.json b/backend/recommendation-service/tests/tests_resources/da_recommendation_1.json deleted file mode 100644 index 2b87b1e7..00000000 --- a/backend/recommendation-service/tests/tests_resources/da_recommendation_1.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "event": { - "event_type": "90 PRESS : CABIN ALT TOO HIGH" - } -} \ No newline at end of file diff --git a/backend/recommendation-service/tests/tests_resources/da_recommendation_2.json b/backend/recommendation-service/tests/tests_resources/da_recommendation_2.json deleted file mode 100644 index 7747665d..00000000 --- a/backend/recommendation-service/tests/tests_resources/da_recommendation_2.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "event": { - "event_type": "ENG1: AUTO SHUTDOWN" - } -} \ No newline at end of file diff --git a/backend/recommendation-service/tests/tests_resources/sncf_recommendation.json b/backend/recommendation-service/tests/tests_resources/sncf_recommendation.json deleted file mode 100644 index ff61e4b3..00000000 --- a/backend/recommendation-service/tests/tests_resources/sncf_recommendation.json +++ /dev/null @@ -1,196 +0,0 @@ -{ - "context": { - "direction_agents": [ - 0, - 0, - 0 - ], - "list_of_target": { - "0": [ - [ - 250, - 2 - ], - [ - 222, - 2 - ], - [ - 204, - 2 - ], - [ - 160, - 2 - ], - [ - 130, - 2 - ], - [ - 116, - 2 - ], - [ - 100, - 6 - ], - [ - 70, - 2 - ], - [ - 52, - 2 - ], - [ - 42, - 2 - ], - [ - 32, - 2 - ], - [ - 21, - 2 - ], - [ - 7, - 2 - ] - ], - "1": [ - [ - 250, - 2 - ], - [ - 222, - 2 - ], - [ - 204, - 7 - ], - [ - 160, - 2 - ], - [ - 130, - 2 - ], - [ - 116, - 2 - ], - [ - 100, - 6 - ], - [ - 70, - 2 - ], - [ - 52, - 2 - ], - [ - 42, - 2 - ], - [ - 32, - 2 - ], - [ - 21, - 2 - ], - [ - 7, - 2 - ] - ], - "2": [ - [ - 250, - 2 - ], - [ - 222, - 2 - ], - [ - 204, - 7 - ], - [ - 160, - 2 - ], - [ - 130, - 2 - ], - [ - 116, - 2 - ], - [ - 100, - 6 - ], - [ - 70, - 2 - ], - [ - 52, - 2 - ], - [ - 42, - 2 - ], - [ - 32, - 2 - ], - [ - 8, - 7 - ] - ] - }, - "position_agents": { - "0": [ - 112, - 5 - ], - "1": [ - 260, - 2 - ], - "2": [ - 295, - 2 - ] - } - }, - "event": { - "event_type" : "PASSENGER", - "agent_id": 0, - "agent_position": [ - 112, - 5 - ], - "malfunction_stop_position": [ - 100, - 6 - ], - "delay": 382 - } -} \ No newline at end of file diff --git a/config/dev/cab-standalone/docker-compose.yml b/config/dev/cab-standalone/docker-compose.yml index 38fd4150..99e45c51 100644 --- a/config/dev/cab-standalone/docker-compose.yml +++ b/config/dev/cab-standalone/docker-compose.yml @@ -7,7 +7,6 @@ services: context: ../../../backend dockerfile: Context-Service-Dockerfile environment: - - CORRELATION_SERVICE=http://cab_correlation:5000 - DATABASE_URL=postgresql://postgres:postgres@db_postgres_context:5432/cab-context - FLASK_APP=app:create_app('dev') - PYTHONPATH=/code @@ -136,13 +135,9 @@ services: context: ../../../frontend dockerfile: Dockerfile args: - VITE_DA_SIMU: ${VITE_DA_SIMU} - VITE_SNCF_SIMU: ${VITE_SNCF_SIMU} VITE_RTE_SIMU: ${VITE_RTE_SIMU} restart: unless-stopped environment: - - VITE_DA_SIMU=${VITE_DA_SIMU} - - VITE_SNCF_SIMU=${VITE_SNCF_SIMU} - VITE_RTE_SIMU=${VITE_RTE_SIMU} volumes: - './ui-config:/usr/share/nginx/html/opfab' @@ -150,7 +145,6 @@ services: ports: - '3200:80' depends_on: - - cabcorrelation - cabrecommendation - cabevent - cabcontext @@ -159,54 +153,6 @@ services: - businessconfig - cards-consultation - cabcorrelation: - container_name: cab_correlation - image: cab/cabcorrelation - build: - context: ../../../backend - dockerfile: Correlation-Service-Dockerfile - restart: unless-stopped - environment: - - CARDS_PUBLICATION_SERVICE=http://cards-publication:8080 - - GATEWAY_SERVICE=http://frontend:80 - - HISTORIC_SERVICE=http://cabhistoric:5000 - - DATABASE_URL=postgresql://postgres:postgres@db_postgres_correlation:5432/cab-correlation - - PYTHONPATH=/code - - FLASK_APP=app:create_app('dev', scheduler=True) - # - FLASK_ENV=development - - URL_INTROSPECT="http://frontend:80/auth/check_token" - - KEYCLOAK_SERVER_URL="http://frontend:80/auth/" - - CONTEXT_URL=http://cabcontext:5000 - - EVENT_URL=http://cabevent:5000 - - CAB_USERNAME=publisher_test - - CAB_PASSWORD=test - - AUTH_DISABLED=True - - DEFAULT_USE_CASE=ORANGE - - TZ=UTC # Set timezone to UTC - - command: sh -c "./entrypoint.sh" - ports: - - 5300:5000 - volumes: - - ./../../../backend/correlation-service:/code - depends_on: - - db_postgres_correlation - - cabevent - - cabcontext - - db_postgres_correlation: - container_name: db_postgres_correlation - image: postgres:14.7 - environment: - - POSTGRES_HOST_AUTH_METHOD=trust - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - - POSTGRES_DB=cab-correlation - ports: - - '5435:5432' - volumes: - - postgres_correlation_data:/var/lib/postgresql/data/ - cabrecommendation: container_name: cab_recommendation image: cab/cabrecommendation @@ -416,7 +362,6 @@ volumes: postgres_context_data: postgres_event_data: postgres_historic_data: - postgres_correlation_data: postgres_recommendation_data: postgres_capitalization_data: pgadmin: diff --git a/config/dev/cab-standalone/nginx-cors-permissive.conf b/config/dev/cab-standalone/nginx-cors-permissive.conf index 4f1856bf..3a6979ac 100644 --- a/config/dev/cab-standalone/nginx-cors-permissive.conf +++ b/config/dev/cab-standalone/nginx-cors-permissive.conf @@ -273,27 +273,6 @@ server { proxy_set_header X-Forwarded-For $remote_addr; } - # TODO: correlation service should not be exposed - location /cab_correlation/ { - - # enables `ng serve` mode - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' '*'; - add_header 'Access-Control-Allow-Headers' '*'; - add_header 'Content-Length' 0; - add_header 'Vary' 'Origin'; - add_header 'Vary' 'Access-Control-Request-Method' ; - add_header 'Vary' 'Access-Control-Request-Headers'; - return 204; - } - - proxy_set_header Host $http_host; - proxy_pass http://cab_correlation:5000/; - proxy_set_header X-Forwarded-For $remote_addr; - } - location /cab_recommendation/ { # enables `ng serve` mode diff --git a/config/dev/cab-standalone/nginx-kubernetes.conf b/config/dev/cab-standalone/nginx-kubernetes.conf index 400d4e4c..0a47b524 100644 --- a/config/dev/cab-standalone/nginx-kubernetes.conf +++ b/config/dev/cab-standalone/nginx-kubernetes.conf @@ -178,20 +178,6 @@ server { proxy_set_header X-Forwarded-For $remote_addr; } - location /cab_correlation/ { - add_header Cache-Control "no-cache"; - # This will make only GET request possible through nginx - # This is added since GET operation are supposed - # to be external and requires authentication - # the POST request should be between services without authenthentication - if ($request_method != 'GET') { - return 405; - } - - proxy_pass http://cab-correlation.cab-dev.svc.cluster.local:5000/; - proxy_set_header X-Forwarded-For $remote_addr; - } - location /cab_recommendation/ { add_header Cache-Control "no-cache"; proxy_pass http://cab-recommendation.cab-dev.svc.cluster.local:5000/; diff --git a/config/dev/cab-standalone/nginx.conf b/config/dev/cab-standalone/nginx.conf index 424683e4..bf718b7e 100644 --- a/config/dev/cab-standalone/nginx.conf +++ b/config/dev/cab-standalone/nginx.conf @@ -163,20 +163,6 @@ server { proxy_set_header X-Forwarded-For $remote_addr; } - location /cab_correlation/ { - # This will make only GET request possible through nginx - # This is added since GET operation are supposed - # to be external and requires authentication - # the POST request should be between services without authenthentication - if ($request_method != 'GET') { - return 405; - } - - proxy_set_header Host $http_host; - proxy_pass http://cab_correlation:5000/; - proxy_set_header X-Forwarded-For $remote_addr; - } - location /cab_recommendation/ { proxy_set_header Host $http_host; proxy_pass http://cab_recommendation:5000/; diff --git a/docs/use_case_managment.md b/docs/use_case_managment.md new file mode 100644 index 00000000..856a2af5 --- /dev/null +++ b/docs/use_case_managment.md @@ -0,0 +1,271 @@ +# InteractiveAI: Adding a New Usecase + +## Setup Instructions + +### 1. Adding Resources for InteractiveAI Services + +Before starting InteractiveAI, it's recommended to set up the following services: + +#### 1.1 Event Service + +To set up the Event Service for your use case (RTE), follow these steps: + +#### 1. Create a Folder and Files + +Start by creating a folder named `RTE` under `backend/event-service/resources` with the following files: + +##### `event_manager.py` + +event_manager.py defines a custom event manager (RTEEventManager) tailored for the RTE use case within InteractiveAI, allowing customization of event handling behaviors, such as ensuring uniqueness based on specified fields. + + +```python +# backend/event-service/resources/RTE/event_manager.py + +from api.event_manager.base_event_manager import BaseEventManager + +class RTEEventManager(BaseEventManager): + def __init__(self): + super().__init__() + self.use_case = "RTE" + self.use_case_process = "cabProcess" + + # Optional: Customize Event Uniqueness + def get_unique_fields(self, data): + """ + Override to specify unique fields for event uniqueness. + + This method specifies the fields on which InteractiveAI will ensure event uniqueness. + """ + input_line = data["data"].get("line") + return {"line": input_line} +``` + +##### `schemas.py` + +schemas.py defines the metadata schema (MetadataSchemaRTE) used by InteractiveAI to validate and structure incoming events specific to the RTE use case, ensuring data consistency and compliance with predefined formats and rules. + +```python +# backend/event-service/resources/RTE/schemas.py + +from apiflask.fields import Float, String, Dict +from apiflask.validators import OneOf +from api.schemas import MetadataSchema + +class MetadataSchemaRTE(MetadataSchema): + event_type = String( + required=True, + validate=OneOf(["KPI", "anticipation", "agent", "consignation"]), + ) + creation_date = String() + zone = String(validate=OneOf(["Est", "Ouest", "Centre"])) + line = String(required=True) + flux = Float() + kpis = Dict(required=True) + event_context = String() +``` + +#### Optional: Customize Event Uniqueness + +The `RTEEventManager` class can override the `get_unique_fields` method to specify unique fields for ensuring event uniqueness in InteractiveAI. Modify this method according to your specific requirements and the data structure of your events. + +#### 2. Integration with InteractiveAI + +Further integration steps with InteractiveAI will depend on your specific deployment and configuration needs. + + +#### 1.2 Context Service + +#### Files for RTE in Context Service + +To integrate RTE with the Context Service, create the following files under `backend/context-service/resources/RTE`: + +###### `context_manager.py` + +`context_manager.py` defines a custom context manager (`RTEContextManager`) for the RTE use case within the Context Service, inheriting from `BaseContextManager` to manage context-related operations. + + +```python +# backend/context-service/resources/RTE/context_manager.py + +from api.context_manager.base_context_manager import BaseContextManager + +class RTEContextManager(BaseContextManager): + def __init__(self): + super().__init__() + self.use_case = "RTE" +``` + + +###### `schemas.py` + +`schemas.py` defines the metadata schema (`MetadataSchemaRTE`) used by the Context Service to validate and structure data specific to the RTE use case ensuring data integrity and adherence to predefined formats. + + +```python +# backend/context-service/resources/RTE/schemas.py + +from api.schemas import MetadataSchema +from apiflask.fields import Dict, String + +class MetadataSchemaRTE(MetadataSchema): + topology = String(allow_none=False) + observation = Dict(allow_none=False) +``` + + +#### 1.3 Recommendation Service + +No specific setup instructions provided. + +##### File for RTE in Recommendation Service + +To integrate RTE with the Recommendation Service, create the following file under `backend/recommendation-service/resources/RTE`: + +###### `manager.py` + +`manager.py` defines a custom recommendation manager (`RTEManager`) for the RTE use case within the Recommendation Service. It extends `BaseRecommendationManager` and overrides the `get_recommendation` method to generate RTE-specific recommendations based on `request_data`. +This file enables RTE-specific recommendation functionality within the Recommendation Service of InteractiveAI. + +```python +# backend/recommendation-service/resources/RTE/manager.py + +from api.manager.base_manager import BaseRecommendationManager + +class RTEManager(BaseRecommendationManager): + def __init__(self): + super().__init__() + + def get_recommendation(self, request_data): + """ + Override to provide recommendations specific to the RTE use case. + + This method generates and returns recommendations tailored for RTE. + """ + action_dict = {} + + output_json = { + "title": "recommendation", + "description": "description", + "use_case": "RTE", + "agent_type": "agent_type", + "actions": [action_dict], + } + + return [output_json] +``` + +### 2. Users, Groups, and Entities Administration + +InteractiveAI utilizes the user management system based on the OperatorFabric project. For detailed information, refer to the [OperatorFabric Documentation](https://opfab.github.io/documentation/current/deployment/#_users_groups_and_entities_administration). + +## Users, Groups, and Entities Administration + +After setting up InteractiveAI, follow these steps to manage users, groups, and entities: + +### 1. Users + +Retrieve a list of users: + +```bash +curl -v http://localhost:2103/users -H "Authorization:Bearer $token" -H "Content-Type:application/type" +``` + +Example Response: +```json +[ + {"login": "admin", "entities": ["RTE"], "groups": ["ADMIN"]}, + {"login": "rte_user", "entities": ["RTE"], "groups": ["ReadOnly", "RTE", "ADMIN", "Dispatcher"]} +] +``` + +### 2. Groups + +Retrieve a list of groups: + +```bash +curl http://localhost:2103/groups -H "Authorization:Bearer $token" -H "Content-Type:application/json" +``` + +Example Response: +```json +[ + {"id": "ADMIN", "name": "ADMINISTRATORS", "description": "The admin group", "realtime": false}, + {"id": "RTE", "name": "RTE France", "description": "RTE TSO Group", "realtime": false}, + {"id": "Dispatcher", "name": "Dispatcher", "description": "Dispatcher Group", "perimeters": ["cabProcess"], "realtime": true}, + {"id": "Planner", "name": "Planner", "description": "Planner Group", "perimeters": ["cabProcess"], "realtime": true}, + {"id": "Supervisor", "name": "Supervisor", "description": "Supervisor Group", "perimeters": ["cabProcess"], "realtime": true}, + {"id": "Manager", "name": "Manager", "description": "Manager Group", "realtime": false}, + {"id": "ReadOnly", "name": "ReadOnly", "description": "ReadOnly Group", "realtime": false} +] +``` + +### 3. Entities + +Retrieve a list of entities: + +```bash +curl http://localhost:2103/entities -H "Authorization:Bearer $token" -H "Content-Type:application/json" +``` + +Example Response: +```json +[ + {"id": "RTE", "name": "Electricity Transmission Network", "description": "Electricity Transmission Network", "entityAllowedToSendCard": true, "parents": ["IRT_MAIN"]}, + {"id": "IRT_MAIN", "name": "IRT Control Centers", "description": "IRT Control Centers", "entityAllowedToSendCard": false} +] +``` + +## Loading Event, Context, and Recommendation Resources + +Follow these steps to load resources for event, context, and recommendation: + +### 1. Event + +Post a new event use case: + +```bash +curl -X POST $url:3200/cab_event/api/v1/usecases -H "Content-type:application/json" -H "Authorization:Bearer $token" --data @$1.json -v +``` + +Example JSON (`rteEvent.json`): +```json +{ + "name": "RTE", + "event_manager_class": "RTEEventManager", + "metadata_schema_class": "MetadataSchemaRTE" +} +``` + +### 2. Context + +Post a new context use case: + +```bash +curl -X POST $url:3200/cabcontext/api/v1/usecases -H "Content-type:application/json" -H "Authorization:Bearer $token" --data @$1.json -v +``` + +Example JSON (`rteContext.json`): +```json +{ + "name": "RTE", + "context_manager_class": "RTEContextManager", + "metadata_schema_class": "MetadataSchemaRTE" +} +``` + +### 3. Recommendation + +Post a new recommendation use case: + +```bash +curl -X POST $url:3200/cab_recommendation/api/v1/usecases -H "Content-type:application/json" -H "Authorization:Bearer $token" --data @$1.json -v +``` + +Example JSON (`rteRecommendationUC.json`): +```json +{ + "name": "RTE", + "manager_class": "RTEManager" +} +``` diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 48a27196..04a91c8f 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -2,11 +2,7 @@ FROM node:20-alpine as build-step RUN mkdir -p /app WORKDIR /app COPY . /app -ARG VITE_DA_SIMU -ARG VITE_SNCF_SIMU ARG VITE_RTE_SIMU -ENV VITE_DA_SIMU=$VITE_DA_SIMU -ENV VITE_SNCF_SIMU=$VITE_SNCF_SIMU ENV VITE_RTE_SIMU=$VITE_RTE_SIMU RUN npm ci RUN npm run build diff --git a/frontend/env/.env b/frontend/env/.env index a7fac437..f66a278a 100644 --- a/frontend/env/.env +++ b/frontend/env/.env @@ -1,5 +1,4 @@ VITE_DEFAULT_LOCALE="en" VITE_FALLBACK_LOCALE="en" -VITE_DA_SIMU=$VITE_DA_SIMU -VITE_SNCF_SIMU=$VITE_SNCF_SIMU -VITE_RTE_SIMU=$VITE_RTE_SIMU \ No newline at end of file +VITE_RTE_SIMU=$VITE_RTE_SIMU +VITE_API="" \ No newline at end of file diff --git a/frontend/env/.env.demo b/frontend/env/.env.demo deleted file mode 100644 index f9be963d..00000000 --- a/frontend/env/.env.demo +++ /dev/null @@ -1,4 +0,0 @@ -VITE_API="https://frontend.cab-dev.irtsystemx.org" -VITE_DA_SIMU="http://192.168.209.166:4003" -VITE_SNCF_SIMU="http://192.168.209.166:5000" -VITE_RTE_SIMU="http://192.168.209.166:5100" \ No newline at end of file diff --git a/frontend/env/.env.development b/frontend/env/.env.development deleted file mode 100644 index 48ff4ac6..00000000 --- a/frontend/env/.env.development +++ /dev/null @@ -1,4 +0,0 @@ -VITE_API="http://192.168.211.95:3200" -VITE_DA_SIMU="http://192.168.209.166:4003" -VITE_SNCF_SIMU="http://192.168.209.166:5000" -VITE_RTE_SIMU="http://192.168.209.166:5100" \ No newline at end of file diff --git a/frontend/env/.env.docker b/frontend/env/.env.docker deleted file mode 100644 index 069341c0..00000000 --- a/frontend/env/.env.docker +++ /dev/null @@ -1 +0,0 @@ -VITE_API="http://localhost:3200" \ No newline at end of file diff --git a/frontend/env/.env.prod b/frontend/env/.env.prod deleted file mode 100644 index 83e3f8ab..00000000 --- a/frontend/env/.env.prod +++ /dev/null @@ -1,4 +0,0 @@ -VITE_API="http://192.168.208.57:3200" -VITE_DA_SIMU="http://192.168.209.166:4003" -VITE_SNCF_SIMU="http://192.168.209.166:5000" -VITE_RTE_SIMU="http://192.168.209.166:5100" \ No newline at end of file diff --git a/frontend/env/.env.production b/frontend/env/.env.production deleted file mode 100644 index 8eb9fa7d..00000000 --- a/frontend/env/.env.production +++ /dev/null @@ -1 +0,0 @@ -VITE_API="" \ No newline at end of file diff --git a/frontend/env/.env.simu b/frontend/env/.env.simu deleted file mode 100644 index 6422a5d5..00000000 --- a/frontend/env/.env.simu +++ /dev/null @@ -1,4 +0,0 @@ -VITE_API="http://192.168.209.166:3200" -VITE_DA_SIMU="http://192.168.209.166:4003" -VITE_SNCF_SIMU="http://192.168.209.166:5000" -VITE_RTE_SIMU="http://192.168.209.166:5100" \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 3e09776f..6cadbd8a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,9 +6,9 @@ "type": "module", "scripts": { "dev": "vite", - "dev:": "vite --mode", + "dev:mode": "vite --mode", "build": "run-p type-check \"build-only {@}\" --", - "build:": "vite build --mode", + "build:mode": "vite build --mode", "preview": "vite preview", "test": "run-p 'test:unit -- run' test:e2e", "test:coverage": "run-p test:unit:coverage test:e2e:coverage", diff --git a/frontend/src/components/organisms/Timeline/TreeNode.vue b/frontend/src/components/organisms/Timeline/TreeNode.vue index dd2fe98c..de864e73 100644 --- a/frontend/src/components/organisms/Timeline/TreeNode.vue +++ b/frontend/src/components/organisms/Timeline/TreeNode.vue @@ -45,6 +45,7 @@