Skip to content

Commit 0a4103f

Browse files
phm07apricotejooola
authored
feat(server,primary-ip): deprecate datacenter (#1278)
The `datacenter` attribute is deprecated in the `Primary IPs` and `Servers` API resources and will be removed after 1 July 2026. See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters for more details. The `location` attribute already exists for Servers, and was added for Primary IPs. Therefor the `datacenter` attribute is deprecated in favor of the `location` attribute in the following commands: - `hcloud server create` - `hcloud server describe` - `hcloud server list` - `hcloud primary-ip create` - `hcloud primary-ip describe` - `hcloud primary-ip list` In list commands, the `datacenter` columns is no longer shown by default, and is replaced with the `location` column. --------- Co-authored-by: Julian Tölle <[email protected]> Co-authored-by: Jonas L. <[email protected]>
1 parent 5c66664 commit 0a4103f

File tree

16 files changed

+188
-92
lines changed

16 files changed

+188
-92
lines changed

docs/reference/manual/hcloud_primary-ip_create.md

Lines changed: 10 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/manual/hcloud_server_create.md

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/cmd/all/list_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ func TestListAll(t *testing.T) {
4141
},
4242
},
4343
Created: time.Now().Add(-72 * time.Hour),
44+
Location: &hcloud.Location{Name: "hel1"},
4445
Datacenter: &hcloud.Datacenter{Name: "hel1-dc2"},
4546
},
4647
}, nil)
@@ -236,8 +237,8 @@ func TestListAll(t *testing.T) {
236237

237238
expOut := `SERVERS
238239
---
239-
ID NAME STATUS IPV4 IPV6 PRIVATE NET DATACENTER AGE
240-
123 my server running 192.0.2.1 - - hel1-dc2 3d
240+
ID NAME STATUS IPV4 IPV6 PRIVATE NET LOCATION AGE
241+
123 my server running 192.0.2.1 - - hel1 3d
241242
242243
IMAGES
243244
---

internal/cmd/datacenter/describe.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ func DescribeDatacenter(client hcapi2.Client, datacenter *hcloud.Datacenter, sho
4141
fmt.Fprintf(&sb, "Name:\t%s\n", datacenter.Name)
4242
fmt.Fprintf(&sb, "Description:\t%s\n", datacenter.Description)
4343

44-
fmt.Fprintln(&sb)
45-
fmt.Fprintf(&sb, "Location:\n")
46-
fmt.Fprint(&sb, util.PrefixLines(location.DescribeLocation(datacenter.Location), " "))
47-
4844
if short {
4945
return sb.String()
5046
}
5147

48+
fmt.Fprintln(&sb)
49+
fmt.Fprintf(&sb, "Location:\n")
50+
fmt.Fprint(&sb, util.PrefixLines(location.DescribeLocation(datacenter.Location), " "))
51+
5252
type ServerTypeStatus struct {
5353
ID int64
5454
Available bool

internal/cmd/primaryip/create.go

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package primaryip
22

33
import (
44
"fmt"
5+
"strings"
56

67
"github.com/spf13/cobra"
78

@@ -16,8 +17,12 @@ import (
1617
var CreateCmd = base.CreateCmd[*hcloud.PrimaryIP]{
1718
BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {
1819
cmd := &cobra.Command{
19-
Use: "create [options] --type <ipv4|ipv6> --name <name>",
20-
Short: "Create a Primary IP",
20+
Use: "create [options] --type <ipv4|ipv6> --name <name>",
21+
Short: "Create a Primary IP",
22+
Long: `Create a Primary IP.
23+
24+
The --datacenter flag is deprecated. Use --location or --assignee-id instead.
25+
See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters.`,
2126
TraverseChildren: true,
2227
DisableFlagsInUseLine: true,
2328
}
@@ -28,9 +33,12 @@ var CreateCmd = base.CreateCmd[*hcloud.PrimaryIP]{
2833
cmd.Flags().String("name", "", "Name (required)")
2934
_ = cmd.MarkFlagRequired("name")
3035

31-
cmd.Flags().Int64("assignee-id", 0, "Assignee (usually a Server) to assign Primary IP to (required if 'datacenter' is not specified)")
36+
cmd.Flags().Int64("assignee-id", 0, "Assignee (usually a Server) to assign Primary IP to")
37+
38+
cmd.Flags().String("location", "", "Location (ID or name) of Primary IP")
39+
_ = cmd.RegisterFlagCompletionFunc("location", cmpl.SuggestCandidatesF(client.Location().Names))
3240

33-
cmd.Flags().String("datacenter", "", "Datacenter (ID or name) (required if 'assignee-id' is not specified)")
41+
cmd.Flags().String("datacenter", "", "Datacenter (name) (deprecated)")
3442
_ = cmd.RegisterFlagCompletionFunc("datacenter", cmpl.SuggestCandidatesF(client.Datacenter().Names))
3543

3644
cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)")
@@ -40,15 +48,16 @@ var CreateCmd = base.CreateCmd[*hcloud.PrimaryIP]{
4048

4149
cmd.Flags().Bool("auto-delete", false, "Delete Primary IP if assigned resource is deleted (true, false)")
4250

43-
cmd.MarkFlagsOneRequired("assignee-id", "datacenter")
44-
cmd.MarkFlagsMutuallyExclusive("assignee-id", "datacenter")
51+
cmd.MarkFlagsOneRequired("assignee-id", "datacenter", "location")
52+
cmd.MarkFlagsMutuallyExclusive("assignee-id", "datacenter", "location")
4553
return cmd
4654
},
4755
Run: func(s state.State, cmd *cobra.Command, _ []string) (*hcloud.PrimaryIP, any, error) {
4856
typ, _ := cmd.Flags().GetString("type")
4957
name, _ := cmd.Flags().GetString("name")
5058
assigneeID, _ := cmd.Flags().GetInt64("assignee-id")
5159
datacenter, _ := cmd.Flags().GetString("datacenter")
60+
locationIDOrName, _ := cmd.Flags().GetString("location")
5261
labels, _ := cmd.Flags().GetStringToString("label")
5362
protection, _ := cmd.Flags().GetStringSlice("enable-protection")
5463
autoDelete, _ := cmd.Flags().GetBool("auto-delete")
@@ -62,7 +71,6 @@ var CreateCmd = base.CreateCmd[*hcloud.PrimaryIP]{
6271
Type: hcloud.PrimaryIPType(typ),
6372
Name: name,
6473
AssigneeType: "server",
65-
Datacenter: datacenter,
6674
Labels: labels,
6775
}
6876
if assigneeID != 0 {
@@ -71,6 +79,30 @@ var CreateCmd = base.CreateCmd[*hcloud.PrimaryIP]{
7179
if cmd.Flags().Changed("auto-delete") {
7280
createOpts.AutoDelete = &autoDelete
7381
}
82+
if cmd.Flags().Changed("location") {
83+
location, _, err := s.Client().Location().Get(s, locationIDOrName)
84+
if err != nil {
85+
return nil, nil, err
86+
}
87+
if location == nil {
88+
return nil, nil, fmt.Errorf("Location not found: %s", locationIDOrName)
89+
}
90+
createOpts.Location = location.Name
91+
}
92+
if cmd.Flags().Changed("datacenter") {
93+
cmd.PrintErrln("Warning: The --datacenter flag is deprecated. Use --location or --assignee-id instead.")
94+
95+
// Backward compatible datacenter argument.
96+
// datacenter hel1-dc2 => location hel1
97+
parts := strings.Split(datacenter, "-")
98+
99+
if len(parts) != 2 {
100+
return nil, nil, fmt.Errorf("Datacenter name is not valid, expected format $LOCATION-$DATACENTER, but got: %s", datacenter)
101+
}
102+
103+
locationName := parts[0]
104+
createOpts.Location = locationName
105+
}
74106

75107
result, _, err := s.Client().PrimaryIP().Create(s, createOpts)
76108
if err != nil {

internal/cmd/primaryip/create_test.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func TestCreate(t *testing.T) {
3939
hcloud.PrimaryIPCreateOpts{
4040
Name: "my-ip",
4141
Type: "ipv4",
42-
Datacenter: "fsn1-dc14",
42+
Location: "fsn1",
4343
Labels: map[string]string{"foo": "bar"},
4444
AssigneeType: "server",
4545
AutoDelete: hcloud.Ptr(true),
@@ -62,12 +62,14 @@ func TestCreate(t *testing.T) {
6262

6363
out, errOut, err := fx.Run(cmd, []string{"--name=my-ip", "--type=ipv4", "--datacenter=fsn1-dc14", "--auto-delete", "--label", "foo=bar"})
6464

65+
expErr := "Warning: The --datacenter flag is deprecated. Use --location or --assignee-id instead.\n"
66+
6567
expOut := `Primary IP 1 created
6668
IPv4: 192.168.2.1
6769
`
6870

6971
require.NoError(t, err)
70-
assert.Empty(t, errOut)
72+
assert.Equal(t, expErr, errOut)
7173
assert.Equal(t, expOut, out)
7274
}
7375

@@ -85,6 +87,9 @@ func TestCreateJSON(t *testing.T) {
8587
Name: "my-ip",
8688
IP: net.ParseIP("192.168.2.1"),
8789
Type: "ipv4",
90+
Location: &hcloud.Location{
91+
Name: "fsn1",
92+
},
8893
Datacenter: &hcloud.Datacenter{
8994
ID: 1,
9095
Name: "fsn1-dc14",
@@ -104,7 +109,7 @@ func TestCreateJSON(t *testing.T) {
104109
hcloud.PrimaryIPCreateOpts{
105110
Name: "my-ip",
106111
Type: "ipv4",
107-
Datacenter: "fsn1-dc14",
112+
Location: "fsn1",
108113
Labels: map[string]string{"foo": "bar"},
109114
AssigneeType: "server",
110115
AutoDelete: hcloud.Ptr(true),
@@ -124,7 +129,9 @@ func TestCreateJSON(t *testing.T) {
124129

125130
jsonOut, out, err := fx.Run(cmd, []string{"-o=json", "--name=my-ip", "--type=ipv4", "--datacenter=fsn1-dc14", "--auto-delete", "--label", "foo=bar"})
126131

127-
expOut := "Primary IP 1 created\n"
132+
expOut := `Warning: The --datacenter flag is deprecated. Use --location or --assignee-id instead.
133+
Primary IP 1 created
134+
`
128135

129136
require.NoError(t, err)
130137
assert.Equal(t, expOut, out)

internal/cmd/primaryip/describe.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/hetznercloud/cli/internal/cmd/base"
1111
"github.com/hetznercloud/cli/internal/cmd/datacenter"
12+
"github.com/hetznercloud/cli/internal/cmd/location"
1213
"github.com/hetznercloud/cli/internal/cmd/util"
1314
"github.com/hetznercloud/cli/internal/hcapi2"
1415
"github.com/hetznercloud/cli/internal/state"
@@ -62,8 +63,15 @@ var DescribeCmd = base.DescribeCmd[*hcloud.PrimaryIP]{
6263
util.DescribeLabels(out, primaryIP.Labels, "")
6364

6465
fmt.Fprintln(out)
65-
fmt.Fprintf(out, "Datacenter:\n")
66-
fmt.Fprintf(out, "%s", util.PrefixLines(datacenter.DescribeDatacenter(s.Client(), primaryIP.Datacenter, true), " "))
66+
fmt.Fprintf(out, "Location:\n")
67+
fmt.Fprintf(out, "%s", util.PrefixLines(location.DescribeLocation(primaryIP.Location), " "))
68+
69+
if primaryIP.Datacenter != nil {
70+
fmt.Fprintln(out)
71+
fmt.Fprintf(out, "Datacenter:\n")
72+
fmt.Fprintf(out, "%s", util.PrefixLines(datacenter.DescribeDatacenter(s.Client(), primaryIP.Datacenter, true), " "))
73+
}
74+
6775
return nil
6876
},
6977
}

internal/cmd/primaryip/describe_test.go

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,16 @@ func TestDescribe(t *testing.T) {
3535
Blocked: true,
3636
AutoDelete: false,
3737
AssigneeType: "server",
38-
Datacenter: &hcloud.Datacenter{ID: 0, Location: &hcloud.Location{ID: 0}},
38+
Location: &hcloud.Location{
39+
ID: 3,
40+
Name: "hel1",
41+
Description: "Helsinki DC Park 1",
42+
NetworkZone: "eu-central",
43+
Country: "FI",
44+
City: "Helsinki",
45+
Latitude: 60.169855,
46+
Longitude: 24.938379,
47+
},
3948
}
4049

4150
fx.Client.PrimaryIPClient.EXPECT().
@@ -64,20 +73,15 @@ Protection:
6473
Labels:
6574
No labels
6675
67-
Datacenter:
68-
ID: 0
69-
Name:
70-
Description:
71-
72-
Location:
73-
ID: 0
74-
Name:
75-
Description:
76-
Network Zone:
77-
Country:
78-
City:
79-
Latitude: 0.000000
80-
Longitude: 0.000000
76+
Location:
77+
ID: 3
78+
Name: hel1
79+
Description: Helsinki DC Park 1
80+
Network Zone: eu-central
81+
Country: FI
82+
City: Helsinki
83+
Latitude: 60.169855
84+
Longitude: 24.938379
8185
`, util.Datetime(primaryIP.Created), humanize.Time(primaryIP.Created))
8286

8387
require.NoError(t, err)

internal/cmd/primaryip/testdata/create_response.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"id": 0,
1313
"latitude": 0,
1414
"longitude": 0,
15-
"name": "",
15+
"name": "fsn1",
1616
"network_zone": ""
1717
},
1818
"datacenter": {

internal/cmd/server/change_type.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ var ChangeTypeCmd = base.Cmd{
4747
return fmt.Errorf("Server Type not found: %s", serverTypeIDOrName)
4848
}
4949

50-
cmd.Print(deprecatedServerTypeWarning(serverType, server.Datacenter.Location.Name))
50+
cmd.Print(deprecatedServerTypeWarning(serverType, server.Location.Name))
5151

5252
keepDisk, _ := cmd.Flags().GetBool("keep-disk")
5353
opts := hcloud.ServerChangeTypeOpts{

0 commit comments

Comments
 (0)