-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcli.py
114 lines (97 loc) · 2.9 KB
/
cli.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import json
import argparse
from spot_optimizer import optimize
def validate_positive_int(value: str, param_name: str) -> int:
"""
Validate that the value is a positive integer.
Args:
value: The string value to validate
param_name: Name of the parameter for error messages
Returns:
int: The validated positive integer
Raises:
ArgumentTypeError: If value is not a positive integer
"""
try:
ivalue = int(value)
if ivalue <= 0:
raise argparse.ArgumentTypeError(
f"{param_name} must be greater than 0, got {ivalue}"
)
return ivalue
except ValueError:
raise argparse.ArgumentTypeError(
f"{param_name} must be an integer, got {value}"
)
def parse_args(args=None):
"""
Parse command line arguments.
Args:
args: List of arguments to parse. Defaults to sys.argv[1:] if None.
Returns:
argparse.Namespace: Parsed command line arguments
"""
parser = argparse.ArgumentParser(description="Run the spot instance optimizer.")
parser.add_argument(
"--cores",
type=lambda x: validate_positive_int(x, "cores"),
required=True,
help="Total number of CPU cores required.",
)
parser.add_argument(
"--memory",
type=lambda x: validate_positive_int(x, "memory"),
required=True,
help="Total amount of RAM required (in GB).",
)
parser.add_argument(
"--region",
type=str,
default="us-west-2",
help="AWS region to find instances in.",
)
parser.add_argument(
"--ssd-only",
action="store_true",
help="Filter for SSD-backed instances.",
)
parser.add_argument(
"--arm-instances",
action="store_true",
help="Include ARM-based instances if True.",
)
parser.add_argument(
"--instance-family",
type=str,
nargs="+",
help="Filter by instance family (e.g., 'm5', 'c6g', etc.).",
)
parser.add_argument(
"--emr-version",
type=str,
help="Optional EMR version for EMR workloads (e.g., '6.10.0').",
)
parser.add_argument(
"--mode",
type=str,
default="balanced",
choices=["latency", "fault_tolerance", "balanced"],
help='Optimization mode: "latency", "fault_tolerance", or "balanced".',
)
return parser.parse_args(args)
def main():
"""Main entry point for the CLI."""
args = parse_args()
result = optimize(
cores=args.cores,
memory=args.memory,
region=args.region,
ssd_only=args.ssd_only,
arm_instances=args.arm_instances,
instance_family=args.instance_family,
emr_version=args.emr_version,
mode=args.mode,
)
print(json.dumps(result, indent=2))
if __name__ == "__main__":
main()