@@ -17,9 +17,10 @@ package cmd
1717import (
1818 "fmt"
1919 "os"
20- "slices"
2120 "time"
2221
22+ "github.com/ksctl/ksctl/v2/pkg/provider/optimizer"
23+
2324 "github.com/fatih/color"
2425 "github.com/ksctl/ksctl/v2/pkg/consts"
2526 "github.com/ksctl/ksctl/v2/pkg/provider"
@@ -62,9 +63,57 @@ ksctl create --help
6263 return cmd
6364}
6465
65- func (k * KsctlCommand ) metadataForSelfManagedCluster (
66- meta * controller.Metadata ,
67- ) {
66+ type CliRecommendation struct {
67+ isOptimizeInstanceRegionReady * optimizer.RecommendationAcrossRegions
68+ errInRecommendation error
69+ }
70+
71+ func (k * KsctlCommand ) CostOptimizeAcrossRegion (inp chan CliRecommendation , meta * controller.Metadata ) {
72+ ticker := time .NewTicker (2 * time .Second )
73+ defer ticker .Stop ()
74+ for {
75+ select {
76+ case o := <- inp :
77+ optimizeResp , errResp := o .isOptimizeInstanceRegionReady , o .errInRecommendation
78+ if errResp != nil {
79+ k .l .Warn (k .Ctx , "Failed to get the recommendation" , "Reason" , errResp )
80+ return
81+ }
82+
83+ if len (optimizeResp .RegionRecommendations ) == 0 {
84+ k .l .Success (k .Ctx , "✨ No recommendation available for the selected region" )
85+ return
86+ }
87+
88+ k .PrintRecommendation (meta .ClusterType , optimizeResp )
89+
90+ availRegions := []string {"Don't change" }
91+ for _ , _o := range optimizeResp .RegionRecommendations {
92+ availRegions = append (availRegions , _o .Region )
93+ }
94+
95+ v , err := k .menuDriven .DropDownList (fmt .Sprintf ("Region Switch. Currently set (%s)" , meta .Region ), availRegions ,
96+ cli .WithDefaultValue ("Don't change" ),
97+ )
98+ if err != nil {
99+ k .l .Error ("Skipping it becuase failed to get the region switch" , "Reason" , err )
100+ return
101+ }
102+ if v == "Don't change" {
103+ return
104+ }
105+
106+ k .l .Print (k .Ctx , "changed the region" , "from" , color .HiRedString (meta .Region ), "to" , color .HiGreenString (v ))
107+ meta .Region = v
108+
109+ return
110+ case <- ticker .C :
111+ k .l .Print (k .Ctx , "Still optimizing instance types..." )
112+ }
113+ }
114+ }
115+
116+ func (k * KsctlCommand ) metadataForSelfManagedCluster (meta * controller.Metadata ) {
68117 metaClient , err := controllerMeta .NewController (
69118 k .Ctx ,
70119 k .l ,
@@ -122,10 +171,29 @@ func (k *KsctlCommand) metadataForSelfManagedCluster(
122171 meta .NoDS = v
123172 }
124173
125- isOptimizeInstanceRegionReady := make (chan []RecommendationSelfManagedCost )
174+ var (
175+ isOptimizeInstanceRegionReady chan CliRecommendation
176+ )
177+ isOptimizeInstanceRegionReady = make (chan CliRecommendation )
126178
127179 go func () {
128- isOptimizeInstanceRegionReady <- k .OptimizeSelfManagedInstanceTypesAcrossRegions (meta , allAvailRegions , cp , wp , etcd , lb )
180+ res , err := metaClient .CostOptimizeAcrossRegions (
181+ allAvailRegions , meta .Region ,
182+ controllerMeta.CostOptimizerInput {
183+ ControlPlane : cp ,
184+ WorkerPlane : wp ,
185+ DataStorePlane : etcd ,
186+ LoadBalancer : lb ,
187+ CountOfControlPlaneNodes : meta .NoCP ,
188+ CountOfWorkerNodes : meta .NoWP ,
189+ CountOfEtcdNodes : meta .NoDS ,
190+ },
191+ )
192+
193+ isOptimizeInstanceRegionReady <- CliRecommendation {
194+ isOptimizeInstanceRegionReady : res ,
195+ errInRecommendation : err ,
196+ }
129197 }()
130198
131199 bootstrapVers , err := metaClient .ListAllBootstrapVersions ()
@@ -172,52 +240,7 @@ func (k *KsctlCommand) metadataForSelfManagedCluster(
172240 os .Exit (1 )
173241 }
174242
175- func () {
176- ticker := time .NewTicker (2 * time .Second )
177- defer ticker .Stop ()
178- for {
179- select {
180- case o := <- isOptimizeInstanceRegionReady :
181- k .PrintRecommendationSelfManagedCost (
182- o ,
183- meta .NoCP ,
184- meta .NoWP ,
185- meta .NoDS ,
186- cp .Sku ,
187- wp .Sku ,
188- etcd .Sku ,
189- lb .Sku ,
190- )
191- pos := slices .IndexFunc (o , func (i RecommendationSelfManagedCost ) bool {
192- return i .region == meta .Region
193- })
194- o = append (o [:pos ], o [pos + 1 :]... )
195-
196- availRegions := []string {"Don't change" }
197- for _ , _o := range o [:5 ] {
198- availRegions = append (availRegions , _o .region )
199- }
200-
201- v , err := k .menuDriven .DropDownList (fmt .Sprintf ("Region Switch. Currently set (%s)" , meta .Region ), availRegions ,
202- cli .WithDefaultValue ("Don't change" ),
203- )
204- if err != nil {
205- k .l .Error ("Skipping it becuase failed to get the region switch" , "Reason" , err )
206- return
207- }
208- if v == "Don't change" {
209- return
210- }
211-
212- k .l .Print (k .Ctx , "changed the region" , "from" , color .HiRedString (meta .Region ), "to" , color .HiGreenString (v ))
213- meta .Region = v
214-
215- return
216- case <- ticker .C :
217- k .l .Print (k .Ctx , "Still optimizing instance types..." )
218- }
219- }
220- }()
243+ k .CostOptimizeAcrossRegion (isOptimizeInstanceRegionReady , meta )
221244
222245 managedCNI , defaultCNI , ksctlCNI , defaultKsctl , err := metaClient .ListBootstrapCNIs ()
223246 if err != nil {
@@ -271,9 +294,7 @@ func (k *KsctlCommand) metadataForSelfManagedCluster(
271294 return
272295}
273296
274- func (k * KsctlCommand ) metadataForManagedCluster (
275- meta * controller.Metadata ,
276- ) {
297+ func (k * KsctlCommand ) metadataForManagedCluster (meta * controller.Metadata ) {
277298 metaClient , err := controllerMeta .NewController (
278299 k .Ctx ,
279300 k .l ,
@@ -295,7 +316,9 @@ func (k *KsctlCommand) metadataForManagedCluster(
295316 meta .NoMP = v
296317 }
297318
298- isOptimizeInstanceRegionReady := make (chan []RecommendationManagedCost )
319+ var (
320+ isOptimizeInstanceRegionReady chan CliRecommendation
321+ )
299322
300323 if meta .Provider != consts .CloudLocal {
301324 allAvailRegions := k .handleRegionSelection (metaClient , meta )
@@ -327,8 +350,21 @@ func (k *KsctlCommand) metadataForManagedCluster(
327350 offeringSelected = v
328351 }
329352
353+ isOptimizeInstanceRegionReady = make (chan CliRecommendation )
354+
330355 go func () {
331- isOptimizeInstanceRegionReady <- k .OptimizeManagedOfferingsAcrossRegions (meta , allAvailRegions , listOfOfferings [offeringSelected ], vm )
356+ res , err := metaClient .CostOptimizeAcrossRegions (
357+ allAvailRegions , meta .Region ,
358+ controllerMeta.CostOptimizerInput {
359+ ManagedOffering : listOfOfferings [offeringSelected ],
360+ ManagedPlane : vm ,
361+ CountOfManagedNodes : meta .NoMP ,
362+ },
363+ )
364+ isOptimizeInstanceRegionReady <- CliRecommendation {
365+ isOptimizeInstanceRegionReady : res ,
366+ errInRecommendation : err ,
367+ }
332368 }()
333369
334370 k .l .Print (k .Ctx , "Current Selection will cost you" )
@@ -344,49 +380,7 @@ func (k *KsctlCommand) metadataForManagedCluster(
344380 os .Exit (1 )
345381 }
346382
347- func () {
348- ticker := time .NewTicker (2 * time .Second )
349- defer ticker .Stop ()
350- for {
351- select {
352- case o := <- isOptimizeInstanceRegionReady :
353- k .PrintRecommendationManagedCost (
354- o ,
355- meta .NoMP ,
356- listOfOfferings [offeringSelected ].Sku ,
357- vm .Sku ,
358- )
359-
360- pos := slices .IndexFunc (o , func (i RecommendationManagedCost ) bool {
361- return i .region == meta .Region
362- })
363- o = append (o [:pos ], o [pos + 1 :]... )
364-
365- availRegions := []string {"Don't change" }
366- for _ , _o := range o [:5 ] {
367- availRegions = append (availRegions , _o .region )
368- }
369-
370- v , err := k .menuDriven .DropDownList (fmt .Sprintf ("Region Switch. Currently set (%s)" , meta .Region ), availRegions ,
371- cli .WithDefaultValue ("Don't change" ),
372- )
373- if err != nil {
374- k .l .Error ("Skipping it becuase failed to get the region switch" , "Reason" , err )
375- return
376- }
377- if v == "Don't change" {
378- return
379- }
380-
381- k .l .Print (k .Ctx , "changed the region" , "from" , color .HiRedString (meta .Region ), "to" , color .HiGreenString (v ))
382- meta .Region = v
383-
384- return
385- case <- ticker .C :
386- k .l .Print (k .Ctx , "Still optimizing instance types..." )
387- }
388- }
389- }()
383+ k .CostOptimizeAcrossRegion (isOptimizeInstanceRegionReady , meta )
390384 }
391385
392386 managedCNI , defaultCNI , ksctlCNI , defaultKsctl , err := metaClient .ListManagedCNIs ()
@@ -452,3 +446,89 @@ func (k *KsctlCommand) metadataForManagedCluster(
452446
453447 return
454448}
449+
450+ func (k * KsctlCommand ) PrintRecommendation (
451+ clusterType consts.KsctlClusterType ,
452+ optimizations * optimizer.RecommendationAcrossRegions ) {
453+
454+ k .l .Print (k .Ctx ,
455+ "Here is your recommendation" ,
456+ "Parameter" , "Region wise cost" ,
457+ )
458+
459+ var headers []string
460+ var data [][]string
461+
462+ if clusterType == consts .ClusterTypeMang {
463+ headers = []string {
464+ "Region" ,
465+ "🏭 Direct Emission" ,
466+ fmt .Sprintf ("ControlPlane (%s)" , optimizations .ManagedOffering ),
467+ fmt .Sprintf ("WorkerPlane (%s)" , optimizations .InstanceTypeWP ),
468+ "Total Monthly Cost" ,
469+ }
470+
471+ for _ , cost := range optimizations .RegionRecommendations {
472+ total := cost .TotalCost
473+ reg := cost .Region
474+ managed := cost .ControlPlaneCost
475+ worker := cost .WorkerPlaneCost
476+
477+ regEmissions := cost .Emissions
478+ var emissions string
479+ if regEmissions == nil {
480+ emissions = "N/A"
481+ } else {
482+ emissions = fmt .Sprintf ("%.2f %s" , regEmissions .DirectCarbonIntensity , regEmissions .Unit )
483+ }
484+
485+ data = append (data , []string {
486+ reg ,
487+ emissions ,
488+ fmt .Sprintf ("$%.2f X 1" , managed ),
489+ fmt .Sprintf ("$%.2f X %d" , worker , optimizations .WorkerPlaneCount ),
490+ fmt .Sprintf ("$%.2f" , total ),
491+ })
492+ }
493+
494+ } else if clusterType == consts .ClusterTypeSelfMang {
495+ headers = []string {
496+ "Region" ,
497+ "🏭 Direct Emission" ,
498+ fmt .Sprintf ("ControlPlane (%s)" , optimizations .InstanceTypeCP ),
499+ fmt .Sprintf ("WorkerPlane (%s)" , optimizations .InstanceTypeWP ),
500+ fmt .Sprintf ("DatastorePlane (%s)" , optimizations .InstanceTypeDS ),
501+ fmt .Sprintf ("LoadBalancer (%s)" , optimizations .InstanceTypeLB ),
502+ "Total Monthly Cost" ,
503+ }
504+
505+ for _ , cost := range optimizations .RegionRecommendations {
506+ total := cost .TotalCost
507+ reg := cost .Region
508+ cp := cost .ControlPlaneCost
509+ wp := cost .WorkerPlaneCost
510+ ds := cost .DataStoreCost
511+ lb := cost .LoadBalancerCost
512+ regEmissions := cost .Emissions
513+
514+ var emissions string
515+ if regEmissions == nil {
516+ emissions = "N/A"
517+ } else {
518+ emissions = fmt .Sprintf ("%.2f %s" , regEmissions .DirectCarbonIntensity , regEmissions .Unit )
519+ }
520+
521+ data = append (data , []string {
522+ reg ,
523+ emissions ,
524+ fmt .Sprintf ("$%.2f X %d" , cp , optimizations .ControlPlaneCount ),
525+ fmt .Sprintf ("$%.2f X %d" , wp , optimizations .WorkerPlaneCount ),
526+ fmt .Sprintf ("$%.2f X %d" , ds , optimizations .DataStoreCount ),
527+ fmt .Sprintf ("$%.2f X 1" , lb ),
528+ fmt .Sprintf ("$%.2f" , total ),
529+ })
530+ }
531+ }
532+
533+ k .l .Table (k .Ctx , headers , data )
534+ }
0 commit comments