diff --git a/internal/pkg/services/ske/utils/utils.go b/internal/pkg/services/ske/utils/utils.go index 605ca4158..904ff97a1 100644 --- a/internal/pkg/services/ske/utils/utils.go +++ b/internal/pkg/services/ske/utils/utils.go @@ -6,6 +6,7 @@ import ( "maps" "os" "path/filepath" + "regexp" "strconv" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -16,13 +17,9 @@ import ( ) const ( - defaultNodepoolAvailabilityZone = "eu01-3" defaultNodepoolCRI = ske.CRINAME_CONTAINERD - defaultNodepoolMachineType = "b1.2" defaultNodepoolMachineImageName = "flatcar" - defaultNodepoolMaxSurge = 1 defaultNodepoolMaxUnavailable = 0 - defaultNodepoolMaximum = 2 defaultNodepoolMinimum = 1 defaultNodepoolName = "pool-default" defaultNodepoolVolumeType = "storage_premium_perf2" @@ -110,22 +107,38 @@ func getDefaultPayloadKubernetes(resp *ske.ProviderOptions) (*ske.Kubernetes, er } func getDefaultPayloadNodepool(resp *ske.ProviderOptions) (*ske.Nodepool, error) { + if resp.AvailabilityZones == nil || len(*resp.AvailabilityZones) == 0 { + return nil, fmt.Errorf("no availability zones found") + } + var availabilityZones []string + for i := range *resp.AvailabilityZones { + azName := (*resp.AvailabilityZones)[i].GetName() + // don't include availability zones like eu01-m, eu02-m, not all flavors are available there + if !regexp.MustCompile(`\w{2}\d{2}-m`).MatchString(azName) { + availabilityZones = append(availabilityZones, azName) + } + } + + if resp.MachineTypes == nil || len(*resp.MachineTypes) == 0 { + return nil, fmt.Errorf("no machine types found") + } + machineType := (*resp.MachineTypes)[0].GetName() + output := &ske.Nodepool{ - AvailabilityZones: &[]string{ - defaultNodepoolAvailabilityZone, - }, + AvailabilityZones: &availabilityZones, Cri: &ske.CRI{ Name: utils.Ptr(defaultNodepoolCRI), }, Machine: &ske.Machine{ - Type: utils.Ptr(defaultNodepoolMachineType), + Type: &machineType, Image: &ske.Image{ Name: utils.Ptr(defaultNodepoolMachineImageName), }, }, - MaxSurge: utils.Ptr(int64(defaultNodepoolMaxSurge)), + // there must be as many nodes as availability zones are given + MaxSurge: utils.Ptr(int64(len(availabilityZones))), MaxUnavailable: utils.Ptr(int64(defaultNodepoolMaxUnavailable)), - Maximum: utils.Ptr(int64(defaultNodepoolMaximum)), + Maximum: utils.Ptr(int64(len(availabilityZones))), Minimum: utils.Ptr(int64(defaultNodepoolMinimum)), Name: utils.Ptr(defaultNodepoolName), Volume: &ske.Volume{ diff --git a/internal/pkg/services/ske/utils/utils_test.go b/internal/pkg/services/ske/utils/utils_test.go index 917d590ae..b150509ec 100644 --- a/internal/pkg/services/ske/utils/utils_test.go +++ b/internal/pkg/services/ske/utils/utils_test.go @@ -146,6 +146,17 @@ func TestClusterExists(t *testing.T) { func fixtureProviderOptions(mods ...func(*ske.ProviderOptions)) *ske.ProviderOptions { providerOptions := &ske.ProviderOptions{ + AvailabilityZones: &[]ske.AvailabilityZone{ + {Name: utils.Ptr("eu01-m")}, + {Name: utils.Ptr("eu01-1")}, + {Name: utils.Ptr("eu01-2")}, + {Name: utils.Ptr("eu01-3")}, + }, + MachineTypes: &[]ske.MachineType{ + { + Name: utils.Ptr("b1.2"), + }, + }, KubernetesVersions: &[]ske.KubernetesVersion{ { State: utils.Ptr("supported"), @@ -263,6 +274,8 @@ func fixtureGetDefaultPayload(mods ...func(*ske.CreateOrUpdateClusterPayload)) * Nodepools: &[]ske.Nodepool{ { AvailabilityZones: &[]string{ + "eu01-1", + "eu01-2", "eu01-3", }, Cri: &ske.CRI{ @@ -275,9 +288,9 @@ func fixtureGetDefaultPayload(mods ...func(*ske.CreateOrUpdateClusterPayload)) * Name: utils.Ptr("flatcar"), }, }, - MaxSurge: utils.Ptr(int64(1)), + MaxSurge: utils.Ptr(int64(3)), MaxUnavailable: utils.Ptr(int64(0)), - Maximum: utils.Ptr(int64(2)), + Maximum: utils.Ptr(int64(3)), Minimum: utils.Ptr(int64(1)), Name: utils.Ptr("pool-default"), Volume: &ske.Volume{ @@ -312,6 +325,34 @@ func TestGetDefaultPayload(t *testing.T) { listProviderOptionsFails: true, isValid: false, }, + { + description: "availability zones nil", + listProviderOptionsResp: fixtureProviderOptions(func(po *ske.ProviderOptions) { + po.AvailabilityZones = nil + }), + isValid: false, + }, + { + description: "no availability zones", + listProviderOptionsResp: fixtureProviderOptions(func(po *ske.ProviderOptions) { + po.AvailabilityZones = &[]ske.AvailabilityZone{} + }), + isValid: false, + }, + { + description: "machine types nil", + listProviderOptionsResp: fixtureProviderOptions(func(po *ske.ProviderOptions) { + po.MachineTypes = nil + }), + isValid: false, + }, + { + description: "no machine types", + listProviderOptionsResp: fixtureProviderOptions(func(po *ske.ProviderOptions) { + po.MachineTypes = &[]ske.MachineType{} + }), + isValid: false, + }, { description: "no Kubernetes versions 1", listProviderOptionsResp: fixtureProviderOptions(func(po *ske.ProviderOptions) {