diff --git a/.golangci.yml b/.golangci.yml index a868e1483..861d54cff 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -65,7 +65,7 @@ linters: text: var-naming - linters: - staticcheck - text: Datacenter is deprecated + text: (Datacenter is deprecated|\[Datacenter.ServerTypes\] is deprecated) formatters: enable: 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/go.mod b/go.mod index 90426d97f..74790632a 100644 --- a/go.mod +++ b/go.mod @@ -63,3 +63,5 @@ require ( google.golang.org/protobuf v1.36.8 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace github.com/hetznercloud/hcloud-go/v2 => github.com/hetznercloud/hcloud-go/v2 v2.37.1-0.20260410081632-85dd7f3232b8 diff --git a/go.sum b/go.sum index c8da02ff7..a0b6b0744 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/guptarohit/asciigraph v0.9.0 h1:MvCSRRVkT2XvU1IO6n92o7l7zqx1DiFaoszOUZQztbY= github.com/guptarohit/asciigraph v0.9.0/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag= -github.com/hetznercloud/hcloud-go/v2 v2.37.0 h1:PMnuOA8pL8aHLLPp6nnnCTo2Xk2tqu4dAfYsC3bWdT0= -github.com/hetznercloud/hcloud-go/v2 v2.37.0/go.mod h1:zaDOCKmpnI86ftoCpUpaiYaw9Wew1ib1AcXTh96deYI= +github.com/hetznercloud/hcloud-go/v2 v2.37.1-0.20260410081632-85dd7f3232b8 h1:nRdcWLhKcYLnHdi0zl0BdIUpcuAWdB722r6yk0K+ki8= +github.com/hetznercloud/hcloud-go/v2 v2.37.1-0.20260410081632-85dd7f3232b8/go.mod h1:qLL/i7AERTum2JPTXf4Og+hrodL/d8pAnqhgRHeKEXg= github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= diff --git a/internal/cmd/datacenter/describe.go b/internal/cmd/datacenter/describe.go index 48b635c7a..2fdd95118 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/datacenter/list_test.go b/internal/cmd/datacenter/list_test.go index 5afa1c18e..daa7cf03d 100644 --- a/internal/cmd/datacenter/list_test.go +++ b/internal/cmd/datacenter/list_test.go @@ -95,11 +95,6 @@ func TestListJSON(t *testing.T) { "latitude": 0, "longitude": 0, "network_zone": "" - }, - "server_types": { - "supported": null, - "available_for_migration": null, - "available": null } } ]`, out) diff --git a/internal/cmd/primaryip/testdata/create_response.json b/internal/cmd/primaryip/testdata/create_response.json index 9633d15e7..383bf1e23 100644 --- a/internal/cmd/primaryip/testdata/create_response.json +++ b/internal/cmd/primaryip/testdata/create_response.json @@ -28,12 +28,7 @@ "name": "fsn1", "network_zone": "" }, - "name": "fsn1-dc14", - "server_types": { - "available": null, - "available_for_migration": null, - "supported": null - } + "name": "fsn1-dc14" }, "dns_ptr": [], "id": 1, diff --git a/internal/cmd/server/testdata/create_response.json b/internal/cmd/server/testdata/create_response.json index 1743855d1..4ab6d7a91 100644 --- a/internal/cmd/server/testdata/create_response.json +++ b/internal/cmd/server/testdata/create_response.json @@ -26,12 +26,7 @@ "name": "fsn1", "network_zone": "" }, - "name": "fsn1-dc14", - "server_types": { - "available": null, - "available_for_migration": null, - "supported": null - } + "name": "fsn1-dc14" }, "id": 1234, "image": { @@ -111,8 +106,8 @@ "prices": null, "storage_type": "local", "locations": [ - { "id": 1, "name": "fsn1", "deprecation": null }, - { "id": 2, "name": "nbg1", "deprecation": null } + { "id": 1, "name": "fsn1", "deprecation": null, "available": false, "recommended": false }, + { "id": 2, "name": "nbg1", "deprecation": null, "available": false, "recommended": false } ] }, "status": "running", 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..baf48fa5a 100644 --- a/internal/cmd/servertype/list.go +++ b/internal/cmd/servertype/list.go @@ -37,13 +37,26 @@ var ListCmd = &base.ListCmd[*hcloud.ServerType, schema.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 }, - ), + 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 strings.Join( + 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 strings.Join( + listLocationNames(serverType, func(l hcloud.ServerTypeLocation) bool { + return !l.Recommended + }), ",", ) }). @@ -79,3 +92,10 @@ var ListCmd = &base.ListCmd[*hcloud.ServerType, schema.ServerType]{ Schema: hcloud.SchemaFromServerType, } + +func listLocationNames(serverType *hcloud.ServerType, del func(hcloud.ServerTypeLocation) bool) []string { + return sliceutil.Transform( + slices.DeleteFunc(slices.Clone(serverType.Locations), del), + func(l hcloud.ServerTypeLocation) string { return l.Location.Name }, + ) +} diff --git a/internal/cmd/servertype/list_test.go b/internal/cmd/servertype/list_test.go index 148f211d5..2c8fa301e 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)