From f5279f40daa60aa77593ff8fabc52d297801bb66 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:47:40 +0200 Subject: [PATCH] feat(datacenter, server-type): Move available and recommended to server_type --- .../manual/hcloud_server-type_list.md | 2 ++ internal/cmd/datacenter/describe.go | 5 +++ internal/cmd/datacenter/describe_test.go | 3 -- internal/cmd/servertype/describe.go | 7 ++-- internal/cmd/servertype/describe_test.go | 6 +++- internal/cmd/servertype/list.go | 36 ++++++++++++------- internal/cmd/servertype/list_test.go | 13 +++---- 7 files changed, 47 insertions(+), 25 deletions(-) diff --git a/docs/reference/manual/hcloud_server-type_list.md b/docs/reference/manual/hcloud_server-type_list.md index 5e705a3b0..e44803de9 100644 --- a/docs/reference/manual/hcloud_server-type_list.md +++ b/docs/reference/manual/hcloud_server-type_list.md @@ -21,6 +21,8 @@ Columns: - id - included_traffic - location + - location_available + - location_recommended - memory - name - storage_type diff --git a/internal/cmd/datacenter/describe.go b/internal/cmd/datacenter/describe.go index 48b635c7a..36b135bbd 100644 --- a/internal/cmd/datacenter/describe.go +++ b/internal/cmd/datacenter/describe.go @@ -49,6 +49,11 @@ func DescribeDatacenter(client hcapi2.Client, datacenter *hcloud.Datacenter, sho fmt.Fprintf(&sb, "Location:\n") fmt.Fprint(&sb, util.PrefixLines(location.DescribeLocation(datacenter.Location), " ")) + // datacenter.ServerTypes will not be populated anymore after 2026-10-01. + if dst := datacenter.ServerTypes; dst.Available == nil && dst.Supported == nil && dst.AvailableForMigration == nil { + return sb.String() + } + type ServerTypeStatus struct { ID int64 Available bool diff --git a/internal/cmd/datacenter/describe_test.go b/internal/cmd/datacenter/describe_test.go index 58b770240..3e28478e2 100644 --- a/internal/cmd/datacenter/describe_test.go +++ b/internal/cmd/datacenter/describe_test.go @@ -43,9 +43,6 @@ Location: City: Latitude: 0.000000 Longitude: 0.000000 - -Server Types: - No Server Types ` require.NoError(t, err) diff --git a/internal/cmd/servertype/describe.go b/internal/cmd/servertype/describe.go index 43f808d19..a777204de 100644 --- a/internal/cmd/servertype/describe.go +++ b/internal/cmd/servertype/describe.go @@ -65,6 +65,8 @@ func DescribeServerType(s state.State, serverType *hcloud.ServerType, short bool for _, info := range locations { fmt.Fprintf(&sb, " - Location:\t%s\n", info.Location.Name) + fmt.Fprintf(&sb, " Available:\t%s\n", util.YesNo(info.Available)) + fmt.Fprintf(&sb, " Recommended:\t%s\n", util.YesNo(info.Recommended)) if deprecationText := util.DescribeDeprecation(info); deprecationText != "" { fmt.Fprint(&sb, util.PrefixLines(deprecationText, " ")) @@ -97,8 +99,7 @@ func fullPricingInfo(s state.State, serverType *hcloud.ServerType) ([]hcloud.Ser } type locationInfo struct { - Location *hcloud.Location - hcloud.DeprecatableResource + *hcloud.ServerTypeLocation Pricing hcloud.ServerTypeLocationPricing } @@ -106,7 +107,7 @@ func joinLocationInfo(serverType *hcloud.ServerType, pricings []hcloud.ServerTyp locations := make([]locationInfo, 0, len(serverType.Locations)) for _, location := range serverType.Locations { - info := locationInfo{Location: location.Location, DeprecatableResource: location.DeprecatableResource} + info := locationInfo{ServerTypeLocation: &location} for _, pricing := range pricings { // Pricing endpoint only sets the location name diff --git a/internal/cmd/servertype/describe_test.go b/internal/cmd/servertype/describe_test.go index 59895d4de..b2b094d80 100644 --- a/internal/cmd/servertype/describe_test.go +++ b/internal/cmd/servertype/describe_test.go @@ -44,6 +44,8 @@ func TestDescribe(t *testing.T) { { Location: &hcloud.Location{Name: "fsn1"}, DeprecatableResource: deprecation, + Available: true, + Recommended: false, }, }, }, nil, nil) @@ -112,7 +114,9 @@ Disk: 40 GB Storage Type: local Locations: - - Location: fsn1 + - Location: fsn1 + Available: yes + Recommended: no Deprecation: Announced: %s (%s) Unavailable After: %s (%s) diff --git a/internal/cmd/servertype/list.go b/internal/cmd/servertype/list.go index 5c987ca95..bc5a755af 100644 --- a/internal/cmd/servertype/list.go +++ b/internal/cmd/servertype/list.go @@ -2,7 +2,6 @@ package servertype import ( "fmt" - "slices" "strings" "time" @@ -13,7 +12,6 @@ import ( "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" - "github.com/hetznercloud/hcloud-go/v2/hcloud/exp/kit/sliceutil" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) @@ -36,16 +34,20 @@ var ListCmd = &base.ListCmd[*hcloud.ServerType, schema.ServerType]{ AddAllowedFields(&hcloud.ServerType{}). AddFieldFn("location", func(serverType *hcloud.ServerType) string { now := time.Now() - return strings.Join( - sliceutil.Transform( - slices.DeleteFunc( - slices.Clone(serverType.Locations), - func(l hcloud.ServerTypeLocation) bool { return l.IsDeprecated() && l.UnavailableAfter().Before(now) }, - ), - func(l hcloud.ServerTypeLocation) string { return l.Location.Name }, - ), - ",", - ) + return listLocationNames(serverType, func(l hcloud.ServerTypeLocation) bool { + return l.IsDeprecated() && l.UnavailableAfter().Before(now) + }) + }). + AddFieldFn("location_available", func(serverType *hcloud.ServerType) string { + now := time.Now() + return listLocationNames(serverType, func(l hcloud.ServerTypeLocation) bool { + return (l.IsDeprecated() && l.UnavailableAfter().Before(now)) || !l.Available + }) + }). + AddFieldFn("location_recommended", func(serverType *hcloud.ServerType) string { + return listLocationNames(serverType, func(l hcloud.ServerTypeLocation) bool { + return !l.Recommended + }) }). AddFieldAlias("storagetype", "storage type"). AddFieldFn("memory", func(serverType *hcloud.ServerType) string { @@ -79,3 +81,13 @@ var ListCmd = &base.ListCmd[*hcloud.ServerType, schema.ServerType]{ Schema: hcloud.SchemaFromServerType, } + +func listLocationNames(serverType *hcloud.ServerType, del func(hcloud.ServerTypeLocation) bool) string { + var locationNames []string + for _, l := range serverType.Locations { + if !del(l) { + locationNames = append(locationNames, l.Location.Name) + } + } + return strings.Join(locationNames, ", ") +} diff --git a/internal/cmd/servertype/list_test.go b/internal/cmd/servertype/list_test.go index 148f211d5..651ee291d 100644 --- a/internal/cmd/servertype/list_test.go +++ b/internal/cmd/servertype/list_test.go @@ -46,17 +46,18 @@ func TestList(t *testing.T) { Disk: 80, StorageType: hcloud.StorageTypeLocal, Locations: []hcloud.ServerTypeLocation{ - {Location: &hcloud.Location{ID: 1, Name: "fsn1"}, DeprecatableResource: serverTypeDeprecation}, - {Location: &hcloud.Location{ID: 2, Name: "nbg1"}}, - {Location: &hcloud.Location{ID: 3, Name: "hel1"}}, + {Location: &hcloud.Location{ID: 1, Name: "fsn1"}, Available: false, Recommended: false, + DeprecatableResource: serverTypeDeprecation}, + {Location: &hcloud.Location{ID: 2, Name: "nbg1"}, Available: true, Recommended: false}, + {Location: &hcloud.Location{ID: 3, Name: "hel1"}, Available: true, Recommended: true}, }, }, }, nil) - out, errOut, err := fx.Run(cmd, []string{}) + out, errOut, err := fx.Run(cmd, []string{"-o=columns=id,name,cores,cpu_type,architecture,memory,disk,location,location_available,location_recommended"}) - expOut := `ID NAME CORES CPU TYPE ARCHITECTURE MEMORY DISK LOCATION -123 test 2 shared arm 8.0 GB 80 GB nbg1,hel1 + expOut := `ID NAME CORES CPU TYPE ARCHITECTURE MEMORY DISK LOCATION LOCATION AVAILABLE LOCATION RECOMMENDED +123 test 2 shared arm 8.0 GB 80 GB nbg1, hel1 nbg1, hel1 hel1 ` require.NoError(t, err)