cloud-dock-cli 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cloud_dock_cli-0.1.0.dist-info/METADATA +116 -0
- cloud_dock_cli-0.1.0.dist-info/RECORD +9 -0
- cloud_dock_cli-0.1.0.dist-info/WHEEL +4 -0
- cloud_dock_cli-0.1.0.dist-info/entry_points.txt +2 -0
- cloud_dock_cli-0.1.0.dist-info/licenses/LICENSE +674 -0
- clouddock/__init__.py +5 -0
- clouddock/cli.py +270 -0
- clouddock/config.py +221 -0
- clouddock/prompts.py +237 -0
clouddock/prompts.py
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
|
|
5
|
+
from .config import (
|
|
6
|
+
CacheConfig,
|
|
7
|
+
CloudDockConfig,
|
|
8
|
+
ComputeConfig,
|
|
9
|
+
DatabaseConfig,
|
|
10
|
+
EnvironmentVariables,
|
|
11
|
+
validate_application_name,
|
|
12
|
+
validate_container_port,
|
|
13
|
+
validate_desired_count,
|
|
14
|
+
validate_image,
|
|
15
|
+
validate_positive_int,
|
|
16
|
+
validate_regions,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def prompt(
|
|
21
|
+
message: str,
|
|
22
|
+
default: str | None = None,
|
|
23
|
+
*,
|
|
24
|
+
validate: Callable[[str], str] | None = None,
|
|
25
|
+
) -> str:
|
|
26
|
+
suffix = f" [{default}]" if default is not None else ""
|
|
27
|
+
while True:
|
|
28
|
+
value = input(f"{message}{suffix}: ")
|
|
29
|
+
if value == "" and default is not None:
|
|
30
|
+
return default
|
|
31
|
+
if value == "":
|
|
32
|
+
if validate is None:
|
|
33
|
+
return ""
|
|
34
|
+
try:
|
|
35
|
+
validate(value)
|
|
36
|
+
except ValueError as exc:
|
|
37
|
+
print(f"Error: {exc}")
|
|
38
|
+
continue
|
|
39
|
+
return value
|
|
40
|
+
if validate is not None:
|
|
41
|
+
try:
|
|
42
|
+
value = validate(value)
|
|
43
|
+
return value
|
|
44
|
+
except ValueError as exc:
|
|
45
|
+
print(f"Error: {exc}")
|
|
46
|
+
continue
|
|
47
|
+
return value
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def prompt_yes_no(prompt_text: str) -> bool:
|
|
51
|
+
while True:
|
|
52
|
+
answer = input(f"{prompt_text} [Y/n]: ").strip().lower()
|
|
53
|
+
if answer in {"", "y", "yes"}:
|
|
54
|
+
return True
|
|
55
|
+
if answer in {"n", "no"}:
|
|
56
|
+
return False
|
|
57
|
+
print("Please answer yes or no.")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def prompt_regions() -> list[str]:
|
|
61
|
+
regions: list[str] = []
|
|
62
|
+
print("AWS regions:")
|
|
63
|
+
while True:
|
|
64
|
+
region = input("> ").strip()
|
|
65
|
+
if not region:
|
|
66
|
+
if regions:
|
|
67
|
+
break
|
|
68
|
+
print("Error: At least one region is required.")
|
|
69
|
+
continue
|
|
70
|
+
try:
|
|
71
|
+
regions.append(validate_regions([region])[0])
|
|
72
|
+
except ValueError as exc:
|
|
73
|
+
print(f"Error: {exc}")
|
|
74
|
+
continue
|
|
75
|
+
print(f"Added region: {region}")
|
|
76
|
+
return validate_regions(regions)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def prompt_compute_type() -> str:
|
|
80
|
+
while True:
|
|
81
|
+
print("Where do you want to run the application?")
|
|
82
|
+
print("> ECS Fargate")
|
|
83
|
+
print("> EKS")
|
|
84
|
+
choice = input("Choice: ").strip().lower()
|
|
85
|
+
if choice in {"ecs", "fargate", "ecs fargate"}:
|
|
86
|
+
return "ecs"
|
|
87
|
+
if choice in {"eks", "e k s"}:
|
|
88
|
+
return "eks"
|
|
89
|
+
print("Please choose ECS Fargate or EKS.")
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def prompt_environment_variables() -> dict[str, str]:
|
|
93
|
+
values: dict[str, str] = {}
|
|
94
|
+
print("Environment variables")
|
|
95
|
+
print("Press Enter without a key to finish.")
|
|
96
|
+
while True:
|
|
97
|
+
key = input("Key: ").strip()
|
|
98
|
+
if not key:
|
|
99
|
+
break
|
|
100
|
+
value = input("Value: ").strip()
|
|
101
|
+
if not value:
|
|
102
|
+
value = ""
|
|
103
|
+
if not key:
|
|
104
|
+
raise ValueError("Environment variable keys cannot be empty.")
|
|
105
|
+
values[key] = value
|
|
106
|
+
return values
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def collect_configuration() -> CloudDockConfig:
|
|
110
|
+
name = prompt("Application name:", validate=validate_application_name)
|
|
111
|
+
image = prompt("Docker image:", validate=validate_image)
|
|
112
|
+
port_input = prompt(
|
|
113
|
+
"Container port:",
|
|
114
|
+
default="8080",
|
|
115
|
+
validate=lambda value: str(validate_container_port(value)),
|
|
116
|
+
)
|
|
117
|
+
port = validate_container_port(port_input)
|
|
118
|
+
|
|
119
|
+
regions = prompt_regions()
|
|
120
|
+
|
|
121
|
+
compute_type = prompt_compute_type()
|
|
122
|
+
desired_count = prompt(
|
|
123
|
+
"Number of application instances:",
|
|
124
|
+
default="2",
|
|
125
|
+
validate=lambda value: str(validate_desired_count(value)),
|
|
126
|
+
)
|
|
127
|
+
cpu = prompt(
|
|
128
|
+
"CPU:",
|
|
129
|
+
default="256",
|
|
130
|
+
validate=lambda value: str(validate_positive_int(value, "CPU")),
|
|
131
|
+
)
|
|
132
|
+
memory = prompt(
|
|
133
|
+
"Memory (MB):",
|
|
134
|
+
default="512",
|
|
135
|
+
validate=lambda value: str(validate_positive_int(value, "Memory")),
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
database_enabled = prompt_yes_no("Do you need a database?")
|
|
139
|
+
database_type = None
|
|
140
|
+
if database_enabled:
|
|
141
|
+
while True:
|
|
142
|
+
db_choice = input(
|
|
143
|
+
"Database type [PostgreSQL/MySQL]: ").strip().lower()
|
|
144
|
+
if db_choice in {"postgres", "postgresql"}:
|
|
145
|
+
database_type = "postgres"
|
|
146
|
+
break
|
|
147
|
+
if db_choice in {"mysql"}:
|
|
148
|
+
database_type = "mysql"
|
|
149
|
+
break
|
|
150
|
+
print("Please choose PostgreSQL or MySQL.")
|
|
151
|
+
|
|
152
|
+
cache_enabled = prompt_yes_no("Do you need caching?")
|
|
153
|
+
cache_type = None
|
|
154
|
+
if cache_enabled:
|
|
155
|
+
while True:
|
|
156
|
+
cache_choice = input(
|
|
157
|
+
"Cache type [Redis/Memcached]: ").strip().lower()
|
|
158
|
+
if cache_choice in {"redis"}:
|
|
159
|
+
cache_type = "redis"
|
|
160
|
+
break
|
|
161
|
+
if cache_choice in {"memcached"}:
|
|
162
|
+
cache_type = "memcached"
|
|
163
|
+
break
|
|
164
|
+
print("Please choose Redis or Memcached.")
|
|
165
|
+
|
|
166
|
+
environment_variables = prompt_environment_variables()
|
|
167
|
+
|
|
168
|
+
return CloudDockConfig(
|
|
169
|
+
application_name=name,
|
|
170
|
+
image=image,
|
|
171
|
+
container_port=port,
|
|
172
|
+
regions=regions,
|
|
173
|
+
compute=ComputeConfig(
|
|
174
|
+
type=compute_type,
|
|
175
|
+
desired_count=int(desired_count),
|
|
176
|
+
cpu=int(cpu),
|
|
177
|
+
memory=int(memory),
|
|
178
|
+
),
|
|
179
|
+
database=DatabaseConfig(enabled=database_enabled, type=database_type),
|
|
180
|
+
cache=CacheConfig(enabled=cache_enabled, type=cache_type),
|
|
181
|
+
environment_variables=EnvironmentVariables(environment_variables),
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def display_name_for_compute(compute_type: str) -> str:
|
|
186
|
+
return "ECS Fargate" if compute_type == "ecs" else "EKS"
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def display_name_for_database(database_type: str | None) -> str:
|
|
190
|
+
if database_type == "postgres":
|
|
191
|
+
return "PostgreSQL"
|
|
192
|
+
if database_type == "mysql":
|
|
193
|
+
return "MySQL"
|
|
194
|
+
return "Disabled"
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def display_name_for_cache(cache_type: str | None) -> str:
|
|
198
|
+
if cache_type == "redis":
|
|
199
|
+
return "Redis"
|
|
200
|
+
if cache_type == "memcached":
|
|
201
|
+
return "Memcached"
|
|
202
|
+
return "Disabled"
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def render_summary(config: CloudDockConfig) -> str:
|
|
206
|
+
lines = [
|
|
207
|
+
"CloudDock configuration",
|
|
208
|
+
"",
|
|
209
|
+
f"Application: {config.application_name}",
|
|
210
|
+
f"Image: {config.image}",
|
|
211
|
+
f"Port: {config.container_port}",
|
|
212
|
+
"",
|
|
213
|
+
"Regions:",
|
|
214
|
+
]
|
|
215
|
+
for region in config.regions:
|
|
216
|
+
lines.append(f" - {region}")
|
|
217
|
+
|
|
218
|
+
lines.extend(
|
|
219
|
+
[
|
|
220
|
+
"",
|
|
221
|
+
"Compute:",
|
|
222
|
+
f" {display_name_for_compute(config.compute.type)}",
|
|
223
|
+
f" Instances: {config.compute.desired_count}",
|
|
224
|
+
f" CPU: {config.compute.cpu}",
|
|
225
|
+
f" Memory: {config.compute.memory} MB",
|
|
226
|
+
"",
|
|
227
|
+
"Database:",
|
|
228
|
+
f" {display_name_for_database(config.database.type) if config.database and config.database.enabled else 'Disabled'}",
|
|
229
|
+
"",
|
|
230
|
+
"Cache:",
|
|
231
|
+
f" {display_name_for_cache(config.cache.type) if config.cache and config.cache.enabled else 'Disabled'}",
|
|
232
|
+
"",
|
|
233
|
+
"Environment variables:",
|
|
234
|
+
f" {len(config.environment_variables.values)} configured",
|
|
235
|
+
]
|
|
236
|
+
)
|
|
237
|
+
return "\n".join(lines)
|