@@ -30,20 +30,91 @@ import (
3030 s "github.com/cortexlabs/cortex/pkg/lib/strings"
3131)
3232
33- // aws instance types take this form: (\w+)([0-9]+)(\w*).(\w+)
34- // the first group is the instance series, e.g. "m", "t", "g", "inf", ...
35- // the second group is a version number for that series, e.g. 3, 4, ...
36- // the third group is optional, and is a set of single-character "flags"
33+ var _digitsRegex = regexp .MustCompile (`[0-9]+` )
34+
35+ type ParsedInstanceType struct {
36+ Family string
37+ Generation int
38+ Capabilities strset.Set
39+ Size string
40+ }
41+
42+ // Checks weather the input is an AWS instance type
43+ func IsValidInstanceType (instanceType string ) bool {
44+ return AllInstanceTypes .Has (instanceType )
45+ }
46+
47+ // Checks whether the input is an AWS instance type
48+ func CheckValidInstanceType (instanceType string ) error {
49+ if ! IsValidInstanceType (instanceType ) {
50+ return ErrorInvalidInstanceType (instanceType )
51+ }
52+ return nil
53+ }
54+
55+ // AWS instance types take the form of: [family][generation][capabilities].[size]
56+ // the first group is the instance family, e.g. "m", "t", "g", "inf", ...
57+ // the second group is a generation number for that series, e.g. 3, 4, ...
58+ // the third group is optional, and is a set of single-character capabilities
3759// "g" represents ARM (graviton), "a" for AMD, "n" for fast networking, "d" for fast storage, etc.
3860// the fourth and final group (after the dot) is the instance size, e.g. "large"
39- var _armInstanceCapabilityRegex = regexp .MustCompile (`^\w+[0-9]+\w*g\w*\.\w+$` )
61+ func ParseInstanceType (instanceType string ) (ParsedInstanceType , error ) {
62+ if err := CheckValidInstanceType (instanceType ); err != nil {
63+ return ParsedInstanceType {}, err
64+ }
4065
41- // instanceType is assumed to be a valid instance type that exists in AWS, e.g. g4dn.xlarge
42- func IsARMInstance (instanceType string ) bool {
43- if strings .HasPrefix (instanceType , "a" ) {
44- return true
66+ parts := strings .Split (instanceType , "." )
67+ if len (parts ) != 2 {
68+ return ParsedInstanceType {}, errors .ErrorUnexpected ("unexpected invalid instance type: " + instanceType )
69+ }
70+
71+ prefix := parts [0 ]
72+ size := parts [1 ]
73+
74+ digitSets := _digitsRegex .FindAllString (prefix , - 1 )
75+ if len (digitSets ) == 0 {
76+ return ParsedInstanceType {}, errors .ErrorUnexpected ("unexpected invalid instance type: " + instanceType )
4577 }
46- return _armInstanceCapabilityRegex .MatchString (instanceType )
78+
79+ prefixParts := _digitsRegex .Split (prefix , - 1 )
80+ capabilitiesStr := prefixParts [len (prefixParts )- 1 ]
81+ capabilities := strset .FromSlice (strings .Split (capabilitiesStr , "" ))
82+
83+ generationStr := digitSets [len (digitSets )- 1 ]
84+ generation , ok := s .ParseInt (generationStr )
85+ if ! ok {
86+ return ParsedInstanceType {}, errors .ErrorUnexpected ("unexpected invalid instance type: " + instanceType )
87+ }
88+
89+ generationIndex := strings .LastIndex (prefix , generationStr )
90+ if generationIndex == - 1 {
91+ return ParsedInstanceType {}, errors .ErrorUnexpected ("unexpected invalid instance type: " + instanceType )
92+ }
93+ family := prefix [:generationIndex ]
94+
95+ return ParsedInstanceType {
96+ Family : family ,
97+ Generation : generation ,
98+ Capabilities : capabilities ,
99+ Size : size ,
100+ }, nil
101+ }
102+
103+ func IsARMInstance (instanceType string ) (bool , error ) {
104+ parsedType , err := ParseInstanceType (instanceType )
105+ if err != nil {
106+ return false , err
107+ }
108+
109+ if parsedType .Family == "a" {
110+ return true , nil
111+ }
112+
113+ if parsedType .Capabilities .Has ("g" ) {
114+ return true , nil
115+ }
116+
117+ return false , nil
47118}
48119
49120func (c * Client ) SpotInstancePrice (instanceType string ) (float64 , error ) {
0 commit comments