gitarsenal-cli 1.1.1 ā 1.1.3
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.
- package/package.json +1 -1
- package/python/README.md +198 -35
- package/python/gitarsenal.py +434 -65
- package/python/gitarsenal_proxy_client.py +375 -0
- package/python/modal_proxy_service.py +317 -0
- package/python/requirements.txt +6 -0
- package/python/test_modalSandboxScript.py +225 -64
package/python/gitarsenal.py
CHANGED
@@ -9,6 +9,76 @@ import argparse
|
|
9
9
|
import sys
|
10
10
|
import os
|
11
11
|
import subprocess
|
12
|
+
import json
|
13
|
+
from pathlib import Path
|
14
|
+
|
15
|
+
def check_modal_auth():
|
16
|
+
"""Check if Modal is authenticated and guide user if not"""
|
17
|
+
try:
|
18
|
+
# Try to run a simple Modal command to check authentication
|
19
|
+
result = subprocess.run(["modal", "app", "list"],
|
20
|
+
capture_output=True, text=True, timeout=10)
|
21
|
+
|
22
|
+
# If the command was successful, Modal is authenticated
|
23
|
+
if result.returncode == 0:
|
24
|
+
return True
|
25
|
+
|
26
|
+
# Check for specific authentication errors
|
27
|
+
if "Token missing" in result.stderr or "Could not authenticate" in result.stderr:
|
28
|
+
print("\n" + "="*80)
|
29
|
+
print("š MODAL AUTHENTICATION REQUIRED")
|
30
|
+
print("="*80)
|
31
|
+
print("GitArsenal requires Modal authentication to create cloud environments.")
|
32
|
+
print("\nTo authenticate with Modal, you need to:")
|
33
|
+
print("1. Create a Modal account at https://modal.com if you don't have one")
|
34
|
+
print("2. Run the following command to get a token:")
|
35
|
+
print(" modal token new")
|
36
|
+
print("3. Then set up your credentials in GitArsenal:")
|
37
|
+
print(" ./gitarsenal.py credentials set modal_token")
|
38
|
+
print("\nAfter completing these steps, try your command again.")
|
39
|
+
print("="*80)
|
40
|
+
return False
|
41
|
+
|
42
|
+
# Other errors
|
43
|
+
print(f"ā ļø Modal command returned error: {result.stderr}")
|
44
|
+
return False
|
45
|
+
|
46
|
+
except FileNotFoundError:
|
47
|
+
print("\n" + "="*80)
|
48
|
+
print("ā MODAL CLI NOT INSTALLED")
|
49
|
+
print("="*80)
|
50
|
+
print("GitArsenal requires the Modal CLI to be installed.")
|
51
|
+
print("\nTo install Modal CLI, run:")
|
52
|
+
print(" pip install modal")
|
53
|
+
print("\nAfter installation, set up your credentials:")
|
54
|
+
print("1. Run 'modal token new' to authenticate")
|
55
|
+
print("2. Run './gitarsenal.py credentials set modal_token'")
|
56
|
+
print("="*80)
|
57
|
+
return False
|
58
|
+
except Exception as e:
|
59
|
+
print(f"ā ļø Error checking Modal authentication: {e}")
|
60
|
+
return False
|
61
|
+
|
62
|
+
def check_proxy_config():
|
63
|
+
"""Check if Modal proxy is configured"""
|
64
|
+
try:
|
65
|
+
# Import the proxy client
|
66
|
+
from gitarsenal_proxy_client import GitArsenalProxyClient
|
67
|
+
|
68
|
+
# Create client and load config
|
69
|
+
client = GitArsenalProxyClient()
|
70
|
+
config = client.load_config()
|
71
|
+
|
72
|
+
# Check if proxy URL and API key are configured
|
73
|
+
if "proxy_url" in config and "api_key" in config:
|
74
|
+
return True
|
75
|
+
else:
|
76
|
+
return False
|
77
|
+
except ImportError:
|
78
|
+
return False
|
79
|
+
except Exception as e:
|
80
|
+
print(f"ā ļø Error checking proxy configuration: {e}")
|
81
|
+
return False
|
12
82
|
|
13
83
|
def main():
|
14
84
|
parser = argparse.ArgumentParser(description="GitArsenal CLI - GPU-accelerated cloud environments")
|
@@ -47,8 +117,10 @@ def main():
|
|
47
117
|
sandbox_parser.add_argument("--repo-name", type=str, help="Repository name override")
|
48
118
|
sandbox_parser.add_argument("--setup-commands", type=str, nargs="+", help="Setup commands to run")
|
49
119
|
sandbox_parser.add_argument("--volume-name", type=str, help="Name of the Modal volume for persistent storage")
|
120
|
+
sandbox_parser.add_argument("--use-api", action="store_true", help="Use API for setup commands")
|
121
|
+
sandbox_parser.add_argument("--use-proxy", action="store_true", help="Use Modal proxy service instead of direct Modal access")
|
50
122
|
|
51
|
-
# SSH
|
123
|
+
# SSH command
|
52
124
|
ssh_parser = subparsers.add_parser("ssh", help="Create a Modal SSH container")
|
53
125
|
ssh_parser.add_argument("--gpu", type=str, default="A10G", choices=["A10G", "A100", "H100", "T4", "V100"],
|
54
126
|
help="GPU type (default: A10G)")
|
@@ -57,90 +129,387 @@ def main():
|
|
57
129
|
ssh_parser.add_argument("--setup-commands", type=str, nargs="+", help="Setup commands to run")
|
58
130
|
ssh_parser.add_argument("--volume-name", type=str, help="Name of the Modal volume for persistent storage")
|
59
131
|
ssh_parser.add_argument("--timeout", type=int, default=60, help="Container timeout in minutes (default: 60)")
|
132
|
+
ssh_parser.add_argument("--use-api", action="store_true", help="Use API for setup commands")
|
133
|
+
ssh_parser.add_argument("--use-proxy", action="store_true", help="Use Modal proxy service instead of direct Modal access")
|
134
|
+
|
135
|
+
# Proxy command
|
136
|
+
proxy_parser = subparsers.add_parser("proxy", help="Configure and use Modal proxy service")
|
137
|
+
proxy_subparsers = proxy_parser.add_subparsers(dest="proxy_command", help="Proxy command")
|
138
|
+
|
139
|
+
# Proxy configure command
|
140
|
+
proxy_configure_parser = proxy_subparsers.add_parser("configure", help="Configure Modal proxy service")
|
141
|
+
|
142
|
+
# Proxy status command
|
143
|
+
proxy_status_parser = proxy_subparsers.add_parser("status", help="Check Modal proxy service status")
|
144
|
+
|
145
|
+
# Proxy sandbox command
|
146
|
+
proxy_sandbox_parser = proxy_subparsers.add_parser("sandbox", help="Create a sandbox through Modal proxy")
|
147
|
+
proxy_sandbox_parser.add_argument("--gpu", type=str, default="A10G", choices=["A10G", "A100", "H100", "T4", "V100"],
|
148
|
+
help="GPU type (default: A10G)")
|
149
|
+
proxy_sandbox_parser.add_argument("--repo-url", type=str, help="Repository URL to clone")
|
150
|
+
proxy_sandbox_parser.add_argument("--repo-name", type=str, help="Repository name override")
|
151
|
+
proxy_sandbox_parser.add_argument("--setup-commands", type=str, nargs="+", help="Setup commands to run")
|
152
|
+
proxy_sandbox_parser.add_argument("--volume-name", type=str, help="Name of the Modal volume for persistent storage")
|
153
|
+
proxy_sandbox_parser.add_argument("--wait", action="store_true", help="Wait for sandbox to be ready")
|
154
|
+
|
155
|
+
# Proxy ssh command
|
156
|
+
proxy_ssh_parser = proxy_subparsers.add_parser("ssh", help="Create an SSH container through Modal proxy")
|
157
|
+
proxy_ssh_parser.add_argument("--gpu", type=str, default="A10G", choices=["A10G", "A100", "H100", "T4", "V100"],
|
158
|
+
help="GPU type (default: A10G)")
|
159
|
+
proxy_ssh_parser.add_argument("--repo-url", type=str, help="Repository URL to clone")
|
160
|
+
proxy_ssh_parser.add_argument("--repo-name", type=str, help="Repository name override")
|
161
|
+
proxy_ssh_parser.add_argument("--setup-commands", type=str, nargs="+", help="Setup commands to run")
|
162
|
+
proxy_ssh_parser.add_argument("--volume-name", type=str, help="Name of the Modal volume for persistent storage")
|
163
|
+
proxy_ssh_parser.add_argument("--timeout", type=int, default=60, help="Container timeout in minutes (default: 60)")
|
164
|
+
proxy_ssh_parser.add_argument("--wait", action="store_true", help="Wait for container to be ready")
|
60
165
|
|
61
166
|
args = parser.parse_args()
|
62
167
|
|
63
|
-
# If no command is provided, show help
|
64
168
|
if not args.command:
|
65
169
|
parser.print_help()
|
66
|
-
return
|
170
|
+
return 0
|
171
|
+
|
172
|
+
# For sandbox and SSH commands, check Modal authentication first
|
173
|
+
if args.command in ["sandbox", "ssh"]:
|
174
|
+
# Check if using proxy service
|
175
|
+
if hasattr(args, 'use_proxy') and args.use_proxy:
|
176
|
+
# Check if proxy is configured
|
177
|
+
if not check_proxy_config():
|
178
|
+
print("\nā ļø Modal proxy service is not configured.")
|
179
|
+
print("Please run './gitarsenal.py proxy configure' first.")
|
180
|
+
return 1
|
181
|
+
else:
|
182
|
+
# Check if Modal is authenticated
|
183
|
+
if not check_modal_auth():
|
184
|
+
print("\nā ļø Please authenticate with Modal before proceeding.")
|
185
|
+
return 1
|
186
|
+
|
187
|
+
# Try to load credentials and set Modal token if available
|
188
|
+
try:
|
189
|
+
from credentials_manager import CredentialsManager
|
190
|
+
credentials_manager = CredentialsManager()
|
191
|
+
credentials = credentials_manager.load_credentials()
|
192
|
+
|
193
|
+
if "modal_token" in credentials:
|
194
|
+
# Set the Modal token in the environment
|
195
|
+
os.environ["MODAL_TOKEN_ID"] = credentials["modal_token"]
|
196
|
+
print("ā
Using Modal token from credentials")
|
197
|
+
|
198
|
+
# Try to authenticate with the token
|
199
|
+
try:
|
200
|
+
token_result = subprocess.run(
|
201
|
+
["modal", "token", "set", credentials["modal_token"]],
|
202
|
+
capture_output=True, text=True
|
203
|
+
)
|
204
|
+
if token_result.returncode == 0:
|
205
|
+
print("ā
Successfully authenticated with Modal")
|
206
|
+
except Exception as e:
|
207
|
+
print(f"ā ļø Error setting Modal token: {e}")
|
208
|
+
except ImportError:
|
209
|
+
print("ā ļø Could not load credentials manager")
|
210
|
+
except Exception as e:
|
211
|
+
print(f"ā ļø Error loading credentials: {e}")
|
67
212
|
|
68
213
|
# Handle credentials commands
|
69
214
|
if args.command == "credentials":
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
cred_parser.print_help()
|
74
|
-
return 1
|
215
|
+
try:
|
216
|
+
from credentials_manager import CredentialsManager
|
217
|
+
credentials_manager = CredentialsManager()
|
75
218
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
219
|
+
if args.cred_command == "setup":
|
220
|
+
# Set up all credentials
|
221
|
+
print("š§ Setting up all credentials")
|
222
|
+
|
223
|
+
# Modal token
|
224
|
+
modal_token = credentials_manager.get_modal_token()
|
225
|
+
if modal_token:
|
226
|
+
print("ā
Modal token set")
|
227
|
+
else:
|
228
|
+
print("ā ļø Modal token not set")
|
229
|
+
|
230
|
+
# OpenAI API key
|
231
|
+
openai_api_key = credentials_manager.get_openai_api_key()
|
232
|
+
if openai_api_key:
|
233
|
+
print("ā
OpenAI API key set")
|
234
|
+
else:
|
235
|
+
print("ā ļø OpenAI API key not set")
|
236
|
+
|
237
|
+
# Hugging Face token
|
238
|
+
huggingface_token = credentials_manager.get_huggingface_token()
|
239
|
+
if huggingface_token:
|
240
|
+
print("ā
Hugging Face token set")
|
241
|
+
else:
|
242
|
+
print("ā ļø Hugging Face token not set")
|
243
|
+
|
244
|
+
# Weights & Biases API key
|
245
|
+
wandb_api_key = credentials_manager.get_wandb_api_key()
|
246
|
+
if wandb_api_key:
|
247
|
+
print("ā
Weights & Biases API key set")
|
248
|
+
else:
|
249
|
+
print("ā ļø Weights & Biases API key not set")
|
250
|
+
|
251
|
+
elif args.cred_command == "set":
|
252
|
+
# Set a specific credential
|
253
|
+
if args.key == "modal_token":
|
254
|
+
modal_token = credentials_manager.get_modal_token()
|
255
|
+
if modal_token:
|
256
|
+
print("ā
Modal token set")
|
257
|
+
else:
|
258
|
+
print("ā ļø Modal token not set")
|
259
|
+
elif args.key == "openai_api_key":
|
260
|
+
openai_api_key = credentials_manager.get_openai_api_key()
|
261
|
+
if openai_api_key:
|
262
|
+
print("ā
OpenAI API key set")
|
263
|
+
else:
|
264
|
+
print("ā ļø OpenAI API key not set")
|
265
|
+
elif args.key == "huggingface_token":
|
266
|
+
huggingface_token = credentials_manager.get_huggingface_token()
|
267
|
+
if huggingface_token:
|
268
|
+
print("ā
Hugging Face token set")
|
269
|
+
else:
|
270
|
+
print("ā ļø Hugging Face token not set")
|
271
|
+
elif args.key == "wandb_api_key":
|
272
|
+
wandb_api_key = credentials_manager.get_wandb_api_key()
|
273
|
+
if wandb_api_key:
|
274
|
+
print("ā
Weights & Biases API key set")
|
275
|
+
else:
|
276
|
+
print("ā ļø Weights & Biases API key not set")
|
277
|
+
|
278
|
+
elif args.cred_command == "get":
|
279
|
+
# Get a specific credential
|
280
|
+
credentials = credentials_manager.load_credentials()
|
281
|
+
if args.key in credentials:
|
282
|
+
# Mask the credential for security
|
283
|
+
value = credentials[args.key]
|
284
|
+
masked_value = value[:4] + "*" * (len(value) - 8) + value[-4:] if len(value) > 8 else "****"
|
285
|
+
print(f"{args.key}: {masked_value}")
|
286
|
+
else:
|
287
|
+
print(f"ā ļø {args.key} not found")
|
288
|
+
|
289
|
+
elif args.cred_command == "clear":
|
290
|
+
# Clear credentials
|
291
|
+
if args.key == "all":
|
292
|
+
credentials_manager.clear_all_credentials()
|
293
|
+
print("ā
All credentials cleared")
|
294
|
+
else:
|
295
|
+
if credentials_manager.clear_credential(args.key):
|
296
|
+
print(f"ā
{args.key} cleared")
|
297
|
+
else:
|
298
|
+
print(f"ā ļø {args.key} not found")
|
299
|
+
|
300
|
+
elif args.cred_command == "list":
|
301
|
+
# List all credentials
|
302
|
+
credentials = credentials_manager.load_credentials()
|
303
|
+
if credentials:
|
304
|
+
print("š Saved credentials:")
|
305
|
+
for key in credentials:
|
306
|
+
print(f" - {key}")
|
307
|
+
else:
|
308
|
+
print("ā ļø No credentials found")
|
82
309
|
|
83
|
-
|
310
|
+
else:
|
311
|
+
print("ā ļø Unknown credentials command")
|
312
|
+
return 1
|
313
|
+
|
314
|
+
except ImportError:
|
315
|
+
print("ā Could not import credentials_manager module")
|
316
|
+
return 1
|
317
|
+
except Exception as e:
|
318
|
+
print(f"ā Error: {e}")
|
319
|
+
return 1
|
84
320
|
|
85
321
|
# Handle sandbox command
|
86
322
|
elif args.command == "sandbox":
|
87
|
-
|
323
|
+
try:
|
324
|
+
# Check if using proxy service
|
325
|
+
if args.use_proxy:
|
326
|
+
# Import proxy client
|
327
|
+
try:
|
328
|
+
from gitarsenal_proxy_client import GitArsenalProxyClient
|
329
|
+
client = GitArsenalProxyClient()
|
330
|
+
|
331
|
+
# Create sandbox through proxy
|
332
|
+
result = client.create_sandbox(
|
333
|
+
gpu_type=args.gpu,
|
334
|
+
repo_url=args.repo_url,
|
335
|
+
repo_name=args.repo_name,
|
336
|
+
setup_commands=args.setup_commands,
|
337
|
+
volume_name=args.volume_name,
|
338
|
+
wait=True # Always wait for sandbox to be ready
|
339
|
+
)
|
340
|
+
|
341
|
+
if not result:
|
342
|
+
print("ā Failed to create sandbox through proxy service")
|
343
|
+
return 1
|
344
|
+
|
345
|
+
print("ā
Sandbox created successfully through proxy service")
|
346
|
+
|
347
|
+
except ImportError:
|
348
|
+
print("ā Could not import gitarsenal_proxy_client module")
|
349
|
+
print("Please make sure gitarsenal_proxy_client.py is in the same directory")
|
350
|
+
return 1
|
351
|
+
else:
|
352
|
+
# Import sandbox creation function
|
353
|
+
from test_modalSandboxScript import create_modal_sandbox
|
354
|
+
|
355
|
+
# Create sandbox directly
|
356
|
+
result = create_modal_sandbox(
|
357
|
+
args.gpu,
|
358
|
+
repo_url=args.repo_url,
|
359
|
+
repo_name=args.repo_name,
|
360
|
+
setup_commands=args.setup_commands,
|
361
|
+
volume_name=args.volume_name
|
362
|
+
)
|
363
|
+
|
364
|
+
if not result:
|
365
|
+
print("ā Failed to create sandbox")
|
366
|
+
return 1
|
367
|
+
|
368
|
+
print("ā
Sandbox created successfully")
|
88
369
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
if args.setup_commands:
|
96
|
-
sandbox_args.extend(["--setup-commands"] + args.setup_commands)
|
97
|
-
if args.volume_name:
|
98
|
-
sandbox_args.extend(["--volume-name", args.volume_name])
|
99
|
-
|
100
|
-
return run_script("test_modalSandboxScript.py", sandbox_args)
|
370
|
+
except ImportError as e:
|
371
|
+
print(f"ā Could not import required module: {e}")
|
372
|
+
return 1
|
373
|
+
except Exception as e:
|
374
|
+
print(f"ā Error: {e}")
|
375
|
+
return 1
|
101
376
|
|
102
|
-
# Handle SSH
|
377
|
+
# Handle SSH command
|
103
378
|
elif args.command == "ssh":
|
104
|
-
|
379
|
+
try:
|
380
|
+
# Check if using proxy service
|
381
|
+
if args.use_proxy:
|
382
|
+
# Import proxy client
|
383
|
+
try:
|
384
|
+
from gitarsenal_proxy_client import GitArsenalProxyClient
|
385
|
+
client = GitArsenalProxyClient()
|
386
|
+
|
387
|
+
# Create SSH container through proxy
|
388
|
+
result = client.create_ssh_container(
|
389
|
+
gpu_type=args.gpu,
|
390
|
+
repo_url=args.repo_url,
|
391
|
+
repo_name=args.repo_name,
|
392
|
+
setup_commands=args.setup_commands,
|
393
|
+
volume_name=args.volume_name,
|
394
|
+
timeout=args.timeout,
|
395
|
+
wait=True # Always wait for container to be ready
|
396
|
+
)
|
397
|
+
|
398
|
+
if not result:
|
399
|
+
print("ā Failed to create SSH container through proxy service")
|
400
|
+
return 1
|
401
|
+
|
402
|
+
print("ā
SSH container created successfully through proxy service")
|
403
|
+
|
404
|
+
except ImportError:
|
405
|
+
print("ā Could not import gitarsenal_proxy_client module")
|
406
|
+
print("Please make sure gitarsenal_proxy_client.py is in the same directory")
|
407
|
+
return 1
|
408
|
+
else:
|
409
|
+
# Import SSH container creation function
|
410
|
+
from test_modalSandboxScript import create_modal_ssh_container
|
411
|
+
|
412
|
+
# Create SSH container directly
|
413
|
+
result = create_modal_ssh_container(
|
414
|
+
args.gpu,
|
415
|
+
repo_url=args.repo_url,
|
416
|
+
repo_name=args.repo_name,
|
417
|
+
setup_commands=args.setup_commands,
|
418
|
+
volume_name=args.volume_name,
|
419
|
+
timeout_minutes=args.timeout
|
420
|
+
)
|
421
|
+
|
422
|
+
if not result:
|
423
|
+
print("ā Failed to create SSH container")
|
424
|
+
return 1
|
425
|
+
|
426
|
+
print("ā
SSH container created successfully")
|
105
427
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
if args.setup_commands:
|
113
|
-
ssh_args.extend(["--setup-commands"] + args.setup_commands)
|
114
|
-
if args.volume_name:
|
115
|
-
ssh_args.extend(["--volume-name", args.volume_name])
|
116
|
-
if args.timeout:
|
117
|
-
ssh_args.extend(["--timeout", str(args.timeout)])
|
118
|
-
|
119
|
-
# Use test_modalSandboxScript.py with SSH mode
|
120
|
-
ssh_args.extend(["--ssh"])
|
121
|
-
return run_script("test_modalSandboxScript.py", ssh_args)
|
122
|
-
|
123
|
-
return 0
|
124
|
-
|
125
|
-
def run_script(script_name, args):
|
126
|
-
"""Run a Python script with the given arguments"""
|
127
|
-
# Get the directory of the current script
|
128
|
-
script_dir = os.path.dirname(os.path.abspath(__file__))
|
129
|
-
script_path = os.path.join(script_dir, script_name)
|
428
|
+
except ImportError as e:
|
429
|
+
print(f"ā Could not import required module: {e}")
|
430
|
+
return 1
|
431
|
+
except Exception as e:
|
432
|
+
print(f"ā Error: {e}")
|
433
|
+
return 1
|
130
434
|
|
131
|
-
#
|
132
|
-
|
435
|
+
# Handle proxy commands
|
436
|
+
elif args.command == "proxy":
|
437
|
+
if not args.proxy_command:
|
438
|
+
proxy_parser.print_help()
|
439
|
+
return 0
|
440
|
+
|
441
|
+
try:
|
442
|
+
# Import proxy client
|
443
|
+
from gitarsenal_proxy_client import GitArsenalProxyClient
|
444
|
+
client = GitArsenalProxyClient()
|
445
|
+
|
446
|
+
if args.proxy_command == "configure":
|
447
|
+
# Configure proxy service
|
448
|
+
client.configure(interactive=True)
|
449
|
+
|
450
|
+
elif args.proxy_command == "status":
|
451
|
+
# Check proxy service status
|
452
|
+
response = client.health_check()
|
453
|
+
if response["success"]:
|
454
|
+
print(f"ā
Proxy service is running: {response['data']['message']}")
|
455
|
+
else:
|
456
|
+
print(f"ā Proxy service health check failed: {response['error']}")
|
457
|
+
return 1
|
458
|
+
|
459
|
+
elif args.proxy_command == "sandbox":
|
460
|
+
# Create sandbox through proxy
|
461
|
+
result = client.create_sandbox(
|
462
|
+
gpu_type=args.gpu,
|
463
|
+
repo_url=args.repo_url,
|
464
|
+
repo_name=args.repo_name,
|
465
|
+
setup_commands=args.setup_commands,
|
466
|
+
volume_name=args.volume_name,
|
467
|
+
wait=args.wait
|
468
|
+
)
|
469
|
+
|
470
|
+
if not result:
|
471
|
+
print("ā Failed to create sandbox through proxy service")
|
472
|
+
return 1
|
473
|
+
|
474
|
+
print("ā
Sandbox created successfully through proxy service")
|
475
|
+
|
476
|
+
elif args.proxy_command == "ssh":
|
477
|
+
# Create SSH container through proxy
|
478
|
+
result = client.create_ssh_container(
|
479
|
+
gpu_type=args.gpu,
|
480
|
+
repo_url=args.repo_url,
|
481
|
+
repo_name=args.repo_name,
|
482
|
+
setup_commands=args.setup_commands,
|
483
|
+
volume_name=args.volume_name,
|
484
|
+
timeout=args.timeout,
|
485
|
+
wait=args.wait
|
486
|
+
)
|
487
|
+
|
488
|
+
if not result:
|
489
|
+
print("ā Failed to create SSH container through proxy service")
|
490
|
+
return 1
|
491
|
+
|
492
|
+
print("ā
SSH container created successfully through proxy service")
|
493
|
+
|
494
|
+
else:
|
495
|
+
print(f"ā Unknown proxy command: {args.proxy_command}")
|
496
|
+
proxy_parser.print_help()
|
497
|
+
return 1
|
498
|
+
|
499
|
+
except ImportError:
|
500
|
+
print("ā Could not import gitarsenal_proxy_client module")
|
501
|
+
print("Please make sure gitarsenal_proxy_client.py is in the same directory")
|
502
|
+
return 1
|
503
|
+
except Exception as e:
|
504
|
+
print(f"ā Error: {e}")
|
505
|
+
return 1
|
133
506
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
return result.returncode
|
138
|
-
except KeyboardInterrupt:
|
139
|
-
print("\nā ļø Command interrupted by user")
|
140
|
-
return 130
|
141
|
-
except Exception as e:
|
142
|
-
print(f"ā Error running {script_name}: {e}")
|
507
|
+
else:
|
508
|
+
print(f"ā Unknown command: {args.command}")
|
509
|
+
parser.print_help()
|
143
510
|
return 1
|
511
|
+
|
512
|
+
return 0
|
144
513
|
|
145
514
|
if __name__ == "__main__":
|
146
515
|
sys.exit(main())
|