package main import ( "context" "fmt" "sort" "github.com/UpCloudLtd/upcloud-go-api/v8/upcloud" "github.com/UpCloudLtd/upcloud-go-api/v8/upcloud/service" "github.com/charmbracelet/huh" ) // pickZone fetches available zones from the UpCloud API and presents an // interactive selector. Only public zones are shown. func pickZone(ctx context.Context, svc *service.Service) (string, error) { resp, err := svc.GetZones(ctx) if err != nil { return "", fmt.Errorf("fetch zones: %w", err) } var opts []huh.Option[string] for _, z := range resp.Zones { if z.Public != upcloud.True { continue } label := fmt.Sprintf("%s — %s", z.ID, z.Description) opts = append(opts, huh.NewOption(label, z.ID)) } if len(opts) == 0 { return "", fmt.Errorf("no public zones available") } sort.Slice(opts, func(i, j int) bool { return opts[i].Value < opts[j].Value }) var zone string err = huh.NewSelect[string](). Title("Select a zone"). Options(opts...). Value(&zone). Run() if err != nil { return "", err } return zone, nil } // pickPlan fetches available plans from the UpCloud API and presents an // interactive selector. GPU plans are filtered out. func pickPlan(ctx context.Context, svc *service.Service) (string, error) { resp, err := svc.GetPlans(ctx) if err != nil { return "", fmt.Errorf("fetch plans: %w", err) } var opts []huh.Option[string] for _, p := range resp.Plans { if p.GPUAmount > 0 { continue } memGB := p.MemoryAmount / 1024 label := fmt.Sprintf("%s — %d CPU, %d GB RAM, %d GB disk", p.Name, p.CoreNumber, memGB, p.StorageSize) opts = append(opts, huh.NewOption(label, p.Name)) } if len(opts) == 0 { return "", fmt.Errorf("no plans available") } sort.Slice(opts, func(i, j int) bool { return opts[i].Value < opts[j].Value }) var plan string err = huh.NewSelect[string](). Title("Select a plan"). Options(opts...). Value(&plan). Run() if err != nil { return "", err } return plan, nil }