Skip to content

Commit b768a9b

Browse files
committed
Added Resources menu
Added psUtils to check for CPU count and RAM ammount of the system
1 parent ed984d8 commit b768a9b

File tree

3 files changed

+91
-23
lines changed

3 files changed

+91
-23
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ jinja2 = "^3.1.6"
3939
inquirerpy = "^0.3.4"
4040
yaspin = "^3.3.0"
4141
click = "^8.3.0"
42+
psutil = "^7.1.3"
4243

4344
[tool.poetry.group.dev.dependencies]
4445
black = "^25.9.0"

src/assets/templates/template.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"${HOST_PORT}:${HOST_PORT}"
1313
],
1414
"expose": [
15-
25565
15+
"${HOST_PORT}"
1616
],
1717
"networks": [
1818
"mc-network"

src/cli/builder.py

Lines changed: 89 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
from __future__ import annotations
22

33
import inspect
4-
from pathlib import Path, PurePath
4+
from pathlib import Path
55
from 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
99
from click import Command, Option
10+
import psutil # type: ignore
1011

1112
from ..core.manage_json import read_json, write_json # type: ignore
1213
from ..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

Comments
 (0)