22
33import inspect
44from pathlib import Path
5- from typing import Any
5+ from random import choice
6+ from typing import Any , cast
67
78from InquirerPy import inquirer # type: ignore
89from InquirerPy .validator import EmptyInputValidator # type: ignore
910from click import Command , Option
10- from importlib_resources import files # type: ignore
11+ from importlib_resources import as_file , files # type: ignore
1112from yaspin import yaspin # type: ignore
1213
1314from ..core .copy_files import copy_files # type: ignore
@@ -108,19 +109,89 @@ def callback(
108109 data : dicts = read_json (path ) or {}
109110 compose : dicts = data .get ("compose" , {}) or {}
110111
111- services : set [dicts ] = set (compose .get ("services" , []))
112- networks : set [str ] = set (compose .get ("networks" , []))
113- envs : set [dicts ] = set (data .get ("envs" , []))
114-
115- if networks :
116- pass
117- if envs :
118- pass
112+ services : list [dicts ] = compose .get ("services" , []) or []
113+ networks : list [str ] = compose .get ("networks" , []) or []
114+ envs : list [dicts ] = data .get ("envs" , []) or []
119115
120116 if not services :
121117 print ("No services found. Use 'create' first." )
122118 return
123119
120+ def find_index_by_name (name : str ) -> int | None :
121+ for i , s in enumerate (services ):
122+ if s .get ("name" ) == name :
123+ return i
124+ return None
125+
126+ if remove :
127+ target = service
128+ if not target :
129+ names = [s .get ("name" ) for s in services if s .get ("name" )]
130+ if not names :
131+ print ("No services found." )
132+ return
133+ target = inquirer .select ( # type: ignore
134+ message = "Select a service to remove: " , choices = names
135+ ).execute ()
136+
137+ idx = find_index_by_name (target )
138+ if idx is None :
139+ print (f"Service '{ target } ' not found." )
140+ return
141+
142+ if confirm (msg = f"Remove service '{ target } '" ):
143+ services .pop (idx )
144+ envs = [
145+ e for e in envs if e .get ("CONTAINER_NAME" ) != target
146+ ]
147+ compose ["services" ] = services
148+ compose ["networks" ] = networks
149+ data ["compose" ] = compose
150+ data ["envs" ] = envs
151+ self .__save_files (data )
152+ print (f"Service '{ target } ' removed and files updated." )
153+
154+ elif add :
155+ name = service
156+ if not name :
157+ name = self .__get_name ("Enter the name of the service: " )
158+ if find_index_by_name (name ):
159+ if not confirm (
160+ msg = f"Service '{ name } ' already exists. Overwrite? "
161+ ):
162+ print ("Add cancelled." )
163+ return
164+ services = [s for s in services if s .get ("name" ) != name ]
165+ envs = [e for e in envs if e .get ("CONTAINER_NAME" ) != name ]
166+
167+ network = None
168+ if networks :
169+ network = inquirer .select ( # type: ignore
170+ message = "Select a network: " , choices = networks
171+ ).execute ()
172+ menu = Menus (network = network )
173+
174+ service_obj , env_obj = self .__get_data (menu , name )
175+ service_obj ["name" ] = name
176+ env_obj ["CONTAINER_NAME" ] = name
177+
178+ services .append (service_obj )
179+ envs .append (env_obj )
180+
181+ if confirm (msg = f"Add/Update service '{ name } '" ):
182+ compose ["services" ] = services
183+ compose ["networks" ] = networks
184+ data ["compose" ] = compose
185+ data ["envs" ] = envs
186+ self .__save_files (data )
187+ print (f"Service '{ name } ' removed and files updated." )
188+
189+ else :
190+ print ("Use --add or --remove flag." )
191+ print ("Use --services [service] for faster output." )
192+ for s in services :
193+ print (f" - { s .get ("name" )} " )
194+
124195 return Command (
125196 name = inspect .currentframe ().f_code .co_name , # type: ignore
126197 help = help ,
@@ -161,19 +232,15 @@ def callback(
161232 )
162233
163234 def __get_data (
164- self , menu : Menus , get_service : bool = True , get_env : bool = True
235+ self , menu : Menus , name : str | None = None
165236 ) -> tuple [dicts , dicts ]:
166237 clear (0.5 )
167238
168- name = self .__get_name (message = "Enter the name of the service: " )
169-
170- service = {}
171- if get_service :
172- service = menu .service (name = name )
239+ if not name :
240+ name = self .__get_name (message = "Enter the name of the service: " )
173241
174- env = {}
175- if get_env :
176- env = menu .env (name = name )
242+ service = menu .service (name = name )
243+ env = menu .env (name = name )
177244
178245 return (service , env )
179246
@@ -189,7 +256,7 @@ def __get_name(self, message: str) -> str:
189256
190257 return name
191258
192- @yaspin (text = "Creating files..." , color = "cyan" )
259+ @yaspin (text = "Saving files..." , color = "cyan" )
193260 def __save_files (self , data : dicts , build : bool = False ) -> None :
194261 tmps_path = files ("minecraft-docker-cli.assets.templates" )
195262 composer_template = tmps_path .joinpath ("docker-compose.yml.j2" )
@@ -199,9 +266,11 @@ def __save_files(self, data: dicts, build: bool = False) -> None:
199266 write_json (self .cwd .joinpath ("data.json" ), data )
200267
201268 composer : dicts = data .get ("composer" ) or {}
202- template_to_file (
203- composer_template , composer , self .cwd .joinpath ("docker-compose.yml" )
204- )
269+ with as_file (composer_template ) as composer_path : # type: ignore
270+ composer_path = cast (Path , composer_path )
271+ template_to_file (
272+ composer_path , composer , self .cwd .joinpath ("docker-compose.yml" )
273+ )
205274
206275 services : list [dicts ] = composer .get ("services" , []) or []
207276 names : list [str ] = [service .get ("name" ) for service in services ] # type: ignore
@@ -210,6 +279,8 @@ def __save_files(self, data: dicts, build: bool = False) -> None:
210279 envs : list [dicts ] = data .get ("envs" ) or []
211280 for env in envs :
212281 relative_path = f"servers/{ env .get ("CONTAINER_NAME" )} /.env" # type: ignore
213- template_to_file (
214- env_template , env , self .cwd .joinpath (relative_path )
215- )
282+ with as_file (env_template ) as env_path : # type: ignore
283+ env_path = cast (Path , env_path )
284+ template_to_file (
285+ env_path , env , self .cwd .joinpath (relative_path )
286+ )
0 commit comments