Skip to content

Commit df01b41

Browse files
authored
Merge pull request #69 from ksctl/feature/62
🆕 Recommend Region which is cheapest in terms of 💵 across regions for selected instancetypes
2 parents 7bd2e3b + 914ca74 commit df01b41

File tree

6 files changed

+487
-7
lines changed

6 files changed

+487
-7
lines changed

cmd/create.go

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@
1515
package cmd
1616

1717
import (
18+
"fmt"
1819
"os"
20+
"slices"
21+
"time"
1922

23+
"github.com/fatih/color"
2024
"github.com/ksctl/ksctl/v2/pkg/consts"
2125
"github.com/ksctl/ksctl/v2/pkg/provider"
2226

@@ -73,7 +77,7 @@ func (k *KsctlCommand) metadataForSelfManagedCluster(
7377
os.Exit(1)
7478
}
7579

76-
k.handleRegionSelection(metaClient, meta)
80+
allAvailRegions := k.handleRegionSelection(metaClient, meta)
7781

7882
cp := k.handleInstanceTypeSelection(metaClient, meta, provider.ComputeIntensive, "Select instance_type for Control Plane")
7983
etcd := k.handleInstanceTypeSelection(metaClient, meta, provider.MemoryIntensive, "Select instance_type for Etcd Nodes")
@@ -118,11 +122,18 @@ func (k *KsctlCommand) metadataForSelfManagedCluster(
118122
meta.NoDS = v
119123
}
120124

125+
isOptimizeInstanceRegionReady := make(chan []RecommendationSelfManagedCost)
126+
127+
go func() {
128+
isOptimizeInstanceRegionReady <- k.OptimizeSelfManagedInstanceTypesAcrossRegions(meta, allAvailRegions, cp, wp, etcd, lb)
129+
}()
130+
121131
bootstrapVers, err := metaClient.ListAllBootstrapVersions()
122132
if err != nil {
123133
k.l.Error("Failed to get the list of bootstrap versions", "Reason", err)
124134
os.Exit(1)
125135
}
136+
126137
if v, err := k.menuDriven.DropDownList("Select the bootstrap version", bootstrapVers, cli.WithDefaultValue(bootstrapVers[0])); err != nil {
127138
k.l.Error("Failed to get the bootstrap version", "Reason", err)
128139
os.Exit(1)
@@ -144,6 +155,7 @@ func (k *KsctlCommand) metadataForSelfManagedCluster(
144155
meta.EtcdVersion = v
145156
}
146157

158+
k.l.Print(k.Ctx, "Current Selection will cost you")
147159
_, err = metaClient.PriceCalculator(
148160
controllerMeta.PriceCalculatorInput{
149161
Currency: cp.Price.Currency,
@@ -160,6 +172,53 @@ func (k *KsctlCommand) metadataForSelfManagedCluster(
160172
os.Exit(1)
161173
}
162174

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{"No 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+
}()
221+
163222
managedCNI, defaultCNI, ksctlCNI, defaultKsctl, err := metaClient.ListBootstrapCNIs()
164223
if err != nil {
165224
k.l.Error("Failed to get the list of self managed CNIs", "Reason", err)
@@ -236,8 +295,10 @@ func (k *KsctlCommand) metadataForManagedCluster(
236295
meta.NoMP = v
237296
}
238297

298+
isOptimizeInstanceRegionReady := make(chan []RecommendationManagedCost)
299+
239300
if meta.Provider != consts.CloudLocal {
240-
k.handleRegionSelection(metaClient, meta)
301+
allAvailRegions := k.handleRegionSelection(metaClient, meta)
241302

242303
category := provider.Unknown
243304
if meta.Provider != consts.CloudLocal {
@@ -266,6 +327,12 @@ func (k *KsctlCommand) metadataForManagedCluster(
266327
offeringSelected = v
267328
}
268329

330+
go func() {
331+
isOptimizeInstanceRegionReady <- k.OptimizeManagedOfferingsAcrossRegions(meta, allAvailRegions, listOfOfferings[offeringSelected], vm)
332+
}()
333+
334+
k.l.Print(k.Ctx, "Current Selection will cost you")
335+
269336
_, err = metaClient.PriceCalculator(
270337
controllerMeta.PriceCalculatorInput{
271338
ManagedControlPlaneMachine: listOfOfferings[offeringSelected],
@@ -276,6 +343,50 @@ func (k *KsctlCommand) metadataForManagedCluster(
276343
k.l.Error("Failed to calculate the price", "Reason", err)
277344
os.Exit(1)
278345
}
346+
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{"No 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+
}()
279390
}
280391

281392
managedCNI, defaultCNI, ksctlCNI, defaultKsctl, err := metaClient.ListManagedCNIs()

cmd/handle_meta.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func (k *KsctlCommand) baseMetadataFields(m *controller.Metadata) {
6363
}
6464
}
6565

66-
func (k *KsctlCommand) handleRegionSelection(meta *controllerMeta.Controller, m *controller.Metadata) {
66+
func (k *KsctlCommand) handleRegionSelection(meta *controllerMeta.Controller, m *controller.Metadata) []provider.RegionOutput {
6767
ss := k.menuDriven.GetProgressAnimation()
6868
ss.Start("Fetching the region list")
6969

@@ -80,6 +80,8 @@ func (k *KsctlCommand) handleRegionSelection(meta *controllerMeta.Controller, m
8080
} else {
8181
m.Region = v
8282
}
83+
84+
return listOfRegions
8385
}
8486

8587
func (k *KsctlCommand) handleInstanceCategorySelection() provider.MachineCategory {

0 commit comments

Comments
 (0)