11from __future__ import annotations
22
33import inspect
4- from pathlib import Path , PurePath
4+ from pathlib import Path
55from typing import Any
66
7- from InquirerPy import inquirer
8- from InquirerPy .validator import EmptyInputValidator
7+ from InquirerPy import inquirer # type: ignore
8+ from InquirerPy .validator import EmptyInputValidator # type: ignore
99from click import Command , Option
10+ import psutil # type: ignore
1011
1112from ..core .manage_json import read_json , write_json # type: ignore
1213from ..core .manage_templates import template_to_file
@@ -21,17 +22,28 @@ def __init__(
2122 ) -> None :
2223 self .network = network
2324 self .update = update
25+
26+ self .cpus : float = psutil .cpu_count (logical = True ) or 0
27+ self .memory : float = (
28+ psutil .virtual_memory ().available // 1024 ** 2 - 512 or 0
29+ )
30+
2431 self .ports : dict [str , int ] = {}
25- self .resources = dict [str , Any ]
32+ self .resources : dict [str , int ] = {}
33+
34+ if self .memory < 512 :
35+ print ("WARNING: RAM AMOUNT TOO LOW" )
36+ clear (2 )
2637
2738 # Construct service contents for docker-compose
2839 def service (self , name : str ) -> dict [str , Any ]:
2940 self .__get_ports ()
30- ports = [f"${{{ port } }}:${{{ port } }}" for port , _ in self .ports .items ()]
3141 expose = self .__expose ()
42+ not_exposed = set ([port for port in self .ports if port not in expose ])
43+ ports = set ([f"${{{ port } }}:${{{ port } }}" for port in not_exposed ])
3244 resources = self .__resources ()
3345
34- service = {
46+ service : dict [ str , Any ] = {
3547 "name" : name ,
3648 "build" : {"context" : f"./servers/{ name } /" },
3749 "env_file" : f"./servers/{ name } /.env" ,
@@ -68,29 +80,77 @@ def __get_ports(self) -> None:
6880
6981 if inquirer .confirm (
7082 message = f"Want to add { port_name } assigned to port { port } ? " ,
71- default = True ,
83+ default = False ,
7284 ).execute ():
7385 self .ports [port_name ] = port
7486
75- if inquirer .confirm (
76- message = "Want to add more ports? " , default = False
77- ).execute ():
78- break
87+ if inquirer .confirm (
88+ message = "Want to add more ports? " , default = False
89+ ).execute ():
90+ break
7991
80- def __expose (self ) -> set [int ]:
81- expose : set [int ] = set ()
92+ def __expose (self ) -> set [str ]:
93+ expose : set [str ] = set ()
8294
8395 for name , port in self .ports .items ():
96+ clear (1 )
97+
8498 if inquirer .confirm (
8599 message = f"Want to expose { name } assigned to { port } ? " ,
86100 default = False ,
87101 ).execute ():
88- expose .add (port )
102+ expose .add (f"${{ { name } }}" )
89103
90104 return expose
91105
92106 def __resources (self ) -> dict [str , Any ]:
93- return {}
107+ while True :
108+ cpus_limit : float = inquirer .number (
109+ message = "Select a limit of CPUs for this service: " ,
110+ min_allowed = 0 ,
111+ max_allowed = self .cpus ,
112+ float_allowed = True ,
113+ validate = EmptyInputValidator (),
114+ ).execute ()
115+ cpus_reservation : float = inquirer .number (
116+ message = "Select a CPUs allocation for this service: " ,
117+ min_allowed = 0 ,
118+ max_allowed = cpus_limit ,
119+ float_allowed = True ,
120+ validate = EmptyInputValidator (),
121+ ).execute ()
122+
123+ memory_limit : float = inquirer .number (
124+ message = "Select a limit of RAM for this service (in MB): " ,
125+ min_allowed = 0 ,
126+ max_allowed = self .memory ,
127+ float_allowed = True ,
128+ validate = EmptyInputValidator (),
129+ ).execute ()
130+ memory_reservation : float = inquirer .number (
131+ message = "Select a RAM allocation for this service (in MB): " ,
132+ min_allowed = 0 ,
133+ max_allowed = memory_limit ,
134+ float_allowed = True ,
135+ validate = EmptyInputValidator (),
136+ ).execute ()
137+
138+ if inquirer .confirm (
139+ message = "Confirm the RAM and CPU allocation for this service" ,
140+ default = False ,
141+ ).execute ():
142+ break
143+
144+ self .cpus -= cpus_limit
145+ self .memory -= memory_limit
146+
147+ return {
148+ "limits" : {"cpus" : cpus_limit , "memory" : memory_limit },
149+ "reservations" : {
150+ "cpus" : cpus_reservation ,
151+ "memory" : memory_reservation ,
152+ },
153+ }
94154
95155 # Construct env file contents
96156 def env (self , name : str ) -> dict [str , Any ]:
@@ -112,12 +172,10 @@ def __init__(self) -> None:
112172 super ().__init__ ()
113173
114174 def create (self ) -> Command :
115-
116175 help = ""
117176 options = [Option (["--network" ], is_flag = True , default = False )]
118177
119178 def callback (network : bool = False ) -> None :
120-
121179 services : set [dict [str , Any ]] = set ([])
122180 networks : set [str ] = set ([])
123181 envs : set [dict [str , Any ]] = set ([])
@@ -145,9 +203,11 @@ def callback(network: bool = False) -> None:
145203 services .add (service )
146204 envs .add (env )
147205
206+ clear (1 )
207+
148208 if not inquirer .confirm (
149209 message = f"Want to continue adding services? (Count: { len (services )} )" ,
150- default = True if len ( services ) < 2 else False ,
210+ default = False ,
151211 ).execute ():
152212 break
153213
@@ -169,7 +229,6 @@ def callback(network: bool = False) -> None:
169229 )
170230
171231 def update (self ) -> Command :
172-
173232 help = ""
174233 options = [Option ()]
175234
@@ -186,6 +245,7 @@ def callback() -> None:
186245 def __get_data (
187246 self , menu : Menus , get_service : bool = True , get_env : bool = True
188247 ) -> tuple [dict [str , Any ], dict [str , Any ]]:
248+ clear (1 )
189249
190250 name = self .__get_name (message = "Enter the name of the service: " )
191251
@@ -200,11 +260,18 @@ def __get_data(
200260 return (service , env )
201261
202262 def __get_name (self , message : str ) -> str :
203- return str (
204- inquirer .text (
263+ while True :
264+ name = inquirer .text (
205265 message = message , validate = EmptyInputValidator ()
206266 ).execute ()
207- )
267+
268+ if inquirer .confirm (
269+ message = f"Want to name this service { name } ? " ,
270+ default = False ,
271+ ).execute ():
272+ break
273+
274+ return str (name )
208275
209276 def __save_files (self , data : dict [str , Any ]) -> None :
210277 write_json (Path (), data )
0 commit comments