66
77 "github.com/drycc/controller-sdk-go/api"
88 "github.com/drycc/controller-sdk-go/config"
9+ "github.com/drycc/controller-sdk-go/limits"
10+ "github.com/drycc/workflow-cli/settings"
911)
1012
1113// LimitsList lists an app's limits.
@@ -20,26 +22,32 @@ func (d *DryccCmd) LimitsList(appID string) error {
2022 if d .checkAPICompatibility (s .Client , err ) != nil {
2123 return err
2224 }
23- if len (config .CPU ) > 0 || len (config .Memory ) > 0 {
24- table := d .getDefaultFormatTable ([]string {"UUID" , "OWNER" , "PTYPE" , "DEVICE" , "QUOTA" })
25- for _ , key := range * sortKeys (config .Memory ) {
25+ cached := make (map [string ]api.LimitPlan )
26+
27+ if len (config .Limits ) > 0 {
28+ table := d .getDefaultFormatTable ([]string {"PTYPE" , "PLAN" , "VCPUS" , "MEMORY" , "FEATURES" })
29+ for _ , ptype := range * sortKeys (config .Limits ) {
30+ limitPlanID := fmt .Sprintf ("%v" , config .Limits [ptype ])
31+ if _ , ok := cached [limitPlanID ]; ! ok {
32+ limitPlan , err := limits .GetPlan (s .Client , limitPlanID )
33+ if err != nil {
34+ return err
35+ }
36+ cached [limitPlanID ] = limitPlan
37+ }
38+ limitPlan := cached [limitPlanID ]
39+ gpuCount := limitPlan .Features ["gpu" ]
40+ gpuName := limitPlan .Spec .Features ["gpu" ].(map [string ]interface {})["name" ]
41+ gpuMemory := limitPlan .Spec .Features ["gpu" ].(map [string ]interface {})["memory" ].(map [string ]interface {})["size" ]
2642 table .Append ([]string {
27- config .UUID ,
28- config .Owner ,
29- key ,
30- "MEM" ,
31- fmt .Sprintf ("%v" , config .Memory [key ]),
32- })
33- }
34- for _ , key := range * sortKeys (config .CPU ) {
35- table .Append ([]string {
36- config .UUID ,
37- config .Owner ,
38- key ,
39- "CPU" ,
40- fmt .Sprintf ("%v" , config .CPU [key ]),
43+ ptype ,
44+ limitPlanID ,
45+ fmt .Sprintf ("%v" , limitPlan .CPU ),
46+ fmt .Sprintf ("%v GiB" , limitPlan .Memory ),
47+ fmt .Sprintf ("%v %v * %v" , gpuName , gpuMemory , gpuCount ),
4148 })
4249 }
50+
4351 table .Render ()
4452 } else {
4553 d .Println (fmt .Sprintf ("No limits found in %s app." , appID ))
@@ -48,27 +56,20 @@ func (d *DryccCmd) LimitsList(appID string) error {
4856}
4957
5058// LimitsSet sets an app's limits.
51- func (d * DryccCmd ) LimitsSet (appID string , cpuLimits [] string , memoryLimits []string ) error {
59+ func (d * DryccCmd ) LimitsSet (appID string , limits []string ) error {
5260 s , appID , err := load (d .ConfigFile , appID )
5361
5462 if err != nil {
5563 return err
5664 }
5765
5866 configObj := api.Config {}
59- if len (cpuLimits ) > 0 {
60- cpuLimitsMap , err := parseLimits (cpuLimits )
61- if err != nil {
62- return err
63- }
64- configObj .CPU = cpuLimitsMap
65- }
66- if len (memoryLimits ) > 0 {
67- memoryLimitsMap , err := parseLimits (memoryLimits )
67+ if len (limits ) > 0 {
68+ limitsMap , err := parseLimits (limits )
6869 if err != nil {
6970 return err
7071 }
71- configObj .Memory = memoryLimitsMap
72+ configObj .Limits = limitsMap
7273 }
7374
7475 d .Print ("Applying limits... " )
@@ -88,7 +89,7 @@ func (d *DryccCmd) LimitsSet(appID string, cpuLimits []string, memoryLimits []st
8889}
8990
9091// LimitsUnset removes an app's limits.
91- func (d * DryccCmd ) LimitsUnset (appID string , cpuLimits [] string , memoryLimits []string ) error {
92+ func (d * DryccCmd ) LimitsUnset (appID string , limits []string ) error {
9293 s , appID , err := load (d .ConfigFile , appID )
9394
9495 if err != nil {
@@ -100,19 +101,12 @@ func (d *DryccCmd) LimitsUnset(appID string, cpuLimits []string, memoryLimits []
100101 quit := progress (d .WOut )
101102
102103 configObj := api.Config {}
103- if len (cpuLimits ) > 0 {
104- cpuMap := make (map [string ]interface {})
105- for _ , limit := range cpuLimits {
106- cpuMap [limit ] = nil
107- }
108- configObj .CPU = cpuMap
109- }
110- if len (memoryLimits ) > 0 {
111- memoryMap := make (map [string ]interface {})
112- for _ , limit := range memoryLimits {
113- memoryMap [limit ] = nil
104+ if len (limits ) > 0 {
105+ limitsMap := make (map [string ]interface {})
106+ for _ , limit := range limits {
107+ limitsMap [limit ] = nil
114108 }
115- configObj .Memory = memoryMap
109+ configObj .Limits = limitsMap
116110 }
117111
118112 _ , err = config .Set (s .Client , appID , configObj )
@@ -127,6 +121,80 @@ func (d *DryccCmd) LimitsUnset(appID string, cpuLimits []string, memoryLimits []
127121 return d .LimitsList (appID )
128122}
129123
124+ // LimitsSpecs list limit spec
125+ func (d * DryccCmd ) LimitsSpecs (keywords string , results int ) error {
126+ s , err := settings .Load (d .ConfigFile )
127+
128+ if err != nil {
129+ return err
130+ }
131+
132+ if results == defaultLimit {
133+ results = s .Limit
134+ }
135+ limitSpecs , count , err := limits .Specs (s .Client , keywords , results )
136+ if d .checkAPICompatibility (s .Client , err ) != nil {
137+ return err
138+ }
139+ if count == 0 {
140+ d .Println ("Could not find any limit spec." )
141+ } else {
142+ table := d .getDefaultFormatTable ([]string {"ID" , "CPU" , "CLOCK" , "BOOST" , "CORES" , "THREADS" , "NETWORK" , "FEATURES" })
143+ for _ , limitSpec := range limitSpecs {
144+ gpuName := limitSpec .Features ["gpu" ].(map [string ]interface {})["name" ]
145+ gpuMemory := limitSpec .Features ["gpu" ].(map [string ]interface {})["memory" ].(map [string ]interface {})["size" ]
146+ table .Append ([]string {
147+ limitSpec .ID ,
148+ fmt .Sprintf ("%v" , limitSpec .CPU ["name" ]),
149+ fmt .Sprintf ("%v" , limitSpec .CPU ["clock" ]),
150+ fmt .Sprintf ("%v" , limitSpec .CPU ["boost" ]),
151+ fmt .Sprintf ("%v" , limitSpec .CPU ["cores" ]),
152+ fmt .Sprintf ("%v" , limitSpec .CPU ["threads" ]),
153+ fmt .Sprintf ("%v" , limitSpec .Features ["network" ]),
154+ fmt .Sprintf ("%v %v" , gpuName , gpuMemory ),
155+ })
156+ }
157+ table .Render ()
158+ }
159+ return nil
160+ }
161+
162+ // LimitsPlans list limit plan
163+ func (d * DryccCmd ) LimitsPlans (specID string , cpu , memory , results int ) error {
164+ s , err := settings .Load (d .ConfigFile )
165+
166+ if err != nil {
167+ return err
168+ }
169+
170+ if results == defaultLimit {
171+ results = s .Limit
172+ }
173+ limitPlans , count , err := limits .Plans (s .Client , specID , cpu , memory , results )
174+ if d .checkAPICompatibility (s .Client , err ) != nil {
175+ return err
176+ }
177+ if count == 0 {
178+ d .Println ("Could not find any limit spec." )
179+ } else {
180+ table := d .getDefaultFormatTable ([]string {"ID" , "SPEC" , "CPU" , "VCPUS" , "MEMORY" , "FEATURES" })
181+ for _ , limitPlan := range limitPlans {
182+ gpuName := limitPlan .Spec .Features ["gpu" ].(map [string ]interface {})["name" ]
183+ gpuMemory := limitPlan .Spec .Features ["gpu" ].(map [string ]interface {})["memory" ].(map [string ]interface {})["size" ]
184+ table .Append ([]string {
185+ limitPlan .ID ,
186+ limitPlan .Spec .ID ,
187+ fmt .Sprintf ("%v" , limitPlan .Spec .CPU ["name" ]),
188+ fmt .Sprintf ("%v" , limitPlan .CPU ),
189+ fmt .Sprintf ("%v GiB" , limitPlan .Memory ),
190+ fmt .Sprintf ("%v %v" , gpuName , gpuMemory ),
191+ })
192+ }
193+ table .Render ()
194+ }
195+ return nil
196+ }
197+
130198func parseLimits (limits []string ) (map [string ]interface {}, error ) {
131199 limitsMap := make (map [string ]interface {})
132200
@@ -144,11 +212,11 @@ func parseLimits(limits []string) (map[string]interface{}, error) {
144212}
145213
146214func parseLimit (limit string ) (string , string , error ) {
147- regex := regexp .MustCompile ("^([a-z0-9]+(?:-[a-z0-9]+)*)=(([1-9][0-9]*[mgMG]|[1-9][0 -9]*m?) )$" )
215+ regex := regexp .MustCompile ("^([a-z0-9]+(?:-[a-z0-9]+)*)=([-.a-zA-Z0 -9]+ )$" )
148216
149217 if ! regex .MatchString (limit ) {
150218 return "" , "" , fmt .Errorf (`%s doesn't fit format type=#unit or type=#
151- Examples: web=2G worker=500M db=1G ` , limit )
219+ Examples: web=std1.large.c1m1 ` , limit )
152220 }
153221
154222 capture := regex .FindStringSubmatch (limit )
0 commit comments