Files
2026-02-07 22:45:10 -06:00

89 lines
1.9 KiB
Go

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
}