11import asyncio
2+ import logging
23import re
34from abc import ABC
4- from typing import Any , Dict , Tuple
5+ from typing import Any , Dict , Optional , Tuple
56
67from fastapi import HTTPException
78
8- from src .api .models import App , Service , create_resource , delete_resource
9+ from src .api .models import App , Service , create_resource , delete_resource , get_resources
910from src .api .schemas import UserSchema
1011from src .api .tools .name import ResourceName
1112from src .api .tools .ssh import run_command
@@ -29,6 +30,26 @@ def parse_service_info(plugin_name: str, info_str: str) -> Dict:
2930 return result
3031
3132
33+ def parse_service_list (text : str ):
34+ """
35+ Extract the list of services from a formatted string.
36+ """
37+ lines = text .strip ().split ("\n " )
38+ apps = [
39+ line .strip () for line in lines if line .strip () and not line .startswith ("=====>" )
40+ ]
41+ return apps
42+
43+
44+ def get_user_id_from_service (name ) -> Optional [int ]:
45+ id = name .split ("_" , maxsplit = 1 )[0 ]
46+
47+ try :
48+ return int (id )
49+ except ValueError :
50+ return None
51+
52+
3253def extract_database_uri (text ):
3354 pattern = re .compile (
3455 r"\b(?:[a-z]+)://(?:[^:@\s]+):(?:[^:@\s]+)@(?:[^:@\s]+):\d+/\S+\b" ,
@@ -358,3 +379,37 @@ async def restart_database(
358379 return False , None
359380
360381 return True , message
382+
383+ @staticmethod
384+ async def sync_dokku_with_api_database () -> None :
385+ available_databases = (await DatabaseService .list_available_databases ())[1 ]
386+ services = {}
387+
388+ for plugin_name in available_databases :
389+ success , message = await run_command (f"{ plugin_name } :list" )
390+
391+ if not success :
392+ logging .warning (
393+ f"Could not recover { plugin_name } services list to sync with database"
394+ )
395+ continue
396+
397+ for name in parse_service_list (message ):
398+ if get_user_id_from_service (name ):
399+ services [f"{ plugin_name } :{ name } " ] = True
400+
401+ logging .warning ("[sync_dokku_w_service_database]::Syncing Dokku..." )
402+
403+ db_services = await get_resources (Service , offset = 0 , limit = None )
404+
405+ for service in db_services :
406+ services .pop (service ["name" ], None )
407+
408+ for service_name in services :
409+ plugin_name , service_name = service_name .split (":" , maxsplit = 1 )
410+ logging .warning (
411+ f"[sync_dokku_w_service_database]:{ plugin_name } :{ service_name } ::Destroying unused service..."
412+ )
413+ await run_command (f"--force { plugin_name } :destroy { service_name } " )
414+
415+ logging .warning ("[sync_dokku_w_service_database]::Sync complete." )
0 commit comments